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}不再支持!" }