Cw 473 exchange refactoring (#1126)

* CW-473 Remove deprecated Exchanges

* CW-473 Clean up Exchange Code

* CW-473 Add Decimals to Crypto Enums

* CW-473 Fix minor merge error

* CW-473 Fix minor merge error

* CW-473 Fix FAQ Locals

* CW-473 Apply requested changes

* CW-473 Show Error if Exchange Provider is not supported anymore

* CW-473 Implement Requested Changes
This commit is contained in:
Konstantin Ullrich 2023-10-25 22:58:25 +02:00 committed by GitHub
parent db7f025b71
commit cef3029f6f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
74 changed files with 941 additions and 1783 deletions

View file

@ -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"
}
]
]

View file

@ -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"
}
]
]

View file

@ -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"
}
]
]

View file

@ -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 ?",

View file

@ -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"
}
]
]

View file

@ -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"
}
]
]

View file

@ -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"
}
]
]

View file

@ -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"
}
]
]

View file

@ -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"
}
]
]

View file

@ -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"
}
]
]

View file

@ -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"
}
]
]

View file

@ -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"
}
]
]

View file

@ -49,10 +49,10 @@
},
{
"question" : "我没有从应用程序中的交易所收到硬币。 我能做什么?",
"answer" : "如果您对交易所有疑问,最好的选择是与交易所本身联系。 我们与XMR.TOMorph和ChangeNow合作因此最好的选择是访问http//xmr.to、http//changenow.io或http://morphtoken.com并与他们的支持部门联系。\n"
"answer" : "如果您对交易所有问题最好的选择是与交易所本身联系。我们与ChangeNowSimplesWapSideShift和Trocador合作。因此最好的选择是访问https://changenow.iohttps://simpleswap.io/https://sideshift.ai/https//trocador.app/并联系他们的支持。\n"
},
{
"question" : "如何联系蛋糕钱包支持?",
"answer" : "电子邮件support@cakewallet.com通过@cakewallet_bot加入电报或在@CakeWalletXMR上发布推文\n"
}
]
]

View file

@ -6,6 +6,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> 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<int> with Serializable<int> 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<int> with Serializable<int> 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<int, CryptoCurrency> _rawCurrencyMap =
@ -223,7 +225,6 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> 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<int> with Serializable<int> 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<int> with Serializable<int> 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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -14,16 +14,12 @@ class ExchangeProviderDescription extends EnumerableItem<int> 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');

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -1,6 +1,6 @@
class Limits {
const Limits({this.min, this.max});
final double? min;
final double? max;
}
}

View file

@ -1,4 +1,3 @@
import 'package:flutter/foundation.dart';
import 'package:cake_wallet/exchange/limits.dart';
abstract class LimitsState {}

View file

@ -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<Trade> 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<bool> checkIsAvailable() async => true;
@override
Future<Limits> 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<String, dynamic>;
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<Trade> 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<String, dynamic>;
final error = responseJSON['description'] as String;
throw TradeNotCreatedException(description, description: error);
}
throw TradeNotCreatedException(description);
}
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
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<Trade> 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<String, dynamic>;
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<String, dynamic>;
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<double> 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<String, dynamic>;
final rate = responseJSON['data'][from.toString()][to.toString()] as String;
try {
final estimatedAmount = double.parse(rate) * amount;
return estimatedAmount;
} catch (_) {
return 0.0;
}
}
}

View file

@ -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;
}

View file

@ -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<CryptoCurrency> _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<bool> checkIsAvailable() async => true;
final SettingsStore settingsStore;
String _lastUsedRateId;
static String getFlow(bool isFixedRate) => isFixedRate ? 'fixed-rate' : 'standard';
@override
Future<Limits> fetchLimits(
{required CryptoCurrency from,
required CryptoCurrency to,
required bool isFixedRateMode}) async {
final headers = {apiHeaderKey: apiKey};
final flow = getFlow(isFixedRateMode);
final params = <String, String>{
'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<String, dynamic>;
return Limits(
min: responseJSON['minAmount'] as double?, max: responseJSON['maxAmount'] as double?);
}
@override
Future<double> 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 = <String, String>{
'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<String, dynamic>;
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<Trade> 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 = <String, dynamic>{
'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<String, dynamic>;
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<String, dynamic>;
@ -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<String, dynamic>;
final fromCurrency = responseJSON['fromCurrency'] as String;
@ -222,54 +253,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
payoutAddress: payoutAddress);
}
@override
Future<double> 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 = <String, String>{
'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<String, dynamic>;
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();
}
}
}
}

View file

@ -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<ExchangePair> pairList;
ExchangeProviderDescription get description;
bool get isAvailable;
bool get isEnabled;
bool get supportsFixedRate;
bool get supportsOnionAddress => false;
@override
String toString() => title;
Future<Limits> fetchLimits(
{required CryptoCurrency from, required CryptoCurrency to, required bool isFixedRateMode});
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode});
Future<Trade> findTradeById({required String id});
Future<double> fetchRate(
{required CryptoCurrency from,
required CryptoCurrency to,
required bool isFixedRateMode});
Future<Trade> createTrade({
required TradeRequest request,
required bool isFixedRateMode});
Future<Trade> findTradeById({required String id});
Future<double> 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<bool> checkIsAvailable();
}

View file

@ -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<ExchangePair> _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<bool> checkIsAvailable() async => true;
static String getRateType(bool isFixedRate) => isFixedRate ? 'fixed' : 'float';
@override
Future<Limits> fetchLimits(
{required CryptoCurrency from,
required CryptoCurrency to,
required bool isFixedRateMode}) async {
final params = <String, String>{
'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<String, dynamic>;
return Limits(min: responseJSON['minAmount'] as double?);
}
@override
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
final _request = request as ExolixRequest;
Future<double> 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<String, dynamic>;
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<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
final headers = {'Content-Type': 'application/json'};
final body = <String, dynamic>{
'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<String, dynamic>;
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<Trade> 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<String, dynamic>;
@ -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<String, dynamic>;
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<double> 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 = <String, String>{
'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<String, dynamic>;
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) {

View file

@ -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<CryptoCurrency> _notSupported = [
CryptoCurrency.xhv,
@ -39,49 +31,28 @@ class SideShiftExchangeProvider extends ExchangeProvider {
CryptoCurrency.eos,
];
static List<ExchangePair> _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<double> 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<String, dynamic>;
final rate = double.parse(responseJSON['rate'] as String);
return rate;
} catch (_) {
return 0.00;
}
}
@override
Future<bool> 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<String, dynamic>;
final cancreateShift = responseJSON['createShift'] as bool;
return cancreateShift;
}
@override
Future<Trade> 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<String, dynamic>;
final error = responseJSON['error']['message'] as String;
throw TradeNotCreatedException(description, description: error);
}
throw TradeNotCreatedException(description);
}
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
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<String> _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<String, dynamic>;
final error = responseJSON['error']['message'] as String;
throw TradeNotCreatedException(description, description: error);
}
throw TradeNotCreatedException(description);
}
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
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<double> 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<String, dynamic>;
return double.parse(responseJSON['rate'] as String);
} catch (_) {
return 0.00;
}
}
@override
Future<Trade> 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<String, dynamic>;
final error = responseJSON['error']['message'] as String;
throw TradeNotCreatedException(description, description: error);
}
throw TradeNotCreatedException(description);
}
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
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<Trade> 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<String, dynamic>;
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<String> _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<String, dynamic>;
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<String, dynamic>;
return responseJSON['id'] as String;
}
String _networkFor(CryptoCurrency currency) =>
currency.tag != null ? _normalizeTag(currency.tag!) : 'mainnet';

View file

@ -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<CryptoCurrency> _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<double> 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 = <String, String>{
'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<bool> checkIsAvailable() async {
@ -76,20 +54,79 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
}
@override
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
final _request = request as SimpleSwapRequest;
final headers = {
'Content-Type': 'application/json'};
final params = <String, String>{
Future<Limits> fetchLimits(
{required CryptoCurrency from,
required CryptoCurrency to,
required bool isFixedRateMode}) async {
final params = <String, dynamic>{
'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<String, dynamic>;
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<String, dynamic>;
final min = double.tryParse(responseJSON['min'] as String? ?? '');
final max = double.tryParse(responseJSON['max'] as String? ?? '');
return Limits(min: min, max: max);
}
@override
Future<double> 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<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
final headers = {'Content-Type': 'application/json'};
final params = {'api_key': apiKey};
final body = <String, dynamic>{
"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<Limits> fetchLimits({
required CryptoCurrency from,
required CryptoCurrency to,
required bool isFixedRateMode}) async {
final fromCurrency = _normalizeCryptoCurrency(from);
final toCurrency = _normalizeCryptoCurrency(to);
final params = <String, dynamic>{
'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<String, dynamic>;
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<String, dynamic>;
final min = double.tryParse(responseJSON['min'] as String? ?? '');
final max = double.tryParse(responseJSON['max'] as String? ?? '');
return Limits(min: min, max: max);
}
@override
Future<Trade> 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<String, dynamic>;
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';

View file

@ -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<ExchangePair> _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<bool> checkIsAvailable() async => true;
String get title => 'Trocador';
@override
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) {
final _request = request as TrocadorRequest;
return _createTrade(request: _request, isFixedRateMode: isFixedRateMode);
}
bool get isAvailable => true;
Future<Trade> _createTrade({
required TrocadorRequest request,
required bool isFixedRateMode,
}) async {
final params = <String, String>{
'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<String, dynamic>;
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<String, dynamic>;
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<bool> checkIsAvailable() async => true;
@override
Future<Limits> fetchLimits(
{required CryptoCurrency from,
required CryptoCurrency to,
required bool isFixedRateMode}) async {
final params = <String, String>{
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<dynamic>;
if (responseJSON.isEmpty) {
throw Exception('No data');
}
if (responseJSON.isEmpty) throw Exception('No data');
final coinJson = responseJSON.first as Map<String, dynamic>;
@ -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 = <String, String>{
'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<Trade> 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<String, dynamic>;
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<String, dynamic>;
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<Trade> 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<Uri> _getUri(String path, Map<String, String> 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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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';
}

View file

@ -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';
}

View file

@ -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;
}
}

View file

@ -1 +1,20 @@
abstract class TradeRequest {}
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;
}

View file

@ -1,9 +1,7 @@
import 'package:flutter/foundation.dart';
import 'package:cw_core/enumerable_item.dart';
class TradeState extends EnumerableItem<String> with Serializable<String> {
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<String> with Serializable<String> {
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<String> with Serializable<String> {
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');

View file

@ -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;
}

View file

@ -0,0 +1,12 @@
import 'package:cake_wallet/exchange/exchange_pair.dart';
import 'package:cw_core/crypto_currency.dart';
List<ExchangePair> supportedPairs(List<CryptoCurrency> 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();
}

View file

@ -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<bool> _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<bool> checkIsAvailable() async {
_isAvailable = await _checkIsAvailable();
return isAvailable;
}
@override
Future<Limits> 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<String, dynamic>;
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<Trade> 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<String, dynamic>;
final error = responseJSON['error_msg'] as String;
throw TradeNotCreatedException(description, description: error);
}
throw TradeNotCreatedException(description);
}
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
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<Trade> 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<String, dynamic>;
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<String, dynamic>;
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<double> 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<double> _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<String, dynamic>;
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));
}

View file

@ -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;
}

View file

@ -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: <Widget>[
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<ExchangePageTheme>()!.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<ExchangePageTheme>()!
.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) {

View file

@ -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<TradeDetailsPageBody> {
@ -51,7 +50,7 @@ class TradeDetailsPageBodyState extends State<TradeDetailsPageBody> {
@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<TradeDetailsPageBody> {
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<void>(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<void>(context, S.of(context).copied_to_clipboard);
},
child: ListRow(title: '${item.title}', value: '${item.value}'));
});
});
}
}

View file

@ -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);
}

View file

@ -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<ExchangeTradeItem>() {
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<void> 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;

View file

@ -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<Trade> 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<void> 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<void> 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<ExchangeProvider> providersForCurrentPair() {
return _providersForPair(from: depositCurrency, to: receiveCurrency);
}
List<ExchangeProvider> providersForCurrentPair() =>
_providersForPair(from: depositCurrency, to: receiveCurrency);
List<ExchangeProvider> _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;
}

View file

@ -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<Trade> 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)));
}
}

View file

@ -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} لم يعد مدعومًا!"
}

View file

@ -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} вече не се поддържа!"
}

View file

@ -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!"
}

View file

@ -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!"
}

View file

@ -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!"
}

View file

@ -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!"
}

View file

@ -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!"
}

View file

@ -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}"
}

View file

@ -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} अब समर्थित नहीं है!"
}

View file

@ -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!"
}

View file

@ -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!"
}

View file

@ -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!"
}

View file

@ -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}はサポートされなくなりました!"
}

View file

@ -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}은 더 이상 지원되지 않습니다!"
}

View file

@ -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} မရှိတော့ပါ!"
}

View file

@ -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!"
}

View file

@ -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!"
}

View file

@ -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!"
}

View file

@ -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} больше не поддерживается!"
}

View file

@ -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} ไม่ได้รับการสนับสนุนอีกต่อไป!"
}

View file

@ -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!"
}

View file

@ -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!"
}

View file

@ -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} більше не підтримується!"
}

View file

@ -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} اب تعاون نہیں کیا جاتا ہے!"
}

View file

@ -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ọ!"
}

View file

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