mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-26 06:08:40 +01:00
Merge branch 'dev' into cw-1440-new-buy-sell-flow
This commit is contained in:
@@ -1 +1 @@
|
||||
[{"title":"تحسينات زي كاش","description":"بعد الترحيل الناجح إلى IronWood الجديد، أضفنا المزيد من التحسينات إلى محفظة zcash"},{"title":"AnyPay على النحو المنشود","description":"الآن، سيؤدي لصق عنوان ما أو مسحه ضوئيًا من أي محفظة إلى توجيهك بشكل صحيح إما للتبديل أو الإرسال من المحفظة الصحيحة، والمزيد من التحسينات"},{"title":"تحسينات واجهة المستخدم","description":"تمت إضافة بعض عناصر واجهة المستخدم الجديدة خصيصًا لك"},{"title":"إصلاحات الشوائب","description":"سحق المزيد من الأخطاء"}]
|
||||
[{"title":"تحسينات AnyPay","description":"الآن، سيؤدي لصق عنوان ما أو مسحه ضوئيًا من أي محفظة إلى توجيهك بشكل صحيح إما للتبديل أو الإرسال من المحفظة الصحيحة، والمزيد من التحسينات"},{"title":"تحسينات واجهة المستخدم","description":"تمت إضافة بعض عناصر واجهة المستخدم الجديدة خصيصًا لك"},{"title":"إصلاحات الشوائب","description":"سحق المزيد من الأخطاء"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Подобрения на Zcash","description":"След успешната миграция към новия IronWood добавихме още подобрения към zcash портфейла"},{"title":"AnyPay според предназначението","description":"Сега поставянето или сканирането на адрес от който и да е портфейл ще ви насочи правилно към размяна или изпращане от правилния портфейл и много повече подобрения"},{"title":"Подобрения на потребителския интерфейс","description":"Добавени са някои нови елементи на потребителския интерфейс само за вас"},{"title":"Поправки на грешки","description":"Смачкани още грешки"}]
|
||||
[{"title":"Подобрения на AnyPay","description":"Сега поставянето или сканирането на адрес от който и да е портфейл ще ви насочи правилно към размяна или изпращане от правилния портфейл и много повече подобрения"},{"title":"Подобрения на потребителския интерфейс","description":"Добавени са някои нови елементи на потребителския интерфейс само за вас"},{"title":"Поправки на грешки","description":"Смачкани още грешки"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Zcash vylepšení","description":"Po úspěšné migraci na nový IronWood jsme přidali další vylepšení do zcash peněženky"},{"title":"AnyPay, jak bylo zamýšleno","description":"Nyní vložení nebo skenování adresy z libovolné peněženky vás správně nasměruje buď na výměnu nebo odeslání ze správné peněženky, a k mnoha dalším vylepšením"},{"title":"vylepšení uživatelského rozhraní","description":"Přidali jsme několik nových prvků uživatelského rozhraní jen pro vás"},{"title":"Opravy chyb","description":"Rozdrtil více brouků"}]
|
||||
[{"title":"Vylepšení AnyPay","description":"Nyní vložení nebo skenování adresy z libovolné peněženky vás správně nasměruje buď na výměnu nebo odeslání ze správné peněženky, a k mnoha dalším vylepšením"},{"title":"vylepšení uživatelského rozhraní","description":"Přidali jsme několik nových prvků uživatelského rozhraní jen pro vás"},{"title":"Opravy chyb","description":"Zmáčkl další brouky"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Zcash-Verbesserungen","description":"Nach der erfolgreichen Migration auf das neue IronWood haben wir weitere Verbesserungen an der Zcash-Wallet vorgenommen"},{"title":"AnyPay wie vorgesehen","description":"Wenn Sie nun eine Adresse aus einem beliebigen Wallet einfügen oder scannen, werden Sie direkt zum Tauschen oder Senden von dem richtigen Wallet weitergeleitet und es gibt noch viele weitere Verbesserungen"},{"title":"Verbesserungen der Benutzeroberfläche","description":"Einige neue UI-Elemente wurden speziell für Sie hinzugefügt"},{"title":"Fehlerbehebungen","description":"Weitere Bugs beseitigt"}]
|
||||
[{"title":"AnyPay-Verbesserungen","description":"Wenn Sie jetzt eine Adresse aus einem beliebigen Wallet einfügen oder scannen, werden Sie direkt zum Tauschen oder Senden von dem richtigen Wallet weitergeleitet und es gibt noch viele weitere Verbesserungen"},{"title":"Verbesserungen der Benutzeroberfläche","description":"Einige neue UI-Elemente wurden speziell für Sie hinzugefügt"},{"title":"Fehlerbehebungen","description":"Weitere Bugs beseitigt"}]
|
||||
@@ -1,10 +1,6 @@
|
||||
[
|
||||
{
|
||||
"title": "Zcash improvements",
|
||||
"description": "After the successful migration to the new IronWood, we added more improvements to zcash wallet"
|
||||
},
|
||||
{
|
||||
"title": "AnyPay as Intended",
|
||||
"title": "AnyPay Improvements",
|
||||
"description": "Now pasting or scanning an address from any wallet will point you correctly to either swapping or sending from the correct wallet, and much more improvements"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Mejoras en Zcash","description":"Después de la migración exitosa al nuevo IronWood, agregamos más mejoras a la billetera zcash"},{"title":"AnyPay según lo previsto","description":"Ahora, pegar o escanear una dirección desde cualquier billetera le indicará correctamente si desea intercambiar o enviar desde la billetera correcta, y muchas más mejoras."},{"title":"Mejoras en la interfaz de usuario","description":"Se agregaron algunos elementos nuevos de la interfaz de usuario solo para ti."},{"title":"Corrección de errores","description":"Aplastado más errores"}]
|
||||
[{"title":"Mejoras en cualquier pago","description":"Ahora, pegar o escanear una dirección desde cualquier billetera le indicará correctamente si desea intercambiar o enviar desde la billetera correcta, y muchas más mejoras."},{"title":"Mejoras en la interfaz de usuario","description":"Se agregaron algunos elementos nuevos de la interfaz de usuario solo para ti."},{"title":"Corrección de errores","description":"Aplastado más errores"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"بهبود Zcash","description":"پس از انتقال موفقیت آمیز به IronWood جدید، بهبودهای بیشتری را به کیف پول zcash اضافه کردیم"},{"title":"AnyPay همانطور که در نظر گرفته شده است","description":"اکنون چسباندن یا اسکن یک آدرس از هر کیف پولی، شما را به درستی به تعویض یا ارسال از کیف پول صحیح و پیشرفت های بسیار بیشتر راهنمایی می کند."},{"title":"بهبودهای رابط کاربری","description":"برخی از عناصر رابط کاربری جدید را فقط برای شما اضافه کرد"},{"title":"رفع اشکال","description":"اشکالات بیشتری را له کرد"}]
|
||||
[{"title":"AnyPay Improvements","description":"اکنون چسباندن یا اسکن یک آدرس از هر کیف پولی، شما را به درستی به تعویض یا ارسال از کیف پول صحیح و پیشرفت های بسیار بیشتر راهنمایی می کند."},{"title":"بهبودهای رابط کاربری","description":"برخی از عناصر رابط کاربری جدید را فقط برای شما اضافه کرد"},{"title":"رفع اشکال","description":"اشکالات بیشتری را له کرد"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Améliorations de Zcash","description":"Après la migration réussie vers le nouvel IronWood, nous avons ajouté d'autres améliorations au portefeuille zcash."},{"title":"AnyPay comme prévu","description":"Désormais, coller ou scanner une adresse à partir de n'importe quel portefeuille vous indiquera correctement soit l'échange, soit l'envoi à partir du bon portefeuille, et bien d'autres améliorations."},{"title":"Améliorations de l'interface utilisateur","description":"Ajout de nouveaux éléments d'interface utilisateur juste pour vous"},{"title":"Corrections de bugs","description":"Écrasé plus de bugs"}]
|
||||
[{"title":"Améliorations d'AnyPay","description":"Désormais, coller ou scanner une adresse à partir de n'importe quel portefeuille vous indiquera correctement soit l'échange, soit l'envoi à partir du bon portefeuille, et bien d'autres améliorations."},{"title":"Améliorations de l'interface utilisateur","description":"Ajout de nouveaux éléments d'interface utilisateur juste pour vous"},{"title":"Corrections de bugs","description":"Écrasé plus de bugs"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Zcash ñemyatyrõ","description":"Ojejapo rire migración osẽ porãva IronWood pyahúpe, romoĩve mejora zcash billetera-pe"},{"title":"AnyPay Ojeipotaháicha","description":"Ko’áĝa emboja térã eescanea peteĩ dirección oimeraẽva billetera-gui nde señaláta hekopete taha’e intercambio térã emondo haĝua billetera hekopeteguágui, ha hetaiteve ñemyatyrõ"},{"title":"UI ñemyatyrõ","description":"Oñemoĩve peteĩ elemento UI pyahu ndéve g̃uarãnte"},{"title":"Umi mba’e’oka ñemyatyrõ","description":"Oñembopupu hetave mba’e’oka"}]
|
||||
[{"title":"AnyPay Ñemyatyrõ","description":"Ko’áĝa emboja térã eescanea peteĩ dirección oimeraẽva billetera-gui nde señaláta hekopete taha’e intercambio térã emondo haĝua billetera hekopeteguágui, ha hetaiteve ñemyatyrõ"},{"title":"UI ñemyatyrõ","description":"Oñemoĩve peteĩ elemento UI pyahu ndéve g̃uarãnte"},{"title":"Umi mba’e’oka ñemyatyrõ","description":"Oñembopupu hetave mba’e’oka"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Zcash ingantawa","description":"Bayan nasarar ƙaura zuwa sabon IronWood, mun ƙara ƙarin haɓakawa zuwa walat ɗin zcash"},{"title":"AnyPay kamar yadda aka nufa","description":"Yanzu liƙa ko duba adireshi daga kowane walat zai nuna maka daidai ga ko dai musanya ko aikawa daga ainihin walat ɗin, da ƙarin haɓakawa."},{"title":"UI inganta","description":"An ƙara wasu sabbin abubuwan UI don ku kawai"},{"title":"Gyaran kwaro","description":"Squashed karin kwari"}]
|
||||
[{"title":"AnyBiyan Ingantawa","description":"Yanzu liƙa ko duba adireshi daga kowane walat zai nuna maka daidai ga ko dai musanya ko aikawa daga ainihin walat ɗin, da ƙarin haɓakawa."},{"title":"UI inganta","description":"An ƙara wasu sabbin abubuwan UI don ku kawai"},{"title":"Gyaran kwaro","description":"Squashed karin kwari"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"ज़कैश में सुधार","description":"नए आयरनवुड में सफल माइग्रेशन के बाद, हमने zcash वॉलेट में और सुधार जोड़े"},{"title":"इच्छानुसार कोई भी भुगतान करें","description":"अब किसी भी वॉलेट से किसी पते को चिपकाने या स्कैन करने से आपको स्वैपिंग या सही वॉलेट से भेजने का सही संकेत मिलेगा, और भी बहुत कुछ सुधार होगा"},{"title":"UI improvements","description":"केवल आपके लिए कुछ ताज़ा यूआई तत्व जोड़े गए हैं"},{"title":"कंप्यूटर प्रोग्राम या प्रणाली में बग को दूर करना","description":"अधिक कीड़ों को कुचल दिया"}]
|
||||
[{"title":"AnyPay सुधार","description":"अब किसी भी वॉलेट से किसी पते को चिपकाने या स्कैन करने से आपको स्वैपिंग या सही वॉलेट से भेजने का सही संकेत मिलेगा, और भी बहुत कुछ सुधार होगा"},{"title":"यूआई सुधार","description":"केवल आपके लिए कुछ ताज़ा यूआई तत्व जोड़े गए हैं"},{"title":"कंप्यूटर प्रोग्राम या प्रणाली में बग को दूर करना","description":"अधिक कीड़ों को कुचल दिया"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Zcash improvements","description":"Nakon uspješne migracije na novi IronWood, dodali smo još poboljšanja u zcash novčanik"},{"title":"AnyPay kako je predviđeno","description":"Sada će vas lijepljenje ili skeniranje adrese iz bilo kojeg novčanika ispravno usmjeriti na zamjenu ili slanje iz ispravnog novčanika i još mnogo poboljšanja"},{"title":"UI improvements","description":"Dodani su novi elementi korisničkog sučelja samo za vas"},{"title":"Ispravci grešaka","description":"Squashed more bugs"}]
|
||||
[{"title":"AnyPay poboljšanja","description":"Sada će vas lijepljenje ili skeniranje adrese iz bilo kojeg novčanika ispravno usmjeriti na zamjenu ili slanje iz ispravnog novčanika i još mnogo poboljšanja"},{"title":"Poboljšanja korisničkog sučelja","description":"Dodani su novi elementi korisničkog sučelja samo za vas"},{"title":"Ispravci grešaka","description":"Zgnječio još kukaca"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Zcash բարելավումներ","description":"Նոր IronWood-ի հաջող տեղափոխումից հետո մենք ավելի շատ բարելավումներ ենք ավելացրել zcash դրամապանակում"},{"title":"AnyPay, ինչպես նախատեսված է","description":"Այժմ ցանկացած դրամապանակից հասցե կպցնելը կամ սկանավորումը ձեզ ճիշտ կուղղորդի՝ կա՛մ փոխանակելու, կա՛մ ճիշտ դրամապանակից ուղարկելու և շատ ավելի բարելավումներ:"},{"title":"UI բարելավումներ","description":"Ավելացրել է մի քանի թարմ UI տարրեր հենց ձեզ համար"},{"title":"Սխալների շտկում","description":"Ճզմեց ավելի շատ սխալներ"}]
|
||||
[{"title":"AnyPay բարելավումներ","description":"Այժմ ցանկացած դրամապանակից հասցե կպցնելը կամ սկանավորումը ձեզ ճիշտ կուղղորդի՝ կա՛մ փոխանակելու, կա՛մ ճիշտ դրամապանակից ուղարկելու և շատ ավելի բարելավումներ:"},{"title":"UI բարելավումներ","description":"Ավելացրել է մի քանի թարմ UI տարրեր հենց ձեզ համար"},{"title":"Սխալների շտկում","description":"Ճզմեց ավելի շատ սխալներ"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Peningkatan Zcash","description":"Setelah migrasi berhasil ke IronWood baru, kami menambahkan lebih banyak perbaikan pada dompet zcash"},{"title":"AnyPay sesuai tujuan","description":"Sekarang menempelkan atau memindai alamat dari dompet mana pun akan mengarahkan Anda dengan benar untuk menukar atau mengirim dari dompet yang benar, dan banyak lagi peningkatan lainnya"},{"title":"Peningkatan UI","description":"Menambahkan beberapa elemen UI baru hanya untuk Anda"},{"title":"Perbaikan bug","description":"Membasmi lebih banyak bug"}]
|
||||
[{"title":"Peningkatan AnyPay","description":"Sekarang menempelkan atau memindai alamat dari dompet mana pun akan mengarahkan Anda dengan benar untuk menukar atau mengirim dari dompet yang benar, dan banyak lagi peningkatan lainnya"},{"title":"Peningkatan UI","description":"Menambahkan beberapa elemen UI baru hanya untuk Anda"},{"title":"Perbaikan bug","description":"Membasmi lebih banyak bug"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Miglioramenti di Zcash","description":"Dopo la riuscita migrazione al nuovo IronWood, abbiamo aggiunto ulteriori miglioramenti al portafoglio zcash"},{"title":"AnyPay come previsto","description":"Ora incollare o scansionare un indirizzo da qualsiasi portafoglio ti indicherà correttamente lo scambio o l'invio dal portafoglio corretto e molti altri miglioramenti"},{"title":"Miglioramenti dell'interfaccia utente","description":"Aggiunti alcuni nuovi elementi dell'interfaccia utente solo per te"},{"title":"Correzioni di bug","description":"Eliminati altri bug"}]
|
||||
[{"title":"Miglioramenti di AnyPay","description":"Ora incollare o scansionare un indirizzo da qualsiasi portafoglio ti indicherà correttamente lo scambio o l'invio dal portafoglio corretto e molti altri miglioramenti"},{"title":"Miglioramenti dell'interfaccia utente","description":"Aggiunti alcuni nuovi elementi dell'interfaccia utente solo per te"},{"title":"Correzioni di bug","description":"Eliminati altri bug"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Zcashの改善","description":"新しい IronWood への移行が成功した後、zcash ウォレットにさらに改良を加えました。"},{"title":"意図したとおりの AnyPay","description":"任意のウォレットからアドレスを貼り付けるかスキャンすると、正しいウォレットからの交換または送信が正しく示されるようになり、さらに多くの改善が行われました。"},{"title":"UIの改善","description":"あなたのためだけにいくつかの新しい UI 要素を追加しました"},{"title":"バグ修正","description":"より多くのバグを潰しました"}]
|
||||
[{"title":"AnyPayの改善","description":"任意のウォレットからアドレスを貼り付けるかスキャンすると、正しいウォレットからの交換または送信が正しく示されるようになり、さらに多くの改善が行われました。"},{"title":"UIの改善","description":"あなたのためだけにいくつかの新しい UI 要素を追加しました"},{"title":"バグ修正","description":"さらに多くのバグを潰しました"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Zcash 개선","description":"새로운 IronWood로 성공적으로 마이그레이션한 후 zcash 지갑에 더 많은 개선 사항을 추가했습니다."},{"title":"의도한 대로 AnyPay","description":"이제 지갑에서 주소를 붙여넣거나 스캔하면 올바른 지갑에서 주소를 교환하거나 보내는 것을 올바르게 가리킬 수 있으며 훨씬 더 많은 개선이 가능합니다."},{"title":"UI 개선","description":"당신을 위한 새로운 UI 요소를 추가했습니다."},{"title":"버그 수정","description":"더 많은 버그를 해결했습니다."}]
|
||||
[{"title":"애니페이 개선","description":"이제 지갑에서 주소를 붙여넣거나 스캔하면 올바른 지갑에서 주소를 교환하거나 보내는 것을 올바르게 가리킬 수 있으며 훨씬 더 많은 개선 사항이 있습니다."},{"title":"UI 개선","description":"당신을 위한 새로운 UI 요소를 추가했습니다."},{"title":"버그 수정","description":"더 많은 버그를 해결했습니다."}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Zcash တိုးတက်မှုများ","description":"IronWood အသစ်သို့ အောင်မြင်စွာ ပြောင်းရွှေ့ပြီးနောက်၊ ကျွန်ုပ်တို့သည် zcash ပိုက်ဆံအိတ်သို့ နောက်ထပ် တိုးတက်မှုများကို ထည့်သွင်းခဲ့သည်။"},{"title":"ရည်ရွယ်ထားသည့်အတိုင်း AnyPay","description":"ယခု မည်သည့်ပိုက်ဆံအိတ်မှ လိပ်စာတစ်ခုကို ကူးထည့်ခြင်း သို့မဟုတ် စကင်န်ဖတ်ခြင်းသည် သင့်အား မှန်ကန်သောပိုက်ဆံအိတ်မှ လဲလှယ်ရန် သို့မဟုတ် ပေးပို့ခြင်းတို့ကို မှန်ကန်စွာ ညွှန်ပြပေးမည်ဖြစ်ပြီး ပိုမိုကောင်းမွန်လာစေရန်၊"},{"title":"UI တိုးတက်မှုများ","description":"သင့်အတွက်သာ လတ်ဆတ်သော UI အစိတ်အပိုင်းအချို့ကို ထည့်ထားသည်။"},{"title":"ချွတ်ယွင်းချက်ပြင်ဆင်မှုများ","description":"နောက်ထပ် ပိုးကောင်များကို နှိမ်နင်းခဲ့သည်။"}]
|
||||
[{"title":"AnyPay တိုးတက်မှုများ","description":"ယခု မည်သည့်ပိုက်ဆံအိတ်မှ လိပ်စာတစ်ခုကို ကူးထည့်ခြင်း သို့မဟုတ် စကင်န်ဖတ်ခြင်းသည် သင့်အား မှန်ကန်သောပိုက်ဆံအိတ်မှ လဲလှယ်ရန် သို့မဟုတ် ပေးပို့ခြင်းတို့ကို မှန်ကန်စွာ ညွှန်ပြပေးမည်ဖြစ်ပြီး ပိုမိုကောင်းမွန်လာစေရန်၊"},{"title":"UI တိုးတက်မှုများ","description":"သင့်အတွက်သာ လတ်ဆတ်သော UI အစိတ်အပိုင်းအချို့ကို ထည့်ထားသည်။"},{"title":"ချွတ်ယွင်းချက်ပြင်ဆင်မှုများ","description":"နောက်ထပ် ပိုးကောင်များကို နှိမ်နင်းခဲ့သည်။"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Zcash-verbeteringen","description":"Na de succesvolle migratie naar het nieuwe IronWood hebben we meer verbeteringen aan de zcash-portemonnee toegevoegd"},{"title":"AnyPay zoals bedoeld","description":"Als u nu een adres uit een willekeurige portemonnee plakt of scant, wordt u correct verwezen naar het wisselen of verzenden vanuit de juiste portemonnee, en nog veel meer verbeteringen"},{"title":"UI-verbeteringen","description":"Speciaal voor jou een aantal nieuwe UI-elementen toegevoegd"},{"title":"Bugfixes","description":"Nog meer bugs geplet"}]
|
||||
[{"title":"AnyPay-verbeteringen","description":"Als u nu een adres uit een willekeurige portemonnee plakt of scant, wordt u correct verwezen naar het wisselen of verzenden vanuit de juiste portemonnee, en nog veel meer verbeteringen"},{"title":"UI-verbeteringen","description":"Speciaal voor jou een aantal nieuwe UI-elementen toegevoegd"},{"title":"Bugfixes","description":"Nog meer bugs geplet"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Ulepszenia Zcasha","description":"Po udanej migracji do nowego IronWood, dodaliśmy kolejne ulepszenia do portfela Zcash"},{"title":"AnyPay zgodnie z przeznaczeniem","description":"Teraz wklejenie lub zeskanowanie adresu z dowolnego portfela wskaże prawidłowo opcję wymiany lub wysłania z odpowiedniego portfela oraz wiele innych ulepszeń"},{"title":"Ulepszenia interfejsu użytkownika","description":"Dodano kilka świeżych elementów interfejsu użytkownika specjalnie dla Ciebie"},{"title":"Poprawki błędów","description":"Zmiażdżono więcej błędów"}]
|
||||
[{"title":"Ulepszenia AnyPay","description":"Teraz wklejenie lub zeskanowanie adresu z dowolnego portfela wskaże prawidłowo opcję wymiany lub wysłania z odpowiedniego portfela oraz wiele innych ulepszeń"},{"title":"Ulepszenia interfejsu użytkownika","description":"Dodano kilka świeżych elementów interfejsu użytkownika specjalnie dla Ciebie"},{"title":"Poprawki błędów","description":"Zmiażdżono więcej błędów"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Melhorias no Zcash","description":"Após a migração bem-sucedida para o novo IronWood, adicionamos mais melhorias à carteira zcash"},{"title":"AnyPay conforme pretendido","description":"Agora, colar ou digitalizar um endereço de qualquer carteira indicará corretamente a troca ou o envio da carteira correta e muito mais melhorias"},{"title":"Melhorias na interface do usuário","description":"Adicionados alguns novos elementos de UI só para você"},{"title":"Correções de bugs","description":"Esmagou mais bugs"}]
|
||||
[{"title":"Melhorias no AnyPay","description":"Agora, colar ou digitalizar um endereço de qualquer carteira indicará corretamente a troca ou o envio da carteira correta e muito mais melhorias"},{"title":"Melhorias na interface do usuário","description":"Adicionados alguns novos elementos de UI só para você"},{"title":"Correções de bugs","description":"Esmagou mais bugs"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Улучшения Zcash","description":"После успешного перехода на новый IronWood мы добавили дополнительные улучшения в кошелек zcash."},{"title":"AnyPay как задумано","description":"Теперь при вставке или сканировании адреса из любого кошелька вы сможете правильно выбрать обмен или отправку из правильного кошелька, а также множество других улучшений."},{"title":"Улучшения пользовательского интерфейса","description":"Специально для вас добавлено несколько свежих элементов пользовательского интерфейса."},{"title":"Исправления ошибок","description":"Устранено больше ошибок"}]
|
||||
[{"title":"Улучшения AnyPay","description":"Теперь при вставке или сканировании адреса из любого кошелька вы сможете правильно выбрать обмен или отправку из правильного кошелька, а также множество других улучшений."},{"title":"Улучшения пользовательского интерфейса","description":"Специально для вас добавлено несколько свежих элементов пользовательского интерфейса."},{"title":"Исправления ошибок","description":"Устранено больше ошибок"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"การปรับปรุง Zcash","description":"หลังจากการโยกย้ายไปยัง IronWood ใหม่ได้สำเร็จ เราได้เพิ่มการปรับปรุงเพิ่มเติมให้กับกระเป๋าเงิน zcash"},{"title":"AnyPay ตามที่ตั้งใจไว้","description":"ตอนนี้การวางหรือสแกนที่อยู่จากกระเป๋าเงินใด ๆ จะนำคุณไปสู่การแลกเปลี่ยนหรือส่งจากกระเป๋าเงินที่ถูกต้องอย่างถูกต้อง และการปรับปรุงอื่น ๆ อีกมากมาย"},{"title":"การปรับปรุง UI","description":"เพิ่มองค์ประกอบ UI ใหม่สำหรับคุณโดยเฉพาะ"},{"title":"แก้ไขข้อบกพร่อง","description":"กำจัดข้อบกพร่องเพิ่มเติม"}]
|
||||
[{"title":"การปรับปรุง AnyPay","description":"ตอนนี้การวางหรือสแกนที่อยู่จากกระเป๋าเงินใด ๆ จะนำคุณไปสู่การแลกเปลี่ยนหรือส่งจากกระเป๋าเงินที่ถูกต้องอย่างถูกต้อง และการปรับปรุงอื่น ๆ อีกมากมาย"},{"title":"การปรับปรุง UI","description":"เพิ่มองค์ประกอบ UI ใหม่สำหรับคุณโดยเฉพาะ"},{"title":"แก้ไขข้อบกพร่อง","description":"กำจัดข้อบกพร่องเพิ่มเติม"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Mga pagpapabuti ng Zcash","description":"Pagkatapos ng matagumpay na paglipat sa bagong IronWood, nagdagdag kami ng higit pang mga pagpapahusay sa zcash wallet"},{"title":"AnyPay gaya ng Nilalayon","description":"Ngayon, ang pag-paste o pag-scan ng isang address mula sa anumang pitaka ay ituturo sa iyo nang tama sa alinman sa pagpapalit o pagpapadala mula sa tamang pitaka, at marami pang mga pagpapabuti"},{"title":"Mga pagpapabuti ng UI","description":"Nagdagdag ng ilang sariwang elemento ng UI para lang sa iyo"},{"title":"Mga pag-aayos ng bug","description":"Nilapit ang higit pang mga bug"}]
|
||||
[{"title":"Mga Pagpapabuti ng AnyPay","description":"Ngayon, ang pag-paste o pag-scan ng isang address mula sa anumang pitaka ay ituturo sa iyo nang tama sa alinman sa pagpapalit o pagpapadala mula sa tamang pitaka, at marami pang mga pagpapabuti"},{"title":"Mga pagpapabuti ng UI","description":"Nagdagdag ng ilang sariwang elemento ng UI para lang sa iyo"},{"title":"Mga pag-aayos ng bug","description":"Nilapit ang higit pang mga bug"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Zcash iyileştirmeleri","description":"Yeni IronWood'a başarılı geçişin ardından zcash cüzdanına daha fazla iyileştirme ekledik"},{"title":"AnyPay İstenildiği Gibi","description":"Artık herhangi bir cüzdandan bir adresi yapıştırmak veya taramak, sizi doğru cüzdandan değiştirmeye veya göndermeye yönlendirecek ve çok daha fazla iyileştirme yapacak"},{"title":"Kullanıcı arayüzü iyileştirmeleri","description":"Size özel bazı yeni kullanıcı arayüzü öğeleri eklendi"},{"title":"Hata düzeltmeleri","description":"Daha fazla hata giderildi"}]
|
||||
[{"title":"AnyPay İyileştirmeleri","description":"Artık herhangi bir cüzdandan bir adresi yapıştırmak veya taramak, sizi doğru cüzdandan değiştirmeye veya göndermeye yönlendirecek ve çok daha fazla iyileştirme yapacak"},{"title":"Kullanıcı arayüzü iyileştirmeleri","description":"Size özel bazı yeni kullanıcı arayüzü öğeleri eklendi"},{"title":"Hata düzeltmeleri","description":"Daha fazla hata giderildi"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Покращення Zcash","description":"Після успішного переходу на новий IronWood ми додали додаткові покращення до гаманця zcash"},{"title":"AnyPay за призначенням","description":"Тепер вставлення або сканування адреси з будь-якого гаманця правильно вкаже вас на обмін або надсилання з правильного гаманця, а також багато інших покращень"},{"title":"Покращення інтерфейсу користувача","description":"Додано кілька свіжих елементів інтерфейсу спеціально для вас"},{"title":"Виправлення помилок","description":"Роздавив більше помилок"}]
|
||||
[{"title":"Покращення AnyPay","description":"Тепер вставлення або сканування адреси з будь-якого гаманця правильно вкаже вас на обмін або надсилання з правильного гаманця, а також багато інших покращень"},{"title":"Покращення інтерфейсу користувача","description":"Додано кілька свіжих елементів інтерфейсу спеціально для вас"},{"title":"Виправлення помилок","description":"Роздавив більше помилок"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Zcash میں بہتری","description":"نئے IronWood میں کامیاب منتقلی کے بعد، ہم نے zcash wallet میں مزید بہتری شامل کی۔"},{"title":"AnyPay جیسا کہ ارادہ ہے۔","description":"اب کسی بھی بٹوے سے ایڈریس پیسٹ یا اسکین کرنا آپ کو صحیح بٹوے سے تبدیل کرنے یا بھیجنے کی طرف صحیح طریقے سے اشارہ کرے گا، اور بہت زیادہ بہتری"},{"title":"UI میں بہتری","description":"صرف آپ کے لیے کچھ تازہ UI عناصر شامل کیے گئے۔"},{"title":"بگ کی اصلاحات","description":"مزید کیڑے کو کچل دیا۔"}]
|
||||
[{"title":"AnyPay میں بہتری","description":"اب کسی بھی بٹوے سے ایڈریس پیسٹ یا اسکین کرنا آپ کو صحیح بٹوے سے تبدیل کرنے یا بھیجنے کی طرف صحیح طریقے سے اشارہ کرے گا، اور بہت زیادہ بہتری"},{"title":"UI میں بہتری","description":"صرف آپ کے لیے کچھ تازہ UI عناصر شامل کیے گئے۔"},{"title":"بگ کی اصلاحات","description":"مزید کیڑے کو کچل دیا۔"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Cải tiến Zcash","description":"Sau khi di chuyển thành công sang IronWood mới, chúng tôi đã bổ sung thêm nhiều cải tiến hơn cho ví zcash"},{"title":"AnyPay như dự định","description":"Giờ đây, việc dán hoặc quét địa chỉ từ bất kỳ ví nào sẽ chỉ cho bạn cách hoán đổi hoặc gửi từ đúng ví và nhiều cải tiến hơn nữa"},{"title":"Cải tiến giao diện người dùng","description":"Đã thêm một số thành phần UI mới dành riêng cho bạn"},{"title":"Sửa lỗi","description":"Dẹp nhiều lỗi hơn"}]
|
||||
[{"title":"Cải tiến AnyPay","description":"Giờ đây, việc dán hoặc quét địa chỉ từ bất kỳ ví nào sẽ chỉ cho bạn cách hoán đổi hoặc gửi từ đúng ví và nhiều cải tiến hơn nữa"},{"title":"Cải tiến giao diện người dùng","description":"Đã thêm một số thành phần UI mới dành riêng cho bạn"},{"title":"Sửa lỗi","description":"Dẹp nhiều lỗi hơn"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Awọn ilọsiwaju Zcash","description":"Lẹhin ijira aṣeyọri si IronWood tuntun, a ṣafikun awọn ilọsiwaju diẹ sii si apamọwọ zcash"},{"title":"AnyPay bi a ti pinnu","description":"Ni bayi titọ tabi ṣiṣayẹwo adirẹsi kan lati eyikeyi apamọwọ yoo tọka si ni deede si boya paarọ tabi firanṣẹ lati apamọwọ to pe, ati awọn ilọsiwaju pupọ diẹ sii."},{"title":"UI awọn ilọsiwaju","description":"Ṣafikun diẹ ninu awọn eroja UI tuntun kan fun ọ"},{"title":"Awọn atunṣe kokoro","description":"Squashed diẹ idun"}]
|
||||
[{"title":"Awọn ilọsiwaju AnyPay","description":"Ni bayi titọ tabi ṣiṣayẹwo adirẹsi kan lati eyikeyi apamọwọ yoo tọka si ni deede si boya paarọ tabi firanṣẹ lati apamọwọ to pe, ati awọn ilọsiwaju pupọ diẹ sii."},{"title":"UI awọn ilọsiwaju","description":"Ṣafikun diẹ ninu awọn eroja UI tuntun kan fun ọ"},{"title":"Awọn atunṣe kokoro","description":"Squashed diẹ idun"}]
|
||||
@@ -1 +1 @@
|
||||
[{"title":"Zcash 的改进","description":"成功迁移到新的 IronWood 后,我们对 zcash 钱包添加了更多改进"},{"title":"AnyPay 符合预期","description":"现在,从任何钱包粘贴或扫描地址都会正确地指示您从正确的钱包进行交换或发送,以及更多改进"},{"title":"用户界面改进","description":"为您添加了一些新鲜的 UI 元素"},{"title":"错误修复","description":"消除了更多错误"}]
|
||||
[{"title":"AnyPay 改进","description":"现在,从任何钱包粘贴或扫描地址将正确地指示您从正确的钱包进行交换或发送,以及更多改进"},{"title":"用户界面改进","description":"为您添加了一些新鲜的 UI 元素"},{"title":"错误修复","description":"消除了更多错误"}]
|
||||
@@ -20,6 +20,7 @@ extension PsbtSigner on PsbtV2 {
|
||||
setGlobalInputCount(tx.inputs.length);
|
||||
setGlobalOutputCount(tx.outputs.length);
|
||||
setGlobalTxVersion(Uint8List.fromList(tx.version).readUint32LE(0));
|
||||
setGlobalFallbackLocktime(Uint8List.fromList(tx.locktime).readUint32LE(0));
|
||||
|
||||
for (var i = 0; i < getGlobalInputCount(); i++) {
|
||||
inputMaps.insert(i, <String, Uint8List>{});
|
||||
|
||||
@@ -88,7 +88,7 @@ dependency_overrides:
|
||||
bitcoin_base:
|
||||
git:
|
||||
url: https://github.com/cake-tech/bitcoin_base
|
||||
ref: bda0e2904effa799ec835b4578cc3fc5d31caa78
|
||||
ref: 4e41f96f4838139895c65c3f49109d05af5d46aa
|
||||
pointycastle: 3.7.4
|
||||
ffi: 2.1.0
|
||||
intl: any
|
||||
|
||||
@@ -43,7 +43,7 @@ dependency_overrides:
|
||||
bitcoin_base:
|
||||
git:
|
||||
url: https://github.com/cake-tech/bitcoin_base
|
||||
ref: bda0e2904effa799ec835b4578cc3fc5d31caa78
|
||||
ref: 4e41f96f4838139895c65c3f49109d05af5d46aa
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
@@ -40,7 +40,7 @@ dependency_overrides:
|
||||
bitcoin_base:
|
||||
git:
|
||||
url: https://github.com/cake-tech/bitcoin_base
|
||||
ref: bda0e2904effa799ec835b4578cc3fc5d31caa78
|
||||
ref: 4e41f96f4838139895c65c3f49109d05af5d46aa
|
||||
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
|
||||
@@ -26,7 +26,7 @@ dependencies:
|
||||
monero:
|
||||
git:
|
||||
url: https://github.com/mrcyjanek/monero_c.git
|
||||
ref: 3bfb3856a838f2bf6b729501837bb0295dedf25d
|
||||
ref: cd4fe366cc8d3c188c91de279f43b29c0e044b15
|
||||
path: impls/monero.dart
|
||||
mutex: ^3.1.0
|
||||
ledger_flutter_plus: ^1.4.1
|
||||
|
||||
@@ -24,7 +24,7 @@ dependencies:
|
||||
monero:
|
||||
git:
|
||||
url: https://github.com/mrcyjanek/monero_c.git
|
||||
ref: 3bfb3856a838f2bf6b729501837bb0295dedf25d
|
||||
ref: cd4fe366cc8d3c188c91de279f43b29c0e044b15
|
||||
path: impls/monero.dart
|
||||
mutex: ^3.1.0
|
||||
|
||||
|
||||
@@ -66,8 +66,13 @@ class Transfer {
|
||||
? []
|
||||
: (json['remote_aliases'] as List<dynamic>).cast<String>(),
|
||||
showSender: json['show_sender'] as bool? ?? false,
|
||||
subtransfers: (json['subtransfers'] as List<dynamic>? ?? [])
|
||||
.map((e) => Subtransfer.fromJson(e as Map<String, dynamic>))
|
||||
subtransfers: (json['subtransfers_by_pid'] as List<dynamic>? ?? [])
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.expand(
|
||||
(group) => (group['subtransfers'] as List<dynamic>? ?? [])
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map(Subtransfer.fromJson),
|
||||
)
|
||||
.toList(),
|
||||
timestamp: json['timestamp'] as int? ?? 0,
|
||||
transferInternalIndex: json['transfer_internal_index'] == null
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:bip32/bip32.dart' as bip32;
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
import 'package:bip39/src/wordlists/english.dart' as bip39_english;
|
||||
|
||||
bool isBip39Seed(String mnemonic) => bip39.validateMnemonic(mnemonic);
|
||||
|
||||
List<String> get bip39EnglishWords => List<String>.from(bip39_english.WORDLIST);
|
||||
|
||||
String generateBip39Mnemonic({int strength = 128}) =>
|
||||
bip39.generateMnemonic(strength: strength);
|
||||
|
||||
String getSecretDerivationFromBip39(String mnemonic, {String passphrase = ''}) {
|
||||
final seed = bip39.mnemonicToSeed(mnemonic, passphrase: passphrase);
|
||||
|
||||
final bip32KeyPair = bip32.BIP32.fromSeed(seed).derivePath("m/44'/128'/0'/0/0");
|
||||
|
||||
return _reduceECKey(bip32KeyPair.privateKey!).toHexString();
|
||||
}
|
||||
|
||||
const _ed25519CurveOrder = "1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED";
|
||||
|
||||
Uint8List _reduceECKey(Uint8List buffer) {
|
||||
final curveOrder = BigInt.parse(_ed25519CurveOrder, radix: 16);
|
||||
final bigNumber = _readBytes(buffer);
|
||||
|
||||
var result = bigNumber % curveOrder;
|
||||
|
||||
final resultBuffer = Uint8List(32);
|
||||
for (var i = 0; i < 32; i++) {
|
||||
resultBuffer[i] = (result & BigInt.from(0xff)).toInt();
|
||||
result = result >> 8;
|
||||
}
|
||||
|
||||
return resultBuffer;
|
||||
}
|
||||
|
||||
/// Read BigInt from a little-endian Uint8List
|
||||
/// From https://github.com/dart-lang/sdk/issues/32803#issuecomment-387405784
|
||||
BigInt _readBytes(Uint8List bytes) {
|
||||
BigInt read(int start, int end) {
|
||||
if (end - start <= 4) {
|
||||
var result = 0;
|
||||
for (int i = end - 1; i >= start; i--) {
|
||||
result = result * 256 + bytes[i];
|
||||
}
|
||||
return BigInt.from(result);
|
||||
}
|
||||
final mid = start + ((end - start) >> 1);
|
||||
return read(start, mid) + read(mid, end) * (BigInt.one << ((mid - start) * 8));
|
||||
}
|
||||
|
||||
return read(0, bytes.length);
|
||||
}
|
||||
|
||||
extension on Uint8List {
|
||||
String toHexString() =>
|
||||
map((b) => b.toRadixString(16).padLeft(2, '0')).join();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
NODE=http://37.27.100.59:10500/json_rpc
|
||||
HEIGHT=$(curl -s -X POST $NODE -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":"0","method":"getinfo"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['result']['height'])")
|
||||
echo "_Checkpoint($(curl -s -X POST $NODE -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":"0","method":"getblockheaderbyheight","params":{"height":1}}' | python3 -c "import sys,json; print(json.load(sys.stdin)['result']['block_header']['timestamp'])"), 1),"
|
||||
for i in $(seq 1 $((HEIGHT/10000))); do echo "_Checkpoint($(curl -s -X POST $NODE -H 'Content-Type: application/json' -d "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"getblockheaderbyheight\",\"params\":{\"height\":${i}0000}}" | python3 -c "import sys,json; print(json.load(sys.stdin)['result']['block_header']['timestamp'])"), ${i}0000),"; done
|
||||
@@ -0,0 +1,467 @@
|
||||
class ZanoHeight {
|
||||
static final List<_Checkpoint> _points = [
|
||||
_Checkpoint(1557342384, 1),
|
||||
_Checkpoint(1557906733, 10000),
|
||||
_Checkpoint(1558516097, 20000),
|
||||
_Checkpoint(1559119125, 30000),
|
||||
_Checkpoint(1559741805, 40000),
|
||||
_Checkpoint(1560341175, 50000),
|
||||
_Checkpoint(1560948480, 60000),
|
||||
_Checkpoint(1561555965, 70000),
|
||||
_Checkpoint(1562142135, 80000),
|
||||
_Checkpoint(1562749400, 90000),
|
||||
_Checkpoint(1563354315, 100000),
|
||||
_Checkpoint(1563958673, 110000),
|
||||
_Checkpoint(1564559835, 120000),
|
||||
_Checkpoint(1565159325, 130000),
|
||||
_Checkpoint(1565772195, 140000),
|
||||
_Checkpoint(1566389235, 150000),
|
||||
_Checkpoint(1566992793, 160000),
|
||||
_Checkpoint(1567597678, 170000),
|
||||
_Checkpoint(1568204955, 180000),
|
||||
_Checkpoint(1568812530, 190000),
|
||||
_Checkpoint(1569418329, 200000),
|
||||
_Checkpoint(1570035660, 210000),
|
||||
_Checkpoint(1570641964, 220000),
|
||||
_Checkpoint(1571242140, 230000),
|
||||
_Checkpoint(1571841282, 240000),
|
||||
_Checkpoint(1572443911, 250000),
|
||||
_Checkpoint(1573049280, 260000),
|
||||
_Checkpoint(1573653255, 270000),
|
||||
_Checkpoint(1574251680, 280000),
|
||||
_Checkpoint(1574854984, 290000),
|
||||
_Checkpoint(1575459060, 300000),
|
||||
_Checkpoint(1576064640, 310000),
|
||||
_Checkpoint(1576665225, 320000),
|
||||
_Checkpoint(1577271045, 330000),
|
||||
_Checkpoint(1577867835, 340000),
|
||||
_Checkpoint(1578470370, 350000),
|
||||
_Checkpoint(1579078170, 360000),
|
||||
_Checkpoint(1579674765, 370000),
|
||||
_Checkpoint(1580277860, 380000),
|
||||
_Checkpoint(1580878155, 390000),
|
||||
_Checkpoint(1581482220, 400000),
|
||||
_Checkpoint(1582087577, 410000),
|
||||
_Checkpoint(1582689270, 420000),
|
||||
_Checkpoint(1583284005, 430000),
|
||||
_Checkpoint(1583880062, 440000),
|
||||
_Checkpoint(1584480692, 450000),
|
||||
_Checkpoint(1585085520, 460000),
|
||||
_Checkpoint(1585694261, 470000),
|
||||
_Checkpoint(1586292210, 480000),
|
||||
_Checkpoint(1586893822, 490000),
|
||||
_Checkpoint(1587498656, 500000),
|
||||
_Checkpoint(1588099364, 510000),
|
||||
_Checkpoint(1588696710, 520000),
|
||||
_Checkpoint(1589300843, 530000),
|
||||
_Checkpoint(1589904930, 540000),
|
||||
_Checkpoint(1590499185, 550000),
|
||||
_Checkpoint(1591111133, 560000),
|
||||
_Checkpoint(1591715587, 570000),
|
||||
_Checkpoint(1592316375, 580000),
|
||||
_Checkpoint(1592918012, 590000),
|
||||
_Checkpoint(1593521050, 600000),
|
||||
_Checkpoint(1594123886, 610000),
|
||||
_Checkpoint(1594725660, 620000),
|
||||
_Checkpoint(1595326710, 630000),
|
||||
_Checkpoint(1595929088, 640000),
|
||||
_Checkpoint(1596535020, 650000),
|
||||
_Checkpoint(1597132395, 660000),
|
||||
_Checkpoint(1597740870, 670000),
|
||||
_Checkpoint(1598339827, 680000),
|
||||
_Checkpoint(1598945010, 690000),
|
||||
_Checkpoint(1599547530, 700000),
|
||||
_Checkpoint(1600153050, 710000),
|
||||
_Checkpoint(1600754010, 720000),
|
||||
_Checkpoint(1601355810, 730000),
|
||||
_Checkpoint(1601956635, 740000),
|
||||
_Checkpoint(1602558615, 750000),
|
||||
_Checkpoint(1603155648, 760000),
|
||||
_Checkpoint(1603759399, 770000),
|
||||
_Checkpoint(1604365586, 780000),
|
||||
_Checkpoint(1604966602, 790000),
|
||||
_Checkpoint(1605564777, 800000),
|
||||
_Checkpoint(1606168023, 810000),
|
||||
_Checkpoint(1606772409, 820000),
|
||||
_Checkpoint(1607377110, 830000),
|
||||
_Checkpoint(1607988084, 840000),
|
||||
_Checkpoint(1608593385, 850000),
|
||||
_Checkpoint(1609196310, 860000),
|
||||
_Checkpoint(1609793426, 870000),
|
||||
_Checkpoint(1610398975, 880000),
|
||||
_Checkpoint(1610999055, 890000),
|
||||
_Checkpoint(1611601290, 900000),
|
||||
_Checkpoint(1612208050, 910000),
|
||||
_Checkpoint(1612805250, 920000),
|
||||
_Checkpoint(1613409645, 930000),
|
||||
_Checkpoint(1614003255, 940000),
|
||||
_Checkpoint(1614600803, 950000),
|
||||
_Checkpoint(1615202091, 960000),
|
||||
_Checkpoint(1615802123, 970000),
|
||||
_Checkpoint(1616414192, 980000),
|
||||
_Checkpoint(1617015705, 990000),
|
||||
_Checkpoint(1617613785, 1000000),
|
||||
_Checkpoint(1618218467, 1010000),
|
||||
_Checkpoint(1618821464, 1020000),
|
||||
_Checkpoint(1619424052, 1030000),
|
||||
_Checkpoint(1620027510, 1040000),
|
||||
_Checkpoint(1620630585, 1050000),
|
||||
_Checkpoint(1621232355, 1060000),
|
||||
_Checkpoint(1621832220, 1070000),
|
||||
_Checkpoint(1622426032, 1080000),
|
||||
_Checkpoint(1623041250, 1090000),
|
||||
_Checkpoint(1623644732, 1100000),
|
||||
_Checkpoint(1624244801, 1110000),
|
||||
_Checkpoint(1624848450, 1120000),
|
||||
_Checkpoint(1625449290, 1130000),
|
||||
_Checkpoint(1626049974, 1140000),
|
||||
_Checkpoint(1626656033, 1150000),
|
||||
_Checkpoint(1627255830, 1160000),
|
||||
_Checkpoint(1627855505, 1170000),
|
||||
_Checkpoint(1628464065, 1180000),
|
||||
_Checkpoint(1629064455, 1190000),
|
||||
_Checkpoint(1629665715, 1200000),
|
||||
_Checkpoint(1630268475, 1210000),
|
||||
_Checkpoint(1630870911, 1220000),
|
||||
_Checkpoint(1631475471, 1230000),
|
||||
_Checkpoint(1632071441, 1240000),
|
||||
_Checkpoint(1632677576, 1250000),
|
||||
_Checkpoint(1633286445, 1260000),
|
||||
_Checkpoint(1633884645, 1270000),
|
||||
_Checkpoint(1634480355, 1280000),
|
||||
_Checkpoint(1635077039, 1290000),
|
||||
_Checkpoint(1635679740, 1300000),
|
||||
_Checkpoint(1636284345, 1310000),
|
||||
_Checkpoint(1636882865, 1320000),
|
||||
_Checkpoint(1637482276, 1330000),
|
||||
_Checkpoint(1638082296, 1340000),
|
||||
_Checkpoint(1638682601, 1350000),
|
||||
_Checkpoint(1639287225, 1360000),
|
||||
_Checkpoint(1639884465, 1370000),
|
||||
_Checkpoint(1640484903, 1380000),
|
||||
_Checkpoint(1641084033, 1390000),
|
||||
_Checkpoint(1641688500, 1400000),
|
||||
_Checkpoint(1642286685, 1410000),
|
||||
_Checkpoint(1642886842, 1420000),
|
||||
_Checkpoint(1643493960, 1430000),
|
||||
_Checkpoint(1644093045, 1440000),
|
||||
_Checkpoint(1644691833, 1450000),
|
||||
_Checkpoint(1645291245, 1460000),
|
||||
_Checkpoint(1645892190, 1470000),
|
||||
_Checkpoint(1646489895, 1480000),
|
||||
_Checkpoint(1647089648, 1490000),
|
||||
_Checkpoint(1647694665, 1500000),
|
||||
_Checkpoint(1648293585, 1510000),
|
||||
_Checkpoint(1648893525, 1520000),
|
||||
_Checkpoint(1649497306, 1530000),
|
||||
_Checkpoint(1650098656, 1540000),
|
||||
_Checkpoint(1650694980, 1550000),
|
||||
_Checkpoint(1651303650, 1560000),
|
||||
_Checkpoint(1651899285, 1570000),
|
||||
_Checkpoint(1652501596, 1580000),
|
||||
_Checkpoint(1653101220, 1590000),
|
||||
_Checkpoint(1653700166, 1600000),
|
||||
_Checkpoint(1654302094, 1610000),
|
||||
_Checkpoint(1654906575, 1620000),
|
||||
_Checkpoint(1655510644, 1630000),
|
||||
_Checkpoint(1656108615, 1640000),
|
||||
_Checkpoint(1656712545, 1650000),
|
||||
_Checkpoint(1657313460, 1660000),
|
||||
_Checkpoint(1657911515, 1670000),
|
||||
_Checkpoint(1658515717, 1680000),
|
||||
_Checkpoint(1659121230, 1690000),
|
||||
_Checkpoint(1659722213, 1700000),
|
||||
_Checkpoint(1660318875, 1710000),
|
||||
_Checkpoint(1660921522, 1720000),
|
||||
_Checkpoint(1661518436, 1730000),
|
||||
_Checkpoint(1662118050, 1740000),
|
||||
_Checkpoint(1662717982, 1750000),
|
||||
_Checkpoint(1663306425, 1760000),
|
||||
_Checkpoint(1663904520, 1770000),
|
||||
_Checkpoint(1664511195, 1780000),
|
||||
_Checkpoint(1665113460, 1790000),
|
||||
_Checkpoint(1665705148, 1800000),
|
||||
_Checkpoint(1666306807, 1810000),
|
||||
_Checkpoint(1666909050, 1820000),
|
||||
_Checkpoint(1667510577, 1830000),
|
||||
_Checkpoint(1668111697, 1840000),
|
||||
_Checkpoint(1668711150, 1850000),
|
||||
_Checkpoint(1669309785, 1860000),
|
||||
_Checkpoint(1669910715, 1870000),
|
||||
_Checkpoint(1670511885, 1880000),
|
||||
_Checkpoint(1671111596, 1890000),
|
||||
_Checkpoint(1671713348, 1900000),
|
||||
_Checkpoint(1672312933, 1910000),
|
||||
_Checkpoint(1672913610, 1920000),
|
||||
_Checkpoint(1673517614, 1930000),
|
||||
_Checkpoint(1674116655, 1940000),
|
||||
_Checkpoint(1674717105, 1950000),
|
||||
_Checkpoint(1675316550, 1960000),
|
||||
_Checkpoint(1675914240, 1970000),
|
||||
_Checkpoint(1676519608, 1980000),
|
||||
_Checkpoint(1677113500, 1990000),
|
||||
_Checkpoint(1677715095, 2000000),
|
||||
_Checkpoint(1678316835, 2010000),
|
||||
_Checkpoint(1678912224, 2020000),
|
||||
_Checkpoint(1679513175, 2030000),
|
||||
_Checkpoint(1680112070, 2040000),
|
||||
_Checkpoint(1680711218, 2050000),
|
||||
_Checkpoint(1681313478, 2060000),
|
||||
_Checkpoint(1681909155, 2070000),
|
||||
_Checkpoint(1682507671, 2080000),
|
||||
_Checkpoint(1683107382, 2090000),
|
||||
_Checkpoint(1683712020, 2100000),
|
||||
_Checkpoint(1684311975, 2110000),
|
||||
_Checkpoint(1684915377, 2120000),
|
||||
_Checkpoint(1685514352, 2130000),
|
||||
_Checkpoint(1686112770, 2140000),
|
||||
_Checkpoint(1686710430, 2150000),
|
||||
_Checkpoint(1687309584, 2160000),
|
||||
_Checkpoint(1687916053, 2170000),
|
||||
_Checkpoint(1688521450, 2180000),
|
||||
_Checkpoint(1689118965, 2190000),
|
||||
_Checkpoint(1689719584, 2200000),
|
||||
_Checkpoint(1690321515, 2210000),
|
||||
_Checkpoint(1690920915, 2220000),
|
||||
_Checkpoint(1691524920, 2230000),
|
||||
_Checkpoint(1692120135, 2240000),
|
||||
_Checkpoint(1692715440, 2250000),
|
||||
_Checkpoint(1693313578, 2260000),
|
||||
_Checkpoint(1693915410, 2270000),
|
||||
_Checkpoint(1694516824, 2280000),
|
||||
_Checkpoint(1695114075, 2290000),
|
||||
_Checkpoint(1695712485, 2300000),
|
||||
_Checkpoint(1696314266, 2310000),
|
||||
_Checkpoint(1696913190, 2320000),
|
||||
_Checkpoint(1697513447, 2330000),
|
||||
_Checkpoint(1698115590, 2340000),
|
||||
_Checkpoint(1698715860, 2350000),
|
||||
_Checkpoint(1699318665, 2360000),
|
||||
_Checkpoint(1699918515, 2370000),
|
||||
_Checkpoint(1700510340, 2380000),
|
||||
_Checkpoint(1701107490, 2390000),
|
||||
_Checkpoint(1701715953, 2400000),
|
||||
_Checkpoint(1702319655, 2410000),
|
||||
_Checkpoint(1702921425, 2420000),
|
||||
_Checkpoint(1703518740, 2430000),
|
||||
_Checkpoint(1704117450, 2440000),
|
||||
_Checkpoint(1704715350, 2450000),
|
||||
_Checkpoint(1705314150, 2460000),
|
||||
_Checkpoint(1705911585, 2470000),
|
||||
_Checkpoint(1706513190, 2480000),
|
||||
_Checkpoint(1707111871, 2490000),
|
||||
_Checkpoint(1707712515, 2500000),
|
||||
_Checkpoint(1708316785, 2510000),
|
||||
_Checkpoint(1708917275, 2520000),
|
||||
_Checkpoint(1709515140, 2530000),
|
||||
_Checkpoint(1710115320, 2540000),
|
||||
_Checkpoint(1710718811, 2550000),
|
||||
_Checkpoint(1711340233, 2560000),
|
||||
_Checkpoint(1711937827, 2570000),
|
||||
_Checkpoint(1712536797, 2580000),
|
||||
_Checkpoint(1713132840, 2590000),
|
||||
_Checkpoint(1713732780, 2600000),
|
||||
_Checkpoint(1714330320, 2610000),
|
||||
_Checkpoint(1714933845, 2620000),
|
||||
_Checkpoint(1715536185, 2630000),
|
||||
_Checkpoint(1716146082, 2640000),
|
||||
_Checkpoint(1716742155, 2650000),
|
||||
_Checkpoint(1717343205, 2660000),
|
||||
_Checkpoint(1717937699, 2670000),
|
||||
_Checkpoint(1718535495, 2680000),
|
||||
_Checkpoint(1719141615, 2690000),
|
||||
_Checkpoint(1719744075, 2700000),
|
||||
_Checkpoint(1720336724, 2710000),
|
||||
_Checkpoint(1720941803, 2720000),
|
||||
_Checkpoint(1721539733, 2730000),
|
||||
_Checkpoint(1722139174, 2740000),
|
||||
_Checkpoint(1722737769, 2750000),
|
||||
_Checkpoint(1723336755, 2760000),
|
||||
_Checkpoint(1723937074, 2770000),
|
||||
_Checkpoint(1724533860, 2780000),
|
||||
_Checkpoint(1725126437, 2790000),
|
||||
_Checkpoint(1725728340, 2800000),
|
||||
_Checkpoint(1726330290, 2810000),
|
||||
_Checkpoint(1726931550, 2820000),
|
||||
_Checkpoint(1727531335, 2830000),
|
||||
_Checkpoint(1728132893, 2840000),
|
||||
_Checkpoint(1728731641, 2850000),
|
||||
_Checkpoint(1729328707, 2860000),
|
||||
_Checkpoint(1729927125, 2870000),
|
||||
_Checkpoint(1730525159, 2880000),
|
||||
_Checkpoint(1731124123, 2890000),
|
||||
_Checkpoint(1731728397, 2900000),
|
||||
_Checkpoint(1732328405, 2910000),
|
||||
_Checkpoint(1732929444, 2920000),
|
||||
_Checkpoint(1733527918, 2930000),
|
||||
_Checkpoint(1734125775, 2940000),
|
||||
_Checkpoint(1734721755, 2950000),
|
||||
_Checkpoint(1735326599, 2960000),
|
||||
_Checkpoint(1735919505, 2970000),
|
||||
_Checkpoint(1736520114, 2980000),
|
||||
_Checkpoint(1737119579, 2990000),
|
||||
_Checkpoint(1737724515, 3000000),
|
||||
_Checkpoint(1738328220, 3010000),
|
||||
_Checkpoint(1738929119, 3020000),
|
||||
_Checkpoint(1739527564, 3030000),
|
||||
_Checkpoint(1740125219, 3040000),
|
||||
_Checkpoint(1740726039, 3050000),
|
||||
_Checkpoint(1741327110, 3060000),
|
||||
_Checkpoint(1741927857, 3070000),
|
||||
_Checkpoint(1742530920, 3080000),
|
||||
_Checkpoint(1743149987, 3090000),
|
||||
_Checkpoint(1743747268, 3100000),
|
||||
_Checkpoint(1744349415, 3110000),
|
||||
_Checkpoint(1744944112, 3120000),
|
||||
_Checkpoint(1745543580, 3130000),
|
||||
_Checkpoint(1746142732, 3140000),
|
||||
_Checkpoint(1746742705, 3150000),
|
||||
_Checkpoint(1747344191, 3160000),
|
||||
_Checkpoint(1747946610, 3170000),
|
||||
_Checkpoint(1748545387, 3180000),
|
||||
_Checkpoint(1749144165, 3190000),
|
||||
_Checkpoint(1749742950, 3200000),
|
||||
_Checkpoint(1750343363, 3210000),
|
||||
_Checkpoint(1750946445, 3220000),
|
||||
_Checkpoint(1751545747, 3230000),
|
||||
_Checkpoint(1752144620, 3240000),
|
||||
_Checkpoint(1752746280, 3250000),
|
||||
_Checkpoint(1753343664, 3260000),
|
||||
_Checkpoint(1753948349, 3270000),
|
||||
_Checkpoint(1754547975, 3280000),
|
||||
_Checkpoint(1755145610, 3290000),
|
||||
_Checkpoint(1755744210, 3300000),
|
||||
_Checkpoint(1756341045, 3310000),
|
||||
_Checkpoint(1756940460, 3320000),
|
||||
_Checkpoint(1757537565, 3330000),
|
||||
_Checkpoint(1758141330, 3340000),
|
||||
_Checkpoint(1758742563, 3350000),
|
||||
_Checkpoint(1759340190, 3360000),
|
||||
_Checkpoint(1759941840, 3370000),
|
||||
_Checkpoint(1760542420, 3380000),
|
||||
_Checkpoint(1761144358, 3390000),
|
||||
_Checkpoint(1761745435, 3400000),
|
||||
_Checkpoint(1762345095, 3410000),
|
||||
_Checkpoint(1762942865, 3420000),
|
||||
_Checkpoint(1763540460, 3430000),
|
||||
_Checkpoint(1764144321, 3440000),
|
||||
_Checkpoint(1764745065, 3450000),
|
||||
_Checkpoint(1765347169, 3460000),
|
||||
_Checkpoint(1765944370, 3470000),
|
||||
_Checkpoint(1766548020, 3480000),
|
||||
_Checkpoint(1767144555, 3490000),
|
||||
_Checkpoint(1767748830, 3500000),
|
||||
_Checkpoint(1768350722, 3510000),
|
||||
_Checkpoint(1768945425, 3520000),
|
||||
_Checkpoint(1769545406, 3530000),
|
||||
_Checkpoint(1770144700, 3540000),
|
||||
_Checkpoint(1770745380, 3550000),
|
||||
_Checkpoint(1771345176, 3560000),
|
||||
_Checkpoint(1771943526, 3570000),
|
||||
_Checkpoint(1772545646, 3580000),
|
||||
_Checkpoint(1773146830, 3590000),
|
||||
_Checkpoint(1773749868, 3600000),
|
||||
_Checkpoint(1774347077, 3610000),
|
||||
_Checkpoint(1774950120, 3620000),
|
||||
_Checkpoint(1775548635, 3630000),
|
||||
_Checkpoint(1776148320, 3640000),
|
||||
_Checkpoint(1776750266, 3650000),
|
||||
_Checkpoint(1777351110, 3660000),
|
||||
_Checkpoint(1777953826, 3670000),
|
||||
_Checkpoint(1778551170, 3680000),
|
||||
_Checkpoint(1779153960, 3690000),
|
||||
_Checkpoint(1779758055, 3700000),
|
||||
_Checkpoint(1780362465, 3710000),
|
||||
_Checkpoint(1780966500, 3720000),
|
||||
_Checkpoint(1781563275, 3730000),
|
||||
_Checkpoint(1782174166, 3740000),
|
||||
_Checkpoint(1782775815, 3750000),
|
||||
_Checkpoint(1783378725, 3760000),
|
||||
_Checkpoint(1783971435, 3770000),
|
||||
_Checkpoint(1784575305, 3780000),
|
||||
_Checkpoint(1785177870, 3790000),
|
||||
_Checkpoint(1785774750, 3800000),
|
||||
_Checkpoint(1786377455, 3810000),
|
||||
_Checkpoint(1786978902, 3820000),
|
||||
];
|
||||
|
||||
static int getBlockHeightByTime(DateTime time) {
|
||||
final t = time.toUtc().millisecondsSinceEpoch;
|
||||
|
||||
if (_points.isEmpty) return 0;
|
||||
|
||||
if (t <= _points.first.timeMs) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _points.length - 1; i++) {
|
||||
final p0 = _points[i];
|
||||
final p1 = _points[i + 1];
|
||||
|
||||
if (t >= p0.timeMs && t < p1.timeMs) {
|
||||
return _interpolate(
|
||||
p0.height,
|
||||
p1.height,
|
||||
p0.timeMs,
|
||||
p1.timeMs,
|
||||
t,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final last = _points[_points.length - 1];
|
||||
final prev = _points[_points.length - 2];
|
||||
|
||||
final avgBlockTimeMs = (last.timeMs - prev.timeMs) / (last.height - prev.height);
|
||||
|
||||
final blocksSinceLast = ((t - last.timeMs) / avgBlockTimeMs).floor();
|
||||
|
||||
return last.height + blocksSinceLast;
|
||||
}
|
||||
|
||||
static DateTime getTimeByBlockHeight(int height) {
|
||||
if (_points.isEmpty) return DateTime.fromMillisecondsSinceEpoch(0, isUtc: true);
|
||||
if (height <= 1) {
|
||||
return DateTime.fromMillisecondsSinceEpoch(_points.first.timeMs, isUtc: true);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _points.length - 1; i++) {
|
||||
final p0 = _points[i];
|
||||
final p1 = _points[i + 1];
|
||||
if (height >= p0.height && height < p1.height) {
|
||||
final t = _interpolate(
|
||||
p0.timeMs,
|
||||
p1.timeMs,
|
||||
p0.height,
|
||||
p1.height,
|
||||
height,
|
||||
);
|
||||
return DateTime.fromMillisecondsSinceEpoch(t, isUtc: true);
|
||||
}
|
||||
}
|
||||
|
||||
final last = _points[_points.length - 1];
|
||||
final prev = _points[_points.length - 2];
|
||||
final avgBlockTimeMs = (last.timeMs - prev.timeMs) / (last.height - prev.height);
|
||||
final msSinceLast = ((height - last.height) * avgBlockTimeMs).floor();
|
||||
return DateTime.fromMillisecondsSinceEpoch(last.timeMs + msSinceLast, isUtc: true);
|
||||
}
|
||||
|
||||
static int _interpolate(
|
||||
int h0,
|
||||
int h1,
|
||||
int t0,
|
||||
int t1,
|
||||
int t,
|
||||
) {
|
||||
final ratio = (t - t0) / (t1 - t0);
|
||||
return h0 + ((h1 - h0) * ratio).floor();
|
||||
}
|
||||
}
|
||||
|
||||
class _Checkpoint {
|
||||
final int timeMs;
|
||||
final int height;
|
||||
|
||||
_Checkpoint(int timeSec, this.height) : timeMs = timeSec * 1000;
|
||||
}
|
||||
@@ -1,9 +1,18 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:monero/zano.dart' as zano;
|
||||
import 'package:cw_zano/api/model/get_address_info_result.dart';
|
||||
import 'package:cw_zano/get_height_by_date.dart';
|
||||
import 'package:monero/zano.dart' as zano;
|
||||
|
||||
class ZanoUtils {
|
||||
static int heightByDate(DateTime date) =>
|
||||
ZanoHeight.getBlockHeightByTime(date.toUtc().subtract(const Duration(days: 1)));
|
||||
|
||||
static int creationTimestampFromHeight(int height) {
|
||||
if (height <= 0) return 0;
|
||||
return ZanoHeight.getTimeByBlockHeight(height).millisecondsSinceEpoch ~/ 1000;
|
||||
}
|
||||
|
||||
static bool validateAddress(String address) {
|
||||
try {
|
||||
final result = GetAddressInfoResult.fromJson(
|
||||
|
||||
+274
-44
@@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:core';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
@@ -6,6 +7,7 @@ import 'dart:math';
|
||||
import 'package:cw_core/amount/money.dart';
|
||||
import 'package:cw_core/cake_hive.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/encryption_file_utils.dart';
|
||||
import 'package:cw_core/node.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/pending_transaction.dart';
|
||||
@@ -15,6 +17,7 @@ import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_credentials.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_keys_file.dart';
|
||||
import 'package:cw_core/zano_asset.dart';
|
||||
import 'package:cw_zano/api/model/create_wallet_result.dart';
|
||||
import 'package:cw_zano/api/model/destination.dart';
|
||||
@@ -32,7 +35,10 @@ import 'package:cw_zano/zano_wallet_addresses.dart';
|
||||
import 'package:cw_zano/zano_wallet_api.dart';
|
||||
import 'package:cw_zano/zano_wallet_exceptions.dart';
|
||||
import 'package:cw_zano/zano_wallet_service.dart';
|
||||
import 'package:cw_zano/zano_utils.dart';
|
||||
import 'package:cw_zano/api/model/balance.dart';
|
||||
import 'package:cw_zano/bip39_seed.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
@@ -42,10 +48,12 @@ class ZanoWallet = ZanoWalletBase with _$ZanoWallet;
|
||||
|
||||
abstract class ZanoWalletBase
|
||||
extends WalletBase<ZanoBalance, ZanoTransactionHistory, ZanoTransactionInfo>
|
||||
with Store, ZanoWalletApi {
|
||||
with Store, ZanoWalletApi, WalletKeysFile {
|
||||
static const int _autoSaveIntervalSeconds = 30;
|
||||
static const int _pollIntervalMilliseconds = 5000;
|
||||
static const int _maxLoadAssetsRetries = 5;
|
||||
static const int _walletStateReady = 2;
|
||||
static const String _cakeKeysFileSuffix = '.cw.keys';
|
||||
|
||||
@override
|
||||
void setPassword(String password) {
|
||||
@@ -54,10 +62,23 @@ abstract class ZanoWalletBase
|
||||
}
|
||||
|
||||
String _password;
|
||||
final EncryptionFileUtils _encryptionFileUtils;
|
||||
bool _didSyncSecrets = false;
|
||||
|
||||
@override
|
||||
String get password => _password;
|
||||
|
||||
@override
|
||||
Future<String> makeKeysFilePath() async => "${await makePath()}$_cakeKeysFileSuffix";
|
||||
|
||||
@override
|
||||
WalletKeysData get walletKeysData => WalletKeysData(
|
||||
mnemonic: _hasSeed ? seed : null,
|
||||
passphrase: (passphrase ?? '').isEmpty ? null : passphrase,
|
||||
);
|
||||
|
||||
bool get _hasSeed => seed.trim().isNotEmpty;
|
||||
|
||||
@override
|
||||
Future<String> signMessage(String message, {String? address = null}) =>
|
||||
super.signMessage(message, address: address);
|
||||
@@ -105,7 +126,8 @@ abstract class ZanoWalletBase
|
||||
/// number of transactions in each request
|
||||
static final int _txChunkSize = (pow(2, 32) - 1).toInt();
|
||||
|
||||
ZanoWalletBase(WalletInfo walletInfo, DerivationInfo derivationInfo, String password)
|
||||
ZanoWalletBase(WalletInfo walletInfo, DerivationInfo derivationInfo, String password,
|
||||
this._encryptionFileUtils)
|
||||
: balance = ObservableMap.of({CryptoCurrency.zano: ZanoBalance.empty(CryptoCurrency.zano)}),
|
||||
_isTransactionUpdating = false,
|
||||
_hasSyncAfterStartup = false,
|
||||
@@ -126,74 +148,138 @@ abstract class ZanoWalletBase
|
||||
@override
|
||||
Future<void> changePassword(String password) async {
|
||||
setPassword(password);
|
||||
if (_hasSeed) {
|
||||
await saveKeysFile(_password, _encryptionFileUtils);
|
||||
saveKeysFile(_password, _encryptionFileUtils, true);
|
||||
}
|
||||
}
|
||||
|
||||
static Future<ZanoWallet> create({required WalletCredentials credentials}) async {
|
||||
static Future<ZanoWallet> create({
|
||||
required WalletCredentials credentials,
|
||||
required EncryptionFileUtils encryptionFileUtils,
|
||||
}) async {
|
||||
final wallet = ZanoWallet(credentials.walletInfo!,
|
||||
await credentials.walletInfo!.getDerivationInfo(), credentials.password!);
|
||||
await credentials.walletInfo!.getDerivationInfo(), credentials.password!, encryptionFileUtils);
|
||||
await wallet.initWallet();
|
||||
final path = await pathForWallet(name: credentials.name, type: credentials.walletInfo!.type);
|
||||
final createWalletResult = await wallet.createWallet(path, credentials.password!);
|
||||
final strength = credentials.seedPhraseLength == 24 ? 256 : 128;
|
||||
final providedMnemonic =
|
||||
credentials is ZanoNewWalletCredentials ? credentials.mnemonic : null;
|
||||
final mnemonic = providedMnemonic ?? generateBip39Mnemonic(strength: strength);
|
||||
final passphrase = credentials.passphrase ?? '';
|
||||
final secretDerivation = getSecretDerivationFromBip39(mnemonic, passphrase: passphrase);
|
||||
final creationTimestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
final createWalletResult = await wallet.restoreWalletFromDerivations(
|
||||
path,
|
||||
credentials.password!,
|
||||
secretDerivation,
|
||||
creationTimestamp: creationTimestamp,
|
||||
);
|
||||
await wallet.initWallet();
|
||||
wallet.seed = mnemonic;
|
||||
wallet.passphrase = passphrase;
|
||||
await wallet.parseCreateWalletResult(createWalletResult);
|
||||
if (credentials.passphrase != null) {
|
||||
await wallet.setPassphrase(credentials.passphrase!);
|
||||
wallet.seed = await createWalletResult.seed(wallet);
|
||||
wallet.passphrase = await wallet.getPassphrase();
|
||||
}
|
||||
await wallet._syncSecretsAndDerivation();
|
||||
await wallet.init(createWalletResult.wi.address);
|
||||
await wallet.save();
|
||||
return wallet;
|
||||
}
|
||||
|
||||
static Future<ZanoWallet> restore(
|
||||
{required ZanoRestoreWalletFromSeedCredentials credentials}) async {
|
||||
static Future<ZanoWallet> restore({
|
||||
required ZanoRestoreWalletFromSeedCredentials credentials,
|
||||
required EncryptionFileUtils encryptionFileUtils,
|
||||
}) async {
|
||||
final wallet = ZanoWallet(credentials.walletInfo!,
|
||||
await credentials.walletInfo!.getDerivationInfo(), credentials.password!);
|
||||
await credentials.walletInfo!.getDerivationInfo(), credentials.password!, encryptionFileUtils);
|
||||
await wallet.initWallet();
|
||||
final path = await pathForWallet(name: credentials.name, type: credentials.walletInfo!.type);
|
||||
final createWalletResult = await wallet.restoreWalletFromSeed(
|
||||
path, credentials.password!, credentials.mnemonic, credentials.passphrase);
|
||||
await wallet.initWallet();
|
||||
await wallet.parseCreateWalletResult(createWalletResult);
|
||||
if (credentials.passphrase != null) {
|
||||
await wallet.setPassphrase(credentials.passphrase!);
|
||||
wallet.seed = await createWalletResult.seed(wallet);
|
||||
wallet.passphrase = await wallet.getPassphrase();
|
||||
final passphrase = credentials.passphrase ?? '';
|
||||
final CreateWalletResult createWalletResult;
|
||||
final isBip39 = isBip39Seed(credentials.mnemonic);
|
||||
final creationTimestamp = ZanoUtils.creationTimestampFromHeight(credentials.height ?? 0);
|
||||
if (isBip39) {
|
||||
final secretDerivation =
|
||||
getSecretDerivationFromBip39(credentials.mnemonic, passphrase: passphrase);
|
||||
createWalletResult = await wallet.restoreWalletFromDerivations(
|
||||
path,
|
||||
credentials.password!,
|
||||
secretDerivation,
|
||||
creationTimestamp: creationTimestamp,
|
||||
);
|
||||
} else {
|
||||
createWalletResult = await wallet.restoreWalletFromSeed(
|
||||
path,
|
||||
credentials.password!,
|
||||
credentials.mnemonic,
|
||||
credentials.passphrase,
|
||||
creationTimestamp: creationTimestamp,
|
||||
);
|
||||
}
|
||||
await wallet.initWallet();
|
||||
wallet.seed = credentials.mnemonic;
|
||||
wallet.passphrase = passphrase;
|
||||
await wallet.parseCreateWalletResult(createWalletResult);
|
||||
if (!isBip39) {
|
||||
try {
|
||||
if (passphrase.isNotEmpty) {
|
||||
await wallet.setPassphrase(passphrase);
|
||||
}
|
||||
final nativeSeed = await createWalletResult.seed(wallet);
|
||||
if (nativeSeed.isNotEmpty) {
|
||||
wallet.seed = nativeSeed;
|
||||
}
|
||||
} catch (e) {
|
||||
printV('native seed not available yet: $e');
|
||||
}
|
||||
}
|
||||
await wallet._syncSecretsAndDerivation();
|
||||
await wallet.init(createWalletResult.wi.address);
|
||||
await wallet.save();
|
||||
return wallet;
|
||||
}
|
||||
|
||||
static Future<ZanoWallet> open(
|
||||
{required String name, required String password, required WalletInfo walletInfo}) async {
|
||||
{required String name,
|
||||
required String password,
|
||||
required WalletInfo walletInfo,
|
||||
required EncryptionFileUtils encryptionFileUtils}) async {
|
||||
final path = await pathForWallet(name: name, type: walletInfo.type);
|
||||
final wallet =
|
||||
ZanoWallet(walletInfo, await walletInfo.getDerivationInfo(), password, encryptionFileUtils);
|
||||
|
||||
await wallet._loadKeysFileIfPresent();
|
||||
|
||||
late final CreateWalletResult createWalletResult;
|
||||
if (ZanoWalletApi.openWalletCache[path] != null) {
|
||||
final wallet = ZanoWallet(walletInfo, await walletInfo.getDerivationInfo(), password);
|
||||
await wallet.parseCreateWalletResult(ZanoWalletApi.openWalletCache[path]!).then((_) {
|
||||
unawaited(wallet.init(ZanoWalletApi.openWalletCache[path]!.wi.address));
|
||||
});
|
||||
return wallet;
|
||||
createWalletResult = ZanoWalletApi.openWalletCache[path]!;
|
||||
} else {
|
||||
final wallet = ZanoWallet(walletInfo, await walletInfo.getDerivationInfo(), password);
|
||||
await wallet.initWallet();
|
||||
final createWalletResult = await wallet.loadWallet(path, password);
|
||||
await wallet.parseCreateWalletResult(createWalletResult).then((_) {
|
||||
unawaited(wallet.init(createWalletResult.wi.address));
|
||||
});
|
||||
return wallet;
|
||||
createWalletResult = await wallet.loadWallet(path, password);
|
||||
}
|
||||
await wallet.parseCreateWalletResult(createWalletResult);
|
||||
if (!wallet._hasSeed) {
|
||||
await wallet._loadSeedIfAvailable();
|
||||
}
|
||||
await wallet._syncSecretsAndDerivation();
|
||||
unawaited(wallet.init(createWalletResult.wi.address));
|
||||
return wallet;
|
||||
}
|
||||
|
||||
Future<void> parseCreateWalletResult(CreateWalletResult result) async {
|
||||
hWallet = result.walletId;
|
||||
seed = await result.seed(this);
|
||||
keys = ZanoWalletKeys(
|
||||
privateSpendKey: result.privateSpendKey,
|
||||
privateViewKey: result.privateViewKey,
|
||||
publicSpendKey: result.publicSpendKey,
|
||||
publicViewKey: result.publicViewKey,
|
||||
);
|
||||
passphrase = await getPassphrase();
|
||||
if ((passphrase ?? '').isEmpty) {
|
||||
try {
|
||||
passphrase = await getPassphrase();
|
||||
} catch (e) {
|
||||
printV('passphrase not available yet: $e');
|
||||
}
|
||||
}
|
||||
|
||||
printV('setting hWallet = ${result.walletId}');
|
||||
walletAddresses.address = result.wi.address;
|
||||
@@ -214,6 +300,126 @@ abstract class ZanoWalletBase
|
||||
}
|
||||
}
|
||||
|
||||
bool _isWalletReady(GetWalletStatusResult walletStatus) =>
|
||||
!walletStatus.isInLongRefresh && walletStatus.walletState == _walletStateReady;
|
||||
|
||||
Future<bool> _hasKeysFile() async {
|
||||
try {
|
||||
final path = await makeKeysFilePath();
|
||||
return File(path).existsSync() || File('$path.backup').existsSync();
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadKeysFileIfPresent() async {
|
||||
if (!await _hasKeysFile()) {
|
||||
return;
|
||||
}
|
||||
final path = await makeKeysFilePath();
|
||||
Future<WalletKeysData> read(String readPath) async {
|
||||
final jsonSource = await _encryptionFileUtils.read(path: readPath, password: _password);
|
||||
return WalletKeysData.fromJSON(json.decode(jsonSource) as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
try {
|
||||
WalletKeysData keysData;
|
||||
if (File(path).existsSync()) {
|
||||
keysData = await read(path);
|
||||
} else {
|
||||
keysData = await read('$path.backup');
|
||||
await saveKeysFile(_password, _encryptionFileUtils);
|
||||
}
|
||||
if (keysData.mnemonic != null && keysData.mnemonic!.trim().isNotEmpty) {
|
||||
seed = keysData.mnemonic!;
|
||||
}
|
||||
if (keysData.passphrase != null && keysData.passphrase!.isNotEmpty) {
|
||||
passphrase = keysData.passphrase;
|
||||
}
|
||||
} catch (e) {
|
||||
printV('error reading zano keys file $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _saveKeysFileIfNeeded() async {
|
||||
if (!_hasSeed || await _hasKeysFile()) {
|
||||
return;
|
||||
}
|
||||
await saveKeysFile(_password, _encryptionFileUtils);
|
||||
saveKeysFile(_password, _encryptionFileUtils, true);
|
||||
}
|
||||
|
||||
Future<void> _loadSeedIfAvailable() async {
|
||||
if (!isBip39Seed(seed)) {
|
||||
try {
|
||||
final loaded = await getSeed();
|
||||
if (loaded.isNotEmpty) {
|
||||
seed = loaded;
|
||||
}
|
||||
} catch (e) {
|
||||
printV('seed not available yet: $e');
|
||||
}
|
||||
}
|
||||
if ((passphrase ?? '').isEmpty) {
|
||||
try {
|
||||
passphrase = await getPassphrase() ?? passphrase;
|
||||
} catch (e) {
|
||||
printV('passphrase not available yet: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _syncSecretsAndDerivation() async {
|
||||
if (!_hasSeed || _didSyncSecrets) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await _persistSecretsIfNeeded();
|
||||
await _setDerivationForSeed();
|
||||
await _saveKeysFileIfNeeded();
|
||||
_didSyncSecrets = true;
|
||||
} catch (e) {
|
||||
printV('error persisting zano secrets $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _persistSecretsIfNeeded() async {
|
||||
if (isBip39Seed(seed) && await getBip39Mnemonic() == null) {
|
||||
await setBip39Secrets(
|
||||
mnemonic: seed,
|
||||
creationTimestamp: walletInfo.restoreHeight > 0
|
||||
? ZanoUtils.creationTimestampFromHeight(walletInfo.restoreHeight)
|
||||
: DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
||||
);
|
||||
}
|
||||
if ((passphrase ?? '').isNotEmpty && await getPassphrase() == null) {
|
||||
await setPassphrase(passphrase!);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _setDerivationForSeed() async {
|
||||
if (!_hasSeed) {
|
||||
return;
|
||||
}
|
||||
final di = await walletInfo.getDerivationInfo();
|
||||
if (isBip39Seed(seed)) {
|
||||
if (di.derivationType == DerivationType.bip39 &&
|
||||
(di.derivationPath ?? '').isNotEmpty) {
|
||||
return;
|
||||
}
|
||||
di.derivationType = DerivationType.bip39;
|
||||
di.derivationPath = "m/44'/128'/0'/0/0";
|
||||
await di.save();
|
||||
return;
|
||||
}
|
||||
if (di.derivationType != DerivationType.bip39 && di.derivationPath == 'legacy') {
|
||||
return;
|
||||
}
|
||||
di.derivationType = DerivationType.unknown;
|
||||
di.derivationPath = 'legacy';
|
||||
await di.save();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close({bool shouldCleanup = true}) async {
|
||||
closeWallet(null);
|
||||
@@ -310,12 +516,13 @@ abstract class ZanoWalletBase
|
||||
Future<Map<String, ZanoTransactionInfo>> fetchTransactions() async {
|
||||
try {
|
||||
final transfers = <Transfer>[];
|
||||
var offset = 0;
|
||||
late GetRecentTxsAndInfoResult result;
|
||||
do {
|
||||
result = await getRecentTxsAndInfo(offset: 0, count: _txChunkSize);
|
||||
// _lastTxIndex += result.transfers.length;
|
||||
result = await getRecentTxsAndInfo(offset: offset, count: _txChunkSize);
|
||||
transfers.addAll(result.transfers);
|
||||
} while (result.lastItemIndex + 1 < result.totalTransfers);
|
||||
offset = result.lastItemIndex + 1;
|
||||
} while (offset < result.totalTransfers);
|
||||
return Transfer.makeMap(transfers, zanoAssets, currentDaemonHeight);
|
||||
} catch (e) {
|
||||
printV((e.toString()));
|
||||
@@ -334,12 +541,18 @@ abstract class ZanoWalletBase
|
||||
|
||||
@override
|
||||
Future<void> renameWalletFiles(String newWalletName) async {
|
||||
final currentWalletPath = await pathForWallet(name: name, type: type);
|
||||
final currentWalletDirPath = await pathForWalletDir(name: name, type: type);
|
||||
final currentWalletPath = '$currentWalletDirPath/$name';
|
||||
final currentCacheFile = File(currentWalletPath);
|
||||
final currentKeysFile = File('$currentWalletPath.keys');
|
||||
final currentAddressListFile = File('$currentWalletPath.address.txt');
|
||||
final currentPendingKiFile = File('$currentWalletPath.outkey2ki');
|
||||
final currentSecretsFile = File(p.join(currentWalletDirPath, 'zano-secrets.json.bin'));
|
||||
final currentCakeKeysFile = File('$currentWalletPath$_cakeKeysFileSuffix');
|
||||
final currentCakeKeysBackupFile = File('$currentWalletPath$_cakeKeysFileSuffix.backup');
|
||||
|
||||
final newWalletPath = await pathForWallet(name: newWalletName, type: type);
|
||||
final newWalletDirPath = await pathForWalletDir(name: newWalletName, type: type);
|
||||
final newWalletPath = '$newWalletDirPath/$newWalletName';
|
||||
|
||||
// Copies current wallet files into new wallet name's dir and files
|
||||
if (currentCacheFile.existsSync()) {
|
||||
@@ -351,9 +564,22 @@ abstract class ZanoWalletBase
|
||||
if (currentAddressListFile.existsSync()) {
|
||||
await currentAddressListFile.copy('$newWalletPath.address.txt');
|
||||
}
|
||||
if (currentPendingKiFile.existsSync()) {
|
||||
await currentPendingKiFile.copy('$newWalletPath.outkey2ki');
|
||||
}
|
||||
if (currentSecretsFile.existsSync()) {
|
||||
await currentSecretsFile.copy(p.join(newWalletDirPath, 'zano-secrets.json.bin'));
|
||||
}
|
||||
if (currentCakeKeysFile.existsSync()) {
|
||||
await currentCakeKeysFile.copy('$newWalletPath$_cakeKeysFileSuffix');
|
||||
}
|
||||
if (currentCakeKeysBackupFile.existsSync()) {
|
||||
await currentCakeKeysBackupFile.copy('$newWalletPath$_cakeKeysFileSuffix.backup');
|
||||
}
|
||||
|
||||
// Delete old name's dir and files
|
||||
await Directory(currentWalletPath).delete(recursive: true);
|
||||
// Delete the old wallet *directory*. pathForWallet() is the wallet file
|
||||
// (.../<name>/<name>); Directory(filePath).delete leaves seed sidecars.
|
||||
await Directory(currentWalletDirPath).delete(recursive: true);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -362,6 +588,7 @@ abstract class ZanoWalletBase
|
||||
@override
|
||||
Future<void> save() async {
|
||||
try {
|
||||
await _saveKeysFileIfNeeded();
|
||||
await store();
|
||||
await walletAddresses.updateAddressesInBox();
|
||||
} catch (e) {
|
||||
@@ -544,9 +771,12 @@ abstract class ZanoWalletBase
|
||||
_updateSyncProgress(walletStatus);
|
||||
|
||||
// we can call getWalletInfo ONLY if getWalletStatus returns NOT is in long refresh and wallet state is 2 (ready)
|
||||
if (!walletStatus.isInLongRefresh && walletStatus.walletState == 2) {
|
||||
if (_isWalletReady(walletStatus)) {
|
||||
if (!_hasSeed) {
|
||||
await _loadSeedIfAvailable();
|
||||
}
|
||||
await _syncSecretsAndDerivation();
|
||||
final walletInfo = await getWalletInfo();
|
||||
seed = await walletInfo.wiExtended.seed(this);
|
||||
keys = ZanoWalletKeys(
|
||||
privateSpendKey: walletInfo.wiExtended.spendPrivateKey,
|
||||
privateViewKey: walletInfo.wiExtended.viewPrivateKey,
|
||||
|
||||
@@ -46,12 +46,13 @@ mixin ZanoWalletApi {
|
||||
|
||||
void setPassword(String password) => zano.PlainWallet_resetWalletPassword(hWallet, password);
|
||||
|
||||
void closeWallet(int? walletToClose, {bool force = false}) async {
|
||||
Future<void> closeWallet(int? walletToClose, {bool force = false}) async {
|
||||
printV('close_wallet ${walletToClose ?? hWallet}: $force');
|
||||
if (Platform.isWindows || force) {
|
||||
final result = await _closeWallet(walletToClose ?? hWallet);
|
||||
final id = walletToClose ?? hWallet;
|
||||
final result = await _closeWallet(id);
|
||||
printV('close_wallet result $result');
|
||||
openWalletCache.removeWhere((_, cwr) => cwr.walletId == (walletToClose ?? hWallet));
|
||||
openWalletCache.removeWhere((_, cwr) => cwr.walletId == id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,31 +77,34 @@ mixin ZanoWalletApi {
|
||||
|
||||
Future<File> _getWalletSecretsFile() async {
|
||||
final dir = await getWalletDir();
|
||||
final file = File(p.join(dir.path, "zano-secrets.json.bin"));
|
||||
return file;
|
||||
return File(p.join(dir.path, 'zano-secrets.json.bin'));
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> _getSecrets() async {
|
||||
final file = await _getWalletSecretsFile();
|
||||
if (!file.existsSync()) {
|
||||
try {
|
||||
final file = await _getWalletSecretsFile();
|
||||
if (!file.existsSync()) {
|
||||
return {};
|
||||
}
|
||||
final data = file.readAsBytesSync();
|
||||
final b64 = convert.base64.encode(data);
|
||||
final respStr = await invokeMethod('decrypt_data', {'buff': b64});
|
||||
final resp = convert.json.decode(respStr);
|
||||
final dataBytes = convert.base64.decode(resp['result']['res_buff'] as String);
|
||||
final dataStr = convert.utf8.decode(dataBytes);
|
||||
return convert.json.decode(dataStr) as Map<String, dynamic>;
|
||||
} catch (e) {
|
||||
printV('error reading zano secrets $e');
|
||||
return {};
|
||||
}
|
||||
final data = file.readAsBytesSync();
|
||||
final b64 = convert.base64.encode(data);
|
||||
final respStr = await invokeMethod("decrypt_data", {"buff": "$b64"});
|
||||
final resp = convert.json.decode(respStr);
|
||||
final dataBytes = convert.base64.decode(resp["result"]["res_buff"] as String);
|
||||
final dataStr = convert.utf8.decode(dataBytes);
|
||||
final dataObject = convert.json.decode(dataStr);
|
||||
return dataObject as Map<String, dynamic>;
|
||||
}
|
||||
|
||||
Future<void> _setSecrets(Map<String, dynamic> data) async {
|
||||
final dataStr = convert.json.encode(data);
|
||||
final b64 = convert.base64.encode(convert.utf8.encode(dataStr));
|
||||
final respStr = await invokeMethod("encrypt_data", {"buff": "$b64"});
|
||||
final respStr = await invokeMethod('encrypt_data', {'buff': b64});
|
||||
final resp = convert.json.decode(respStr);
|
||||
final dataBytes = convert.base64.decode(resp["result"]["res_buff"] as String);
|
||||
final dataBytes = convert.base64.decode(resp['result']['res_buff'] as String);
|
||||
final file = await _getWalletSecretsFile();
|
||||
file.writeAsBytesSync(dataBytes);
|
||||
}
|
||||
@@ -124,7 +128,25 @@ mixin ZanoWalletApi {
|
||||
return _setWalletSecret("passphrase", passphrase);
|
||||
}
|
||||
|
||||
Future<String?> getBip39Mnemonic() async {
|
||||
return await _getWalletSecret("bip39_mnemonic");
|
||||
}
|
||||
|
||||
Future<void> setBip39Secrets({
|
||||
required String mnemonic,
|
||||
required int creationTimestamp,
|
||||
}) async {
|
||||
final secrets = await _getSecrets();
|
||||
secrets["bip39_mnemonic"] = mnemonic;
|
||||
secrets["creation_timestamp"] = creationTimestamp.toString();
|
||||
await _setSecrets(secrets);
|
||||
}
|
||||
|
||||
Future<String> getSeed() async {
|
||||
final bip39Mnemonic = await getBip39Mnemonic();
|
||||
if (bip39Mnemonic != null && bip39Mnemonic.isNotEmpty) {
|
||||
return bip39Mnemonic;
|
||||
}
|
||||
final passphrase = await getPassphrase();
|
||||
final respStr = await invokeMethod("get_restore_info", {"seed_password": passphrase ?? ""});
|
||||
final resp = convert.json.decode(respStr);
|
||||
@@ -328,10 +350,59 @@ mixin ZanoWalletApi {
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<CreateWalletResult> restoreWalletFromDerivations(
|
||||
String path,
|
||||
String password,
|
||||
String secretDerivation, {
|
||||
bool isAuditable = false,
|
||||
required int creationTimestamp,
|
||||
}) async {
|
||||
printV('restore_wallet_from_derivations path $path');
|
||||
final params = jsonEncode({
|
||||
"creation_timestamp": creationTimestamp,
|
||||
"is_auditable": isAuditable,
|
||||
"pass": password,
|
||||
"path": path,
|
||||
"secret_derivation": secretDerivation,
|
||||
});
|
||||
final json = await callSyncMethod('restore_from_derivations', 0, params);
|
||||
final map = jsonDecode(json) as Map<String, dynamic>?;
|
||||
if (map?['error'] != null) {
|
||||
final code = map!['error']!['code'] ?? '';
|
||||
final message = map['error']!['message'] ?? '';
|
||||
if (code == Consts.errorWrongSeed) {
|
||||
throw RestoreFromSeedsException(
|
||||
'Error restoring wallet\nPlease check the seed words are correct. Additionally, if you created this wallet with a passphrase please add it under the Advanced Settings page.');
|
||||
} else if (code == Consts.errorAlreadyExists) {
|
||||
throw RestoreFromSeedsException('Error restoring wallet, already exists');
|
||||
}
|
||||
throw RestoreFromSeedsException('Error restoring wallet, $message ($code)');
|
||||
}
|
||||
if (map?['result'] == null) {
|
||||
throw RestoreFromSeedsException('Error restoring wallet, empty response');
|
||||
}
|
||||
final result = CreateWalletResult.fromJson(map!['result'] as Map<String, dynamic>);
|
||||
openWalletCache[path] = result;
|
||||
printV('restore_wallet_from_derivations ${result.name} ${result.wi.address}');
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<CreateWalletResult> restoreWalletFromSeed(
|
||||
String path, String password, String seed, String? passphrase) async {
|
||||
String path,
|
||||
String password,
|
||||
String seed,
|
||||
String? passphrase, {
|
||||
required int creationTimestamp,
|
||||
}) async {
|
||||
printV('restore_wallet path $path');
|
||||
final json = zano.PlainWallet_restore(seed, path, password, passphrase ?? '');
|
||||
final params = jsonEncode({
|
||||
"creation_timestamp": creationTimestamp,
|
||||
"pass": password,
|
||||
"path": path,
|
||||
"seed_phrase": seed,
|
||||
"seed_pass": passphrase ?? '',
|
||||
});
|
||||
final json = await callSyncMethod('restore', 0, params);
|
||||
final map = jsonDecode(json) as Map<String, dynamic>?;
|
||||
if (map?['error'] != null) {
|
||||
final code = map!['error']!['code'] ?? '';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:cw_core/encryption_file_utils.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
@@ -14,8 +15,14 @@ import 'package:hive/hive.dart';
|
||||
import 'package:monero/zano.dart' as zano;
|
||||
|
||||
class ZanoNewWalletCredentials extends WalletCredentials {
|
||||
ZanoNewWalletCredentials({required String name, String? password, required String? passphrase})
|
||||
: super(name: name, password: password, passphrase: passphrase);
|
||||
ZanoNewWalletCredentials({
|
||||
required String name,
|
||||
String? password,
|
||||
required String? passphrase,
|
||||
this.mnemonic,
|
||||
}) : super(name: name, password: password, passphrase: passphrase);
|
||||
|
||||
final String? mnemonic;
|
||||
}
|
||||
|
||||
class ZanoRestoreWalletFromSeedCredentials extends WalletCredentials {
|
||||
@@ -52,7 +59,9 @@ class ZanoWalletService extends WalletService<
|
||||
ZanoRestoreWalletFromSeedCredentials,
|
||||
ZanoRestoreWalletFromKeysCredentials,
|
||||
ZanoNewWalletCredentials> {
|
||||
ZanoWalletService();
|
||||
ZanoWalletService(this.isDirect);
|
||||
|
||||
final bool isDirect;
|
||||
|
||||
static bool walletFilesExist(String path) =>
|
||||
!File(path).existsSync() && !File('$path.keys').existsSync();
|
||||
@@ -65,7 +74,8 @@ class ZanoWalletService extends WalletService<
|
||||
@override
|
||||
Future<ZanoWallet> create(WalletCredentials credentials, {bool? isTestnet}) async {
|
||||
printV('zanowallet service create isTestnet $isTestnet');
|
||||
return await ZanoWalletBase.create(credentials: credentials);
|
||||
return await ZanoWalletBase.create(
|
||||
credentials: credentials, encryptionFileUtils: encryptionFileUtilsFor(isDirect));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -82,12 +92,21 @@ class ZanoWalletService extends WalletService<
|
||||
}
|
||||
try {
|
||||
final wallet =
|
||||
await ZanoWalletBase.open(name: name, password: password, walletInfo: walletInfo);
|
||||
await ZanoWalletBase.open(
|
||||
name: name,
|
||||
password: password,
|
||||
walletInfo: walletInfo,
|
||||
encryptionFileUtils: encryptionFileUtilsFor(isDirect));
|
||||
saveBackup(name);
|
||||
return wallet;
|
||||
} catch (e) {
|
||||
printV('openWallet $name failed: $e');
|
||||
await restoreWalletFilesFromBackup(name);
|
||||
return await ZanoWalletBase.open(name: name, password: password, walletInfo: walletInfo);
|
||||
return await ZanoWalletBase.open(
|
||||
name: name,
|
||||
password: password,
|
||||
walletInfo: walletInfo,
|
||||
encryptionFileUtils: encryptionFileUtilsFor(isDirect));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,15 +134,24 @@ class ZanoWalletService extends WalletService<
|
||||
throw Exception('Wallet not found');
|
||||
}
|
||||
final currentWallet =
|
||||
ZanoWallet(currentWalletInfo, await currentWalletInfo.getDerivationInfo(), password);
|
||||
ZanoWallet(currentWalletInfo, await currentWalletInfo.getDerivationInfo(), password,
|
||||
encryptionFileUtilsFor(isDirect));
|
||||
|
||||
final oldPath = await pathForWallet(name: currentName, type: getType());
|
||||
final cached = ZanoWalletApi.openWalletCache.remove(oldPath);
|
||||
if (cached != null) {
|
||||
currentWallet.hWallet = cached.walletId;
|
||||
await currentWallet.closeWallet(cached.walletId, force: true);
|
||||
}
|
||||
|
||||
await currentWallet.renameWalletFiles(newName);
|
||||
|
||||
final newWalletInfo = currentWalletInfo;
|
||||
newWalletInfo.id = WalletBase.idFor(newName, getType());
|
||||
newWalletInfo.name = newName;
|
||||
|
||||
await newWalletInfo.save();
|
||||
final newDirPath = await pathForWalletDir(name: newName, type: getType());
|
||||
currentWalletInfo.id = WalletBase.idFor(newName, getType());
|
||||
currentWalletInfo.name = newName;
|
||||
currentWalletInfo.dirPath = newDirPath;
|
||||
currentWalletInfo.path = '$newDirPath/$newName';
|
||||
await currentWalletInfo.save();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -135,7 +163,8 @@ class ZanoWalletService extends WalletService<
|
||||
@override
|
||||
Future<ZanoWallet> restoreFromSeed(ZanoRestoreWalletFromSeedCredentials credentials,
|
||||
{bool? isTestnet}) async {
|
||||
return ZanoWalletBase.restore(credentials: credentials);
|
||||
return ZanoWalletBase.restore(
|
||||
credentials: credentials, encryptionFileUtils: encryptionFileUtilsFor(isDirect));
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -11,6 +11,8 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
bip39: ^1.0.6
|
||||
bip32: ^2.0.0
|
||||
ffi: ^2.0.1
|
||||
http: ^1.1.0
|
||||
path_provider: ^2.0.11
|
||||
@@ -25,7 +27,7 @@ dependencies:
|
||||
monero:
|
||||
git:
|
||||
url: https://github.com/mrcyjanek/monero_c.git
|
||||
ref: 3bfb3856a838f2bf6b729501837bb0295dedf25d
|
||||
ref: cd4fe366cc8d3c188c91de279f43b29c0e044b15
|
||||
path: impls/monero.dart
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import 'package:cw_zano/bip39_seed.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group("Zano bip39 secret derivation", () {
|
||||
group("Test Wallet 1", () {
|
||||
final bip39Seed =
|
||||
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
|
||||
final expectedSecretDerivation =
|
||||
"bfafd1eb0e43da200c5c11537d355e458e7c326b3bc1b19f4546573d6bac9d0f";
|
||||
final expectedSecretDerivationWithPassphrase =
|
||||
"674ba1caeaf8a79e66a026858c78d4e565032953e98d39bdea12559bcae86a0c";
|
||||
|
||||
test("Get secret derivation from bip39", () {
|
||||
final secretDerivation = getSecretDerivationFromBip39(bip39Seed);
|
||||
expect(secretDerivation, expectedSecretDerivation);
|
||||
});
|
||||
|
||||
test("Get secret derivation from bip39 with passphrase", () {
|
||||
final secretDerivation =
|
||||
getSecretDerivationFromBip39(bip39Seed, passphrase: 'TREZOR');
|
||||
expect(secretDerivation, expectedSecretDerivationWithPassphrase);
|
||||
});
|
||||
});
|
||||
|
||||
group("Test Wallet 2", () {
|
||||
final bip39Seed =
|
||||
'melt veteran patrol echo miss fat wrap apple crowd eyebrow weird boring';
|
||||
final expectedSecretDerivation =
|
||||
"8b2693e1d60b0431e3208762bc8a3f232890f50a3fea1e9605ec10a86afe1800";
|
||||
|
||||
test("Get secret derivation from bip39", () {
|
||||
final secretDerivation = getSecretDerivationFromBip39(bip39Seed);
|
||||
expect(secretDerivation, expectedSecretDerivation);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
+49
-1
@@ -1,9 +1,15 @@
|
||||
PODS:
|
||||
- bitbox_flutter (0.0.1):
|
||||
- Flutter
|
||||
- breez_sdk_spark_flutter (0.23.0):
|
||||
- Flutter
|
||||
- connectivity_plus (0.0.1):
|
||||
- Flutter
|
||||
- CryptoSwift (1.8.4)
|
||||
- cw_decred (0.0.1):
|
||||
- Flutter
|
||||
- cw_mweb (0.0.1):
|
||||
- Flutter
|
||||
- device_display_brightness (0.0.1):
|
||||
- Flutter
|
||||
- device_info_plus (0.0.1):
|
||||
@@ -61,6 +67,8 @@ PODS:
|
||||
- Flutter
|
||||
- flutter_mailer (0.0.1):
|
||||
- Flutter
|
||||
- flutter_native_splash (2.4.3):
|
||||
- Flutter
|
||||
- flutter_secure_storage (6.0.0):
|
||||
- Flutter
|
||||
- fluttertoast (0.0.2):
|
||||
@@ -71,9 +79,13 @@ PODS:
|
||||
- Flutter
|
||||
- integration_test (0.0.1):
|
||||
- Flutter
|
||||
- local_auth_darwin (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- OrderedSet (6.0.3)
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- payjoin_flutter (0.23.0)
|
||||
- permission_handler_apple (9.4.8):
|
||||
- Flutter
|
||||
- quick_actions_ios (0.0.1):
|
||||
@@ -81,6 +93,10 @@ PODS:
|
||||
- reown_yttrium (0.0.1):
|
||||
- Flutter
|
||||
- YttriumWrapper (= 0.8.35)
|
||||
- rive_common (0.0.1):
|
||||
- Flutter
|
||||
- rlz (0.0.1):
|
||||
- Flutter
|
||||
- SDWebImage (5.21.2):
|
||||
- SDWebImage/Core (= 5.21.2)
|
||||
- SDWebImage/Core (5.21.2)
|
||||
@@ -91,6 +107,8 @@ PODS:
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sp_scanner (0.0.1):
|
||||
- Flutter
|
||||
- sqflite_darwin (0.0.4):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@@ -135,8 +153,11 @@ PODS:
|
||||
|
||||
DEPENDENCIES:
|
||||
- bitbox_flutter (from `.symlinks/plugins/bitbox_flutter/ios`)
|
||||
- breez_sdk_spark_flutter (from `.symlinks/plugins/breez_sdk_spark_flutter/ios`)
|
||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||
- CryptoSwift
|
||||
- cw_decred (from `.symlinks/plugins/cw_decred/ios`)
|
||||
- cw_mweb (from `.symlinks/plugins/cw_mweb/ios`)
|
||||
- device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`)
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
|
||||
@@ -148,18 +169,24 @@ DEPENDENCIES:
|
||||
- flutter_local_authentication (from `.symlinks/plugins/flutter_local_authentication/ios`)
|
||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||
- flutter_mailer (from `.symlinks/plugins/flutter_mailer/ios`)
|
||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
|
||||
- integration_test (from `.symlinks/plugins/integration_test/ios`)
|
||||
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- payjoin_flutter (from `.symlinks/plugins/payjoin_flutter/ios`)
|
||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||
- quick_actions_ios (from `.symlinks/plugins/quick_actions_ios/ios`)
|
||||
- reown_yttrium (from `.symlinks/plugins/reown_yttrium/ios`)
|
||||
- rive_common (from `.symlinks/plugins/rive_common/ios`)
|
||||
- rlz (from `.symlinks/plugins/rlz/ios`)
|
||||
- sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`)
|
||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sp_scanner (from `.symlinks/plugins/sp_scanner/ios`)
|
||||
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
||||
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
|
||||
- torch_dart (from `.symlinks/plugins/torch_dart/ios`)
|
||||
@@ -182,8 +209,14 @@ SPEC REPOS:
|
||||
EXTERNAL SOURCES:
|
||||
bitbox_flutter:
|
||||
:path: ".symlinks/plugins/bitbox_flutter/ios"
|
||||
breez_sdk_spark_flutter:
|
||||
:path: ".symlinks/plugins/breez_sdk_spark_flutter/ios"
|
||||
connectivity_plus:
|
||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||
cw_decred:
|
||||
:path: ".symlinks/plugins/cw_decred/ios"
|
||||
cw_mweb:
|
||||
:path: ".symlinks/plugins/cw_mweb/ios"
|
||||
device_display_brightness:
|
||||
:path: ".symlinks/plugins/device_display_brightness/ios"
|
||||
device_info_plus:
|
||||
@@ -206,6 +239,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||
flutter_mailer:
|
||||
:path: ".symlinks/plugins/flutter_mailer/ios"
|
||||
flutter_native_splash:
|
||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||
flutter_secure_storage:
|
||||
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
||||
fluttertoast:
|
||||
@@ -216,20 +251,30 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/in_app_review/ios"
|
||||
integration_test:
|
||||
:path: ".symlinks/plugins/integration_test/ios"
|
||||
local_auth_darwin:
|
||||
:path: ".symlinks/plugins/local_auth_darwin/darwin"
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
payjoin_flutter:
|
||||
:path: ".symlinks/plugins/payjoin_flutter/ios"
|
||||
permission_handler_apple:
|
||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||
quick_actions_ios:
|
||||
:path: ".symlinks/plugins/quick_actions_ios/ios"
|
||||
reown_yttrium:
|
||||
:path: ".symlinks/plugins/reown_yttrium/ios"
|
||||
rive_common:
|
||||
:path: ".symlinks/plugins/rive_common/ios"
|
||||
rlz:
|
||||
:path: ".symlinks/plugins/rlz/ios"
|
||||
sensitive_clipboard:
|
||||
:path: ".symlinks/plugins/sensitive_clipboard/ios"
|
||||
share_plus:
|
||||
:path: ".symlinks/plugins/share_plus/ios"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
sp_scanner:
|
||||
:path: ".symlinks/plugins/sp_scanner/ios"
|
||||
sqflite_darwin:
|
||||
:path: ".symlinks/plugins/sqflite_darwin/darwin"
|
||||
sqlite3_flutter_libs:
|
||||
@@ -247,6 +292,7 @@ EXTERNAL SOURCES:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
bitbox_flutter: 9505732798041c413152669751beeaecc5fe400f
|
||||
breez_sdk_spark_flutter: f02552ffcff6012e5a4849517d78376ad1046250
|
||||
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
||||
CryptoSwift: e64e11850ede528a02a0f3e768cec8e9d92ecb90
|
||||
cw_decred: a02cf30175a46971c1e2fa22c48407534541edc6
|
||||
@@ -277,6 +323,8 @@ SPEC CHECKSUMS:
|
||||
permission_handler_apple: 92d754bbaa7361d436db2d6c3c1c2a0fdcec462e
|
||||
quick_actions_ios: 500fcc11711d9f646739093395c4ae8eec25f779
|
||||
reown_yttrium: cee334ade64725b1d83f7b34c706a6aae2696d58
|
||||
rive_common: dd421daaf9ae69f0125aa761dd96abd278399952
|
||||
rlz: 3f4022361f540a5c26d9d2474fea1d2455b69d8d
|
||||
SDWebImage: 9f177d83116802728e122410fb25ad88f5c7608a
|
||||
sensitive_clipboard: 161e9abc3d56b3131309d8a321eb4690a803c16b
|
||||
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
||||
@@ -288,7 +336,7 @@ SPEC CHECKSUMS:
|
||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||
torch_dart: f4620705d10f05492fab047f2fa1c3a600e7d17d
|
||||
uni_links: ed8c961e47ed9ce42b6d91e1de8049e38a4b3152
|
||||
universal_ble: 45519b2aeafe62761e2c6309f8927edb5288b914
|
||||
universal_ble: a322ebabee64f0ec27a313e89a5dd6967f37a60f
|
||||
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
||||
YttriumWrapper: 31e937fe9fbe0f1314d2ca6be9ce9b379a059966
|
||||
|
||||
@@ -201,7 +201,6 @@
|
||||
<array>
|
||||
<string>solana</string>
|
||||
<string>solana-wallet</string>
|
||||
<string>solana_wallet</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
|
||||
@@ -86,6 +86,7 @@ class WalletCreationService {
|
||||
case WalletType.dogecoin:
|
||||
case WalletType.nano:
|
||||
case WalletType.zcash:
|
||||
case WalletType.zano:
|
||||
case WalletType.decred:
|
||||
return true;
|
||||
case WalletType.monero:
|
||||
@@ -93,7 +94,6 @@ class WalletCreationService {
|
||||
case WalletType.none:
|
||||
case WalletType.haven:
|
||||
case WalletType.banano:
|
||||
case WalletType.zano:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1345,7 +1345,7 @@ Future<void> setup({
|
||||
case WalletType.wownero:
|
||||
return wownero!.createWowneroWalletService(_unspentCoinsInfoSource);
|
||||
case WalletType.zano:
|
||||
return zano!.createZanoWalletService();
|
||||
return zano!.createZanoWalletService(SettingsStoreBase.walletPasswordDirectInput);
|
||||
case WalletType.decred:
|
||||
return decred!.createDecredWalletService(
|
||||
_unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput);
|
||||
|
||||
@@ -17,11 +17,11 @@ bool isBIP39Wallet(WalletType walletType) {
|
||||
case WalletType.monero:
|
||||
case WalletType.dogecoin:
|
||||
case WalletType.zcash:
|
||||
case WalletType.zano:
|
||||
case WalletType.decred:
|
||||
return true;
|
||||
case WalletType.wownero:
|
||||
case WalletType.haven:
|
||||
case WalletType.zano:
|
||||
case WalletType.none:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -286,7 +286,12 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||
'wallet_restore_from_seed_blockheight_textfield_key',
|
||||
),
|
||||
onHeightOrDateEntered: widget.onHeightOrDateEntered,
|
||||
hasDatePicker: [WalletType.monero, WalletType.wownero, WalletType.zcash].contains(
|
||||
hasDatePicker: [
|
||||
WalletType.monero,
|
||||
WalletType.wownero,
|
||||
WalletType.zcash,
|
||||
WalletType.zano,
|
||||
].contains(
|
||||
widget.type,
|
||||
),
|
||||
walletType: widget.type,
|
||||
|
||||
@@ -13,6 +13,7 @@ import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
|
||||
import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
|
||||
import 'package:cake_wallet/zano/zano.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -606,7 +607,13 @@ class _WalletRestorePageBodyState extends State<_WalletRestorePageBody>
|
||||
final seedWords = seedPhrase.split(' ');
|
||||
|
||||
if (seedWords.length == 14 && walletRestoreViewModel.type == WalletType.wownero) return true;
|
||||
if (seedWords.length == 26 && walletRestoreViewModel.type == WalletType.zano) return true;
|
||||
if (walletRestoreViewModel.type == WalletType.zano) {
|
||||
if (seedWords.length == 26) return true;
|
||||
if ([12, 24].contains(seedWords.length) && zano!.isBip39Seed(seedPhrase.trim())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (seedWords.length == 12 && walletRestoreViewModel.type == WalletType.monero) {
|
||||
return walletRestoreFromSeedFormKey.currentState?.blockchainHeightKey.currentState
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/src/widgets/standard_switch.dart';
|
||||
import 'package:cake_wallet/utils/date_picker.dart';
|
||||
import 'package:cake_wallet/wownero/wownero.dart';
|
||||
import 'package:cake_wallet/zano/zano.dart';
|
||||
import 'package:cake_wallet/zcash/zcash.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -200,6 +201,8 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
|
||||
height = wownero!.getHeightByDate(date: date);
|
||||
} else if (widget.walletType == WalletType.zcash) {
|
||||
height = await zcash!.getHeightByDate(date);
|
||||
} else if (widget.walletType == WalletType.zano) {
|
||||
height = zano!.getHeightByDate(date: date);
|
||||
} else {
|
||||
throw Exception("unknown currency in BlockchainHeightWidget");
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
|
||||
case WalletType.solana:
|
||||
case WalletType.tron:
|
||||
case WalletType.zcash:
|
||||
case WalletType.zano:
|
||||
case WalletType.decred:
|
||||
return true;
|
||||
|
||||
@@ -74,7 +75,6 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
|
||||
case WalletType.wownero:
|
||||
case WalletType.none:
|
||||
case WalletType.haven:
|
||||
case WalletType.zano:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,8 +128,9 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
|
||||
|
||||
bool isNonSeedWallet = wallet.isNonSeedWallet;
|
||||
|
||||
bool isNotMoneroBip39Wallet =
|
||||
wallet.type == WalletType.monero && di.derivationType != DerivationType.bip39;
|
||||
bool isNotBip39CoinWallet =
|
||||
(wallet.type == WalletType.monero || wallet.type == WalletType.zano) &&
|
||||
di.derivationType != DerivationType.bip39;
|
||||
|
||||
bool isNotDecredBip39Wallet = wallet.type == WalletType.decred &&
|
||||
di.derivationType != DerivationType.bip39 &&
|
||||
@@ -142,7 +143,7 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
|
||||
isElectrumDerivationType ||
|
||||
isSameTypeAsSelectedWallet ||
|
||||
isNonSeedWallet ||
|
||||
isNotMoneroBip39Wallet ||
|
||||
isNotBip39CoinWallet ||
|
||||
isNotDecredBip39Wallet;
|
||||
}
|
||||
|
||||
|
||||
@@ -139,6 +139,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
|
||||
name: name,
|
||||
password: walletPassword,
|
||||
passphrase: passphrase,
|
||||
mnemonic: newWalletArguments!.mnemonic,
|
||||
);
|
||||
case WalletType.zcash:
|
||||
return zcash!.createZcashNewWalletCredentials(
|
||||
|
||||
@@ -83,8 +83,13 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||
late final bool hasSeedLanguageSelector =
|
||||
[WalletType.monero, WalletType.haven, WalletType.wownero].contains(type);
|
||||
|
||||
late final bool hasBlockchainHeightSelector =
|
||||
[WalletType.monero, WalletType.haven, WalletType.wownero, WalletType.zcash].contains(type);
|
||||
late final bool hasBlockchainHeightSelector = [
|
||||
WalletType.monero,
|
||||
WalletType.haven,
|
||||
WalletType.wownero,
|
||||
WalletType.zcash,
|
||||
WalletType.zano,
|
||||
].contains(type);
|
||||
|
||||
late final bool hasRestoreFromPrivateKey = [
|
||||
WalletType.ethereum,
|
||||
@@ -204,13 +209,15 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||
height: height,
|
||||
);
|
||||
case WalletType.zano:
|
||||
return zano!.createZanoRestoreWalletFromSeedCredentials(
|
||||
final credentials = zano!.createZanoRestoreWalletFromSeedCredentials(
|
||||
name: name,
|
||||
password: password,
|
||||
height: height,
|
||||
passphrase: passphrase ?? '',
|
||||
mnemonic: seed,
|
||||
);
|
||||
credentials.derivationInfo = derivationInfo;
|
||||
return credentials;
|
||||
case WalletType.decred:
|
||||
return decred!.createDecredRestoreWalletFromSeedCredentials(
|
||||
name: name,
|
||||
@@ -363,6 +370,17 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||
seedKey: seedKey,
|
||||
node: node,
|
||||
);
|
||||
case WalletType.zano:
|
||||
final mnemonic = (credentials['seed'] as String?)?.trim() ?? '';
|
||||
if (mnemonic.isEmpty) break;
|
||||
if (zano!.isBip39Seed(mnemonic)) {
|
||||
return [
|
||||
DerivationInfo(derivationType: DerivationType.bip39),
|
||||
];
|
||||
}
|
||||
return [
|
||||
DerivationInfo(derivationType: DerivationType.unknown),
|
||||
];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+21
-6
@@ -46,7 +46,7 @@ class CWZano extends Zano {
|
||||
@override
|
||||
List<String> getWordList(String language) {
|
||||
assert(language.toLowerCase() == LanguageList.english.toLowerCase());
|
||||
return EnglishMnemonics.words;
|
||||
return [...zano_bip39.bip39EnglishWords, ...EnglishMnemonics.words];
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -61,9 +61,18 @@ class CWZano extends Zano {
|
||||
}
|
||||
|
||||
@override
|
||||
WalletCredentials createZanoNewWalletCredentials(
|
||||
{required String name, required String? password, required String? passphrase}) {
|
||||
return ZanoNewWalletCredentials(name: name, password: password, passphrase: passphrase);
|
||||
WalletCredentials createZanoNewWalletCredentials({
|
||||
required String name,
|
||||
required String? password,
|
||||
required String? passphrase,
|
||||
String? mnemonic,
|
||||
}) {
|
||||
return ZanoNewWalletCredentials(
|
||||
name: name,
|
||||
password: password,
|
||||
passphrase: passphrase,
|
||||
mnemonic: mnemonic,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -122,8 +131,8 @@ class CWZano extends Zano {
|
||||
// }
|
||||
|
||||
@override
|
||||
WalletService createZanoWalletService() {
|
||||
return ZanoWalletService();
|
||||
WalletService createZanoWalletService(bool isDirect) {
|
||||
return ZanoWalletService(isDirect);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -146,6 +155,12 @@ class CWZano extends Zano {
|
||||
@override
|
||||
bool validateAddress(String address) => ZanoUtils.validateAddress(address);
|
||||
|
||||
@override
|
||||
bool isBip39Seed(String mnemonic) => zano_bip39.isBip39Seed(mnemonic);
|
||||
|
||||
@override
|
||||
int getHeightByDate({required DateTime date}) => ZanoUtils.heightByDate(date);
|
||||
|
||||
@override
|
||||
Map<String, List<int>> debugCallLength() {
|
||||
return api.debugCallLength();
|
||||
|
||||
+8
-8
@@ -280,11 +280,11 @@ packages:
|
||||
dependency: "direct overridden"
|
||||
description:
|
||||
path: "."
|
||||
ref: e18b6437daaf0572de6aea2439c2ec4d22658bbb
|
||||
resolved-ref: e18b6437daaf0572de6aea2439c2ec4d22658bbb
|
||||
ref: "5943a3e773203f21728f87f1c0779040db8f2c28"
|
||||
resolved-ref: "5943a3e773203f21728f87f1c0779040db8f2c28"
|
||||
url: "https://github.com/breez/breez-sdk-spark-flutter"
|
||||
source: git
|
||||
version: "0.14.0"
|
||||
version: "0.23.0"
|
||||
bs58:
|
||||
dependency: "direct overridden"
|
||||
description:
|
||||
@@ -2050,8 +2050,8 @@ packages:
|
||||
dependency: "direct overridden"
|
||||
description:
|
||||
path: "impls/monero.dart"
|
||||
ref: "3bfb3856a838f2bf6b729501837bb0295dedf25d"
|
||||
resolved-ref: "3bfb3856a838f2bf6b729501837bb0295dedf25d"
|
||||
ref: cd4fe366cc8d3c188c91de279f43b29c0e044b15
|
||||
resolved-ref: cd4fe366cc8d3c188c91de279f43b29c0e044b15
|
||||
url: "https://github.com/mrcyjanek/monero_c.git"
|
||||
source: git
|
||||
version: "0.0.0"
|
||||
@@ -2600,9 +2600,9 @@ packages:
|
||||
dependency: "direct overridden"
|
||||
description:
|
||||
path: "."
|
||||
ref: "9457422fce3f1524437f6a1429200f048931a2fe"
|
||||
resolved-ref: "9457422fce3f1524437f6a1429200f048931a2fe"
|
||||
url: "https://github.com/MrCyjaneK/rive_common"
|
||||
ref: "34ef174e87dc4a29e728babfaad8dd9464b704ae"
|
||||
resolved-ref: "34ef174e87dc4a29e728babfaad8dd9464b704ae"
|
||||
url: "https://github.com/malik1004x/rive_common"
|
||||
source: git
|
||||
version: "0.4.15"
|
||||
riverpod:
|
||||
|
||||
@@ -960,7 +960,7 @@ dependency_overrides:
|
||||
monero:
|
||||
git:
|
||||
url: https://github.com/mrcyjanek/monero_c.git
|
||||
ref: 3bfb3856a838f2bf6b729501837bb0295dedf25d
|
||||
ref: cd4fe366cc8d3c188c91de279f43b29c0e044b15
|
||||
path: ./impls/monero.dart
|
||||
msgpack_dart:
|
||||
git:
|
||||
|
||||
@@ -14,15 +14,15 @@ TYPES=($MONERO_COM $CAKEWALLET)
|
||||
APP_ANDROID_TYPE=$1
|
||||
|
||||
MONERO_COM_NAME="Monero.com"
|
||||
MONERO_COM_VERSION="6.4.1"
|
||||
MONERO_COM_BUILD_NUMBER=4165
|
||||
MONERO_COM_VERSION="6.4.2"
|
||||
MONERO_COM_BUILD_NUMBER=4167
|
||||
MONERO_COM_BUNDLE_ID="com.monero.app"
|
||||
MONERO_COM_PACKAGE="com.monero.app"
|
||||
MONERO_COM_SCHEME="monero.com"
|
||||
|
||||
CAKEWALLET_NAME="Cake Wallet"
|
||||
CAKEWALLET_VERSION="6.4.1"
|
||||
CAKEWALLET_BUILD_NUMBER=4420
|
||||
CAKEWALLET_VERSION="6.4.3"
|
||||
CAKEWALLET_BUILD_NUMBER=4423
|
||||
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
|
||||
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
|
||||
CAKEWALLET_SCHEME="cakewallet"
|
||||
|
||||
@@ -12,13 +12,13 @@ TYPES=($MONERO_COM $CAKEWALLET)
|
||||
APP_IOS_TYPE=$1
|
||||
|
||||
MONERO_COM_NAME="Monero.com"
|
||||
MONERO_COM_VERSION="6.4.1"
|
||||
MONERO_COM_BUILD_NUMBER=171
|
||||
MONERO_COM_VERSION="6.4.2"
|
||||
MONERO_COM_BUILD_NUMBER=173
|
||||
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
|
||||
|
||||
CAKEWALLET_NAME="Cake Wallet"
|
||||
CAKEWALLET_VERSION="6.4.1"
|
||||
CAKEWALLET_BUILD_NUMBER=434
|
||||
CAKEWALLET_VERSION="6.4.3"
|
||||
CAKEWALLET_BUILD_NUMBER=437
|
||||
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
||||
|
||||
|
||||
|
||||
@@ -16,13 +16,13 @@ if [ -n "$1" ]; then
|
||||
fi
|
||||
|
||||
MONERO_COM_NAME="Monero.com"
|
||||
MONERO_COM_VERSION="6.4.1"
|
||||
MONERO_COM_BUILD_NUMBER=82
|
||||
MONERO_COM_VERSION="6.4.2"
|
||||
MONERO_COM_BUILD_NUMBER=83
|
||||
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
|
||||
|
||||
CAKEWALLET_NAME="Cake Wallet"
|
||||
CAKEWALLET_VERSION="6.4.1"
|
||||
CAKEWALLET_BUILD_NUMBER=150
|
||||
CAKEWALLET_VERSION="6.4.2"
|
||||
CAKEWALLET_BUILD_NUMBER=151
|
||||
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
||||
|
||||
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then
|
||||
|
||||
@@ -16,7 +16,7 @@ fi
|
||||
# NOTE: Make sure to update monero_c prebuilds link in workflow files
|
||||
# https://github.com/MrCyjaneK/monero_c/releases/download/v0.18.4.6-RC2/release-bundle.zip
|
||||
git fetch -a
|
||||
git checkout 5952bef2ec01b0b7e57c11613cbdc081dcd727c5
|
||||
git checkout cd4fe366cc8d3c188c91de279f43b29c0e044b15
|
||||
git reset --hard
|
||||
git submodule update --init --force --recursive
|
||||
|
||||
|
||||
+5
-2
@@ -1178,6 +1178,7 @@ import 'package:cw_core/zano_asset.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
""";
|
||||
const zanoCWHeaders = """
|
||||
import 'package:cw_zano/bip39_seed.dart' as zano_bip39;
|
||||
import 'package:cw_zano/mnemonics/english.dart';
|
||||
import 'package:cw_zano/model/zano_transaction_credentials.dart';
|
||||
import 'package:cw_zano/model/zano_transaction_info.dart';
|
||||
@@ -1196,12 +1197,12 @@ abstract class Zano {
|
||||
List<String> getWordList(String language);
|
||||
|
||||
WalletCredentials createZanoRestoreWalletFromSeedCredentials({required String name, required String password, required String passphrase, required int height, required String mnemonic});
|
||||
WalletCredentials createZanoNewWalletCredentials({required String name, required String? password, required String? passphrase});
|
||||
WalletCredentials createZanoNewWalletCredentials({required String name, required String? password, required String? passphrase, String? mnemonic});
|
||||
Map<String, String> getKeys(Object wallet);
|
||||
Object createZanoTransactionCredentials({required List<Output> outputs, required TransactionPriority priority, required CryptoCurrency currency});
|
||||
double formatterIntAmountToDouble({required int amount, required CryptoCurrency currency, required bool forFee});
|
||||
int formatterParseAmount({required String amount, required CryptoCurrency currency});
|
||||
WalletService createZanoWalletService();
|
||||
WalletService createZanoWalletService(bool isDirect);
|
||||
CryptoCurrency? assetOfTransaction(WalletBase wallet, TransactionInfo tx);
|
||||
List<ZanoAsset> getZanoAssets(WalletBase wallet);
|
||||
String getZanoAssetAddress(CryptoCurrency asset);
|
||||
@@ -1211,6 +1212,8 @@ abstract class Zano {
|
||||
Future<CryptoCurrency?> getZanoAsset(WalletBase wallet, String contractAddress);
|
||||
String getAddress(WalletBase wallet);
|
||||
bool validateAddress(String address);
|
||||
bool isBip39Seed(String mnemonic);
|
||||
int getHeightByDate({required DateTime date});
|
||||
Map<String, List<int>> debugCallLength();
|
||||
bool isTokenAlreadyAdded(WalletBase wallet, String contractAddress);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user