1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 09:57:02 +01:00

Remove use of ethgasstation; use metaswap /gasPrices api for gas price estimates (#9867)

* Remove use of ethgassthat; use metaswap /gasPrices api for gas price estimates

* Remove references to ethgasstation

* Pass base to BigNumber constructor in fetchExternalBasicGasEstimates

* Update ui/app/hooks/useTokenTracker.js

Co-authored-by: Erik Marks <25517051+rekmarks@users.noreply.github.com>

* Delete gas price chart

* Remove price chart css import

* Delete additional fee chart code

* Lint fix

* Delete more code no longer used after ethgasstation removal

Co-authored-by: Erik Marks <25517051+rekmarks@users.noreply.github.com>
This commit is contained in:
Dan J Miller 2020-12-02 19:55:19 -03:30 committed by GitHub
parent 0653a489b0
commit 97d268c8ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
80 changed files with 85 additions and 9529 deletions

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "የሰንሰለት መታወቂያ"
},
"chartOnlyAvailableEth": {
"message": "ቻርት የሚገኘው በ Ethereum አውታረ መረቦች ላይ ብቻ ነው።"
},
"chromeRequiredForHardwareWallets": {
"message": "ከሃርድዌርዎ ቋት ጋር ለመገናኘት MetaMask በ Google Chrome ላይ መጠቀም አለብዎት።"
},
@ -398,9 +395,6 @@
"fast": {
"message": "ፈጣን"
},
"faster": {
"message": "በፍጥነት"
},
"fiat": {
"message": "ፊያት",
"description": "Exchange type"
@ -579,9 +573,6 @@
"links": {
"message": "ማስፈንጠሪያዎች"
},
"liveGasPricePredictions": {
"message": "ቀጥታ የነዳጅ ዋጋ ትንበያዎች"
},
"loadMore": {
"message": "ተጨማሪ ጫን"
},
@ -1015,9 +1006,6 @@
"slow": {
"message": "ቀስ"
},
"slower": {
"message": "ዘገምተኛ"
},
"somethingWentWrong": {
"message": "ኤጭ! የሆነ ችግር ተፈጥሯል።"
},
@ -1162,9 +1150,6 @@
"transactionSubmitted": {
"message": "ግብይቱ የቀረበው በነዳጅ ዋጋ $1በ$2ነው።"
},
"transactionTime": {
"message": "የግብይት ጊዜ"
},
"transactionUpdated": {
"message": "ግብይት የዘመነው በ $2ነው።"
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "معرّف السلسلة"
},
"chartOnlyAvailableEth": {
"message": "الرسم البياني متاح فقط على شبكات إيثيريوم."
},
"chromeRequiredForHardwareWallets": {
"message": "تحتاج إلى استخدام MetaMask على Google Chrome للاتصال بمحفظة الأجهزة الخاصة بك."
},
@ -398,9 +395,6 @@
"fast": {
"message": "سريع"
},
"faster": {
"message": "أسرع"
},
"fileImportFail": {
"message": "استيراد الملف لا ينجح؟ انقر هنا!",
"description": "Helps user import their account from a JSON file"
@ -575,9 +569,6 @@
"links": {
"message": "الروابط"
},
"liveGasPricePredictions": {
"message": "توقعات أسعار الجاس الحية"
},
"loadMore": {
"message": "تحميل المزيد"
},
@ -1011,9 +1002,6 @@
"slow": {
"message": "بطيء"
},
"slower": {
"message": "أبطأ"
},
"somethingWentWrong": {
"message": "عذراً! حدث خطأ ما."
},
@ -1158,9 +1146,6 @@
"transactionSubmitted": {
"message": "تم تقديم المعاملة برسوم $1 من عملة جاس في $2."
},
"transactionTime": {
"message": "وقت المعاملة"
},
"transactionUpdated": {
"message": "تم تحديث المعاملة في $2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "Идентификатор на веригата"
},
"chartOnlyAvailableEth": {
"message": "Диаграмата е достъпна само в мрежи на Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "За да се свържете с хардуерния си портфейл, трябва да използвате MetaMask в Google Chrome."
},
@ -398,9 +395,6 @@
"fast": {
"message": "Бързо"
},
"faster": {
"message": "По-бързо"
},
"fileImportFail": {
"message": "Импортирането на файл не работи? Натиснете тук!",
"description": "Helps user import their account from a JSON file"
@ -575,9 +569,6 @@
"links": {
"message": "Връзки"
},
"liveGasPricePredictions": {
"message": "Прогнози на живо за цената на газа"
},
"loadMore": {
"message": "Зареди повече"
},
@ -1014,9 +1005,6 @@
"slow": {
"message": "Бавно"
},
"slower": {
"message": "По-бавно"
},
"somethingWentWrong": {
"message": "Упс! Нещо се обърка."
},
@ -1161,9 +1149,6 @@
"transactionSubmitted": {
"message": "Транзакция, изпратена с такса за газ от $1 при $2."
},
"transactionTime": {
"message": "Време на транзакция"
},
"transactionUpdated": {
"message": "Транзакцията е актуализирана на $2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "চেন আইডি"
},
"chartOnlyAvailableEth": {
"message": "শুধুমাত্র Ethereum নেটওয়ার্কগুলিতে চার্ট উপলভ্য। "
},
"chromeRequiredForHardwareWallets": {
"message": "আপনার হার্ডওয়্যার ওয়ালেটের সাথে সংযোগ করতে আপনাকে Google Chrome এ MetaMask ব্যবহার করতে হবে। "
},
@ -398,9 +395,6 @@
"fast": {
"message": "দ্রুত"
},
"faster": {
"message": "দ্রুততর"
},
"fiat": {
"message": "ফিয়াট",
"description": "Exchange type"
@ -579,9 +573,6 @@
"links": {
"message": "লিঙ্কসমূহ"
},
"liveGasPricePredictions": {
"message": "সরাসরি গ্যাসের মূল্যের অনুমান"
},
"loadMore": {
"message": "আরও লোড করুন"
},
@ -1018,9 +1009,6 @@
"slow": {
"message": "মন্থর"
},
"slower": {
"message": "ধীর গতির"
},
"somethingWentWrong": {
"message": "ওহো! কিছু সমস্যা হয়েছে।"
},
@ -1165,9 +1153,6 @@
"transactionSubmitted": {
"message": "$2 এ $1 এর গ্যাস ফী সহ লেনদেন জমা করা হয়েছে।"
},
"transactionTime": {
"message": "লেনদেনের সময়"
},
"transactionUpdated": {
"message": "লেনদেন $2 এ আপডেট করা হয়েছে।"
},

View File

@ -164,9 +164,6 @@
"chainId": {
"message": "Cadena ID"
},
"chartOnlyAvailableEth": {
"message": "Mostra només els disponibles a les xarxes Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Necessites fer servir MetaMask amb Google Chrome per a connectar-te al teu Moneder Hardware."
},
@ -395,9 +392,6 @@
"fast": {
"message": "Ràpid"
},
"faster": {
"message": "Més ràpid"
},
"fileImportFail": {
"message": "La importació no funciona? Fes clic aquí!",
"description": "Helps user import their account from a JSON file"
@ -566,9 +560,6 @@
"links": {
"message": "Enllaços"
},
"liveGasPricePredictions": {
"message": "Prediccions del preu del gas en directe"
},
"loadMore": {
"message": "Carregar Més"
},
@ -996,9 +987,6 @@
"slow": {
"message": "Lent"
},
"slower": {
"message": "Més lent"
},
"somethingWentWrong": {
"message": "Ui! Alguna cosa ha fallat."
},
@ -1134,9 +1122,6 @@
"transactionSubmitted": {
"message": "Transacció enviada amb un preu del gas de $1 a $2."
},
"transactionTime": {
"message": "Temps de transacció"
},
"transactionUpdated": {
"message": "Transacció actualitzada a $2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "Kæde-ID"
},
"chartOnlyAvailableEth": {
"message": "Skema kun tilgængeligt på Ethereum-netværk."
},
"chromeRequiredForHardwareWallets": {
"message": "Du skal bruge MetaMask i Google Chrome for at forbinde med din Hardware Wallet."
},
@ -398,9 +395,6 @@
"fast": {
"message": "Hurtig"
},
"faster": {
"message": "Hurtigere"
},
"fileImportFail": {
"message": "Virker filimportering ikke? Klik her!",
"description": "Helps user import their account from a JSON file"
@ -569,9 +563,6 @@
"likeToAddTokens": {
"message": "Ønsker du at tilføje disse tokens?"
},
"liveGasPricePredictions": {
"message": "Live forudsigelser af brændstofpriser"
},
"loadMore": {
"message": "Indlæs Mere"
},
@ -996,9 +987,6 @@
"slow": {
"message": "Langsom"
},
"slower": {
"message": "Langsommere"
},
"somethingWentWrong": {
"message": "Ups! Noget gik galt."
},
@ -1134,9 +1122,6 @@
"transactionSubmitted": {
"message": "Transaktion indsendt med brændstofgebyr på $1 til $2."
},
"transactionTime": {
"message": "Transaktionstid"
},
"transactionUpdated": {
"message": "Transaktion opdateret til $2."
},

View File

@ -158,9 +158,6 @@
"cancelled": {
"message": "Abgebrochen"
},
"chartOnlyAvailableEth": {
"message": "Die Grafik ist nur in Ethereum-Netzwerken verfügbar."
},
"chromeRequiredForHardwareWallets": {
"message": "Sie müssen MetaMask unter Google Chrome nutzen, um sich mit Ihrem Hardware-Wallet zu verbinden."
},
@ -386,9 +383,6 @@
"fast": {
"message": "Schnell"
},
"faster": {
"message": "Schneller"
},
"fiat": {
"message": "FIAT",
"description": "Exchange type"
@ -564,9 +558,6 @@
"likeToAddTokens": {
"message": "Möchtest du diese Token hinzufügen?"
},
"liveGasPricePredictions": {
"message": "Live-Gaspreisprognosen"
},
"loadMore": {
"message": "Mehr laden"
},
@ -987,9 +978,6 @@
"slow": {
"message": "Langsam"
},
"slower": {
"message": "Langsamer"
},
"somethingWentWrong": {
"message": "Hoppla! Da hat etwas nicht geklappt."
},
@ -1128,9 +1116,6 @@
"transactionSubmitted": {
"message": "Transaktion mit einer Gasgebühr von $1 bei $2 übermittelt."
},
"transactionTime": {
"message": "Transaktionszeit"
},
"transactionUpdated": {
"message": "Transaktion für $2 aktualisiert."
},

View File

@ -164,9 +164,6 @@
"chainId": {
"message": "Αναγνωριστικό Αλυσίδας"
},
"chartOnlyAvailableEth": {
"message": "Το διάγραμμα είναι διαθέσιμο μόνο σε δίκτυα Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Θα πρέπει να χρησιμοποιήσετε το MetaMask στο Google Chrome για να συνδεθείτε στο Πορτοφόλι Υλικού."
},
@ -395,9 +392,6 @@
"fast": {
"message": "Γρήγορα"
},
"faster": {
"message": "Πιο γρήγορα"
},
"fiat": {
"message": "Εντολή",
"description": "Exchange type"
@ -576,9 +570,6 @@
"links": {
"message": "Σύνδεσμοι"
},
"liveGasPricePredictions": {
"message": "Ζωντανές Προβλέψεις Τιμής Καυσίμου"
},
"loadMore": {
"message": "Φόρτωση Περισσότερων"
},
@ -1015,9 +1006,6 @@
"slow": {
"message": "Αργά"
},
"slower": {
"message": "Πιο αργά"
},
"somethingWentWrong": {
"message": "Ουπς! Κάτι πήγε στραβά."
},
@ -1159,9 +1147,6 @@
"transactionSubmitted": {
"message": "Η συναλλαγή στάλθηκε με τέλος gas του $1 σε $2."
},
"transactionTime": {
"message": "Χρόνος Συναλλαγής"
},
"transactionUpdated": {
"message": "Η συναλλαγή ενημερώθηκε σε $2."
},

View File

@ -245,9 +245,6 @@
"chainId": {
"message": "Chain ID"
},
"chartOnlyAvailableEth": {
"message": "Chart only available on Ethereum networks."
},
"chromeRequiredForHardwareWallets": {
"message": "You need to use MetaMask on Google Chrome in order to connect to your Hardware Wallet."
},
@ -660,9 +657,6 @@
"fast": {
"message": "Fast"
},
"faster": {
"message": "Faster"
},
"fastest": {
"message": "Fastest"
},
@ -914,9 +908,6 @@
"links": {
"message": "Links"
},
"liveGasPricePredictions": {
"message": "Live Gas Price Predictions"
},
"loadMore": {
"message": "Load More"
},
@ -1491,9 +1482,6 @@
"showSeedPhrase": {
"message": "Show seed phrase"
},
"showTransactionTimeDescription": {
"message": "Select this to display pending transaction time estimates in the activity tab while on the Ethereum Mainnet. Note: estimates are approximations based on network conditions."
},
"sigRequest": {
"message": "Signature Request"
},
@ -1515,9 +1503,6 @@
"slow": {
"message": "Slow"
},
"slower": {
"message": "Slower"
},
"somethingWentWrong": {
"message": "Oops! Something went wrong."
},
@ -1654,16 +1639,6 @@
"swapEstimatedNetworkFeesInfo": {
"message": "This is an estimate of the network fee that will be used to complete your swap. The actual amount may change according to network conditions."
},
"swapEstimatedTime": {
"message": "Estimated time:"
},
"swapEstimatedTimeCalculating": {
"message": "Calculating..."
},
"swapEstimatedTimeFull": {
"message": "$1 $2",
"description": "This message shows bolded swapEstimatedTime message, which is substited for $1, followed by either the estimated remaining transaction time in mm:ss, or the swapEstimatedTimeCalculating message, which are substituted for $2."
},
"swapFailedErrorDescription": {
"message": "Your funds are safe and still available in your wallet."
},
@ -1871,9 +1846,6 @@
"swapsAdvancedOptions": {
"message": "Advanced Options"
},
"swapsAlmostDone": {
"message": "Almost done..."
},
"swapsBestQuote": {
"message": "Best quote"
},
@ -2012,9 +1984,6 @@
"transactionSubmitted": {
"message": "Transaction submitted with gas fee of $1 at $2."
},
"transactionTime": {
"message": "Transaction Time"
},
"transactionUpdated": {
"message": "Transaction updated at $2."
},

View File

@ -139,9 +139,6 @@
"chainId": {
"message": "ID Cadena"
},
"chartOnlyAvailableEth": {
"message": "Tabla solo disponible en redes Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Hay que usar MetaMask en Google Chrome para poder conectarse con tu Monedero Físico."
},
@ -322,9 +319,6 @@
"fast": {
"message": "Rápido"
},
"faster": {
"message": "Más Rápido"
},
"fiat": {
"message": "FIAT",
"description": "Exchange type"
@ -470,9 +464,6 @@
"links": {
"message": "Enlaces"
},
"liveGasPricePredictions": {
"message": "Previsiones en vivo del precio de Gas"
},
"loadMore": {
"message": "Cargar Más"
},
@ -801,9 +792,6 @@
"slow": {
"message": "Lento"
},
"slower": {
"message": "Más lento"
},
"somethingWentWrong": {
"message": "¡Ups! Algo funcionó mal."
},
@ -912,9 +900,6 @@
"transactionSubmitted": {
"message": "Se propuso la transacción con una comisión de gas de $1, en $2."
},
"transactionTime": {
"message": "Tiempo de Transacción"
},
"transactionUpdated": {
"message": "Se actualizó la transacción en $2."
},

View File

@ -164,9 +164,6 @@
"chainId": {
"message": "ID de cadena"
},
"chartOnlyAvailableEth": {
"message": "Chart está disponible únicamente en las redes de Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Debes utilizar MetaMask en Google Chrome para poder conectarte a tu billetera de hardware."
},
@ -395,9 +392,6 @@
"fast": {
"message": "Rápido"
},
"faster": {
"message": "Más rápido"
},
"fiat": {
"message": "Dinero fiduciario",
"description": "Exchange type"
@ -570,9 +564,6 @@
"links": {
"message": "Enlaces"
},
"liveGasPricePredictions": {
"message": "Predicciones del precio del gas en vivo"
},
"loadMore": {
"message": "Cargar más"
},
@ -1003,9 +994,6 @@
"slow": {
"message": "Lento"
},
"slower": {
"message": "Más lento"
},
"somethingWentWrong": {
"message": "¡Vaya! Se produjo un error."
},
@ -1144,9 +1132,6 @@
"transactionSubmitted": {
"message": "Se envió la transacción con una tasa de gas de $1 en $2."
},
"transactionTime": {
"message": "Tiempo de transacción"
},
"transactionUpdated": {
"message": "La transacción se actualizó en $2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "Ahela ID"
},
"chartOnlyAvailableEth": {
"message": "Tabel on saadaval vaid Ethereumi võrkudes."
},
"chromeRequiredForHardwareWallets": {
"message": "Riistvararahakoti ühendamiseks peate kasutama MetaMaski Google Chrome'is."
},
@ -398,9 +395,6 @@
"fast": {
"message": "Kiire"
},
"faster": {
"message": "Kiiremini"
},
"fileImportFail": {
"message": "Faili importimine ei toimi? Klõpsake siia!",
"description": "Helps user import their account from a JSON file"
@ -575,9 +569,6 @@
"links": {
"message": "Lingid"
},
"liveGasPricePredictions": {
"message": "Gaasihinna prognoosid reaalajas"
},
"loadMore": {
"message": "Laadi rohkem"
},
@ -1008,9 +999,6 @@
"slow": {
"message": "Aeglane"
},
"slower": {
"message": "Aeglasem"
},
"somethingWentWrong": {
"message": "Oih! Midagi läks valesti."
},
@ -1155,9 +1143,6 @@
"transactionSubmitted": {
"message": "Tehing edastatud gaasihinnaga $1 asukohas $2."
},
"transactionTime": {
"message": "Tehingu aeg"
},
"transactionUpdated": {
"message": "Tehing on uuendatud $2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "آی دی زنجیره"
},
"chartOnlyAvailableEth": {
"message": "تنها قابل دسترس را در شبکه های ایتریوم جدول بندی نمایید"
},
"chromeRequiredForHardwareWallets": {
"message": "برای وصل شدن به کیف سخت افزار شما باید MetaMask را در گوگل کروم استفاده نمایید."
},
@ -398,9 +395,6 @@
"fast": {
"message": "سریع"
},
"faster": {
"message": "سریع تر"
},
"fiat": {
"message": "حکم قانونی",
"description": "Exchange type"
@ -579,9 +573,6 @@
"links": {
"message": "لینک ها"
},
"liveGasPricePredictions": {
"message": "پیش بینی های قیمت گاز"
},
"loadMore": {
"message": "بارگیری بیشتر"
},
@ -1018,9 +1009,6 @@
"slow": {
"message": "آهسته"
},
"slower": {
"message": "آهسته تر"
},
"somethingWentWrong": {
"message": "اوه! مشکلی پیش آمده."
},
@ -1165,9 +1153,6 @@
"transactionSubmitted": {
"message": "معامله با فیس گاز 1$1 در 2$2 ارائه شد."
},
"transactionTime": {
"message": "زمان معامله"
},
"transactionUpdated": {
"message": "معامله به 1$2 بروزرسانی شد."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "Ketjun tunnus"
},
"chartOnlyAvailableEth": {
"message": "Kaavio saatavilla vain Ethereum-verkoissa."
},
"chromeRequiredForHardwareWallets": {
"message": "Sinun tarvitsee käyttää MetaMaskia Google Chromessa voidaksesi yhdistää laitteistokukkaroosi."
},
@ -398,9 +395,6 @@
"fast": {
"message": "Nopea"
},
"faster": {
"message": "Nopeammin"
},
"fiat": {
"message": "Kiinteä",
"description": "Exchange type"
@ -579,9 +573,6 @@
"links": {
"message": "Linkit"
},
"liveGasPricePredictions": {
"message": "Polttoaineen hintojen live-ennusteet"
},
"loadMore": {
"message": "Lataa lisää"
},
@ -1015,9 +1006,6 @@
"slow": {
"message": "Hidas"
},
"slower": {
"message": "Hitaammin"
},
"somethingWentWrong": {
"message": "Hupsis! Jotakin meni pieleen."
},
@ -1162,9 +1150,6 @@
"transactionSubmitted": {
"message": "Tapahtuma toimitettu $1 bensataksalla kohdassa $2."
},
"transactionTime": {
"message": "Tapahtuman aika"
},
"transactionUpdated": {
"message": "Tapahtuma päivitetty $2."
},

View File

@ -146,9 +146,6 @@
"cancelled": {
"message": "Nakansela"
},
"chartOnlyAvailableEth": {
"message": "Available lang ang chart sa mga Ethereum network."
},
"chromeRequiredForHardwareWallets": {
"message": "Kailangan mong gamitin ang MetaMask sa Google Chrome upang makakonekta sa iyong Hardware Wallet."
},
@ -371,9 +368,6 @@
"fast": {
"message": "Mabilis"
},
"faster": {
"message": "Mas Mabilis"
},
"fileImportFail": {
"message": "Hindi gumagana ang pag-import ng file? Mag-click dito!",
"description": "Helps user import their account from a JSON file"
@ -529,9 +523,6 @@
"links": {
"message": "Mga Link"
},
"liveGasPricePredictions": {
"message": "Mga Live na Prediksyon sa Presyo ng Gas"
},
"loadMore": {
"message": "Mag-load Pa"
},
@ -924,9 +915,6 @@
"slow": {
"message": "Mabagal"
},
"slower": {
"message": "Mas Mabagal"
},
"somethingWentWrong": {
"message": "Oops! Nagkaroon ng problema."
},
@ -1062,9 +1050,6 @@
"transactionSubmitted": {
"message": "Nasumite ang transaksyon nang may gas fee na $1 sa $2."
},
"transactionTime": {
"message": "Oras ng Transaksyon"
},
"transactionUpdated": {
"message": "Na-update ang transaksyon sa $2."
},

View File

@ -158,9 +158,6 @@
"chainId": {
"message": "ID de chaîne"
},
"chartOnlyAvailableEth": {
"message": "Tableau disponible uniquement sur les réseaux Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Pour connecter votre portefeuille hardware, vous devez utiliser MetaMask pour Google Chrome."
},
@ -389,9 +386,6 @@
"fast": {
"message": "Rapide"
},
"faster": {
"message": "Plus rapide"
},
"fiat": {
"message": "FIAT",
"description": "Exchange type"
@ -573,9 +567,6 @@
"links": {
"message": "Liens"
},
"liveGasPricePredictions": {
"message": "Prévisions des prix de l'essence en direct"
},
"loadMore": {
"message": "Charger plus"
},
@ -1000,9 +991,6 @@
"slow": {
"message": "Lente"
},
"slower": {
"message": "Plus lent"
},
"somethingWentWrong": {
"message": "Oups ! Quelque chose a mal tourné. "
},
@ -1141,9 +1129,6 @@
"transactionSubmitted": {
"message": "Transaction envoyée sur $2."
},
"transactionTime": {
"message": "Heure de la transaction"
},
"transactionUpdated": {
"message": "Transaction mise à jour sur $2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "מזהה שרשרת"
},
"chartOnlyAvailableEth": {
"message": "טבלה זמינה רק ברשתות אתריום."
},
"chromeRequiredForHardwareWallets": {
"message": "עליך להשתמש ב-MetaMask בגוגל כרום כדי להתחבר לארנק החומרה שלך."
},
@ -398,9 +395,6 @@
"fast": {
"message": "מהיר"
},
"faster": {
"message": "מהר יותר"
},
"fiat": {
"message": "פיאט",
"description": "Exchange type"
@ -579,9 +573,6 @@
"links": {
"message": "קישורים"
},
"liveGasPricePredictions": {
"message": "תחזיות מחירי גז בשידור חי"
},
"loadMore": {
"message": "טען עוד"
},
@ -1012,9 +1003,6 @@
"slow": {
"message": "אטי"
},
"slower": {
"message": "לאט יותר"
},
"somethingWentWrong": {
"message": "אופס! משהו השתבש."
},
@ -1159,9 +1147,6 @@
"transactionSubmitted": {
"message": "עסקה הוגשה עם עמלת דלק של $1 ב-$2."
},
"transactionTime": {
"message": "זמן העסקה"
},
"transactionUpdated": {
"message": "העסקה עודכנה ב- $2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "चेन आई.डी."
},
"chartOnlyAvailableEth": {
"message": "केवल ईथरअम नेटवर्क पर उपलब्ध चार्ट।"
},
"chromeRequiredForHardwareWallets": {
"message": "अपने हार्डवेयर वॉलेट से कनेक्ट करने के लिए आपको Google Chrome में MetaMask का उपयोग करना ज़रूरी है।"
},
@ -398,9 +395,6 @@
"fast": {
"message": "तेज़"
},
"faster": {
"message": "तीव्र"
},
"fiat": {
"message": "फ़्लैट",
"description": "Exchange type"
@ -576,9 +570,6 @@
"likeToAddTokens": {
"message": "क्या आप इन टोकन को जोड़ना चाहेंगे?"
},
"liveGasPricePredictions": {
"message": "लाइव गैस की कीमत की भविष्यवाणी"
},
"loadMore": {
"message": "और लोड करें"
},
@ -1012,9 +1003,6 @@
"slow": {
"message": "धीमा"
},
"slower": {
"message": "धीमा"
},
"somethingWentWrong": {
"message": "ओह! कुछ गलत हो गया।"
},
@ -1159,9 +1147,6 @@
"transactionSubmitted": {
"message": "$2 पर $1 के गैस शुल्क के साथ ट्रांज़ैक्शन दर्ज किया गया।"
},
"transactionTime": {
"message": "ट्रांज़ैक्शन का समय"
},
"transactionUpdated": {
"message": "$2 पर ट्रांज़ैक्शन अपडेट किया गया।"
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "Identifikacijska oznaka bloka"
},
"chartOnlyAvailableEth": {
"message": "Grafikon je dostupan samo na mrežama Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Trebate upotrebljavati MetaMask u pregledniku Google Chrome kako biste ga povezali s vašim hardverskim novčanikom."
},
@ -398,9 +395,6 @@
"fast": {
"message": "Brzo"
},
"faster": {
"message": "Brže"
},
"fileImportFail": {
"message": "Uvoženje datoteke ne radi? Kliknite ovdje.",
"description": "Helps user import their account from a JSON file"
@ -575,9 +569,6 @@
"links": {
"message": "Poveznice"
},
"liveGasPricePredictions": {
"message": "Predviđanja uživo za cijenu goriva"
},
"loadMore": {
"message": "Učitaj više"
},
@ -1011,9 +1002,6 @@
"slow": {
"message": "Sporo"
},
"slower": {
"message": "Sporije"
},
"somethingWentWrong": {
"message": "Ups! Nešto je pošlo po zlu."
},
@ -1155,9 +1143,6 @@
"transactionSubmitted": {
"message": "Transakcija je poslana s naknadom za gorivo od $1 u $2."
},
"transactionTime": {
"message": "Vrijeme transkacije"
},
"transactionUpdated": {
"message": "Transakcija je ažurirana u $2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "Lánc azonosítója"
},
"chartOnlyAvailableEth": {
"message": "A diagram csak Ethereum hálózatokon érhető el"
},
"chromeRequiredForHardwareWallets": {
"message": "A MetaMask-ot Google Chrome-mal kell használnia a Hardveres pénztárcához való csatlakozáshoz."
},
@ -398,9 +395,6 @@
"fast": {
"message": "Gyors"
},
"faster": {
"message": "Gyorsabban"
},
"fileImportFail": {
"message": "Nem működik a fájl importálása? Kattintson ide!",
"description": "Helps user import their account from a JSON file"
@ -575,9 +569,6 @@
"links": {
"message": "Linkek"
},
"liveGasPricePredictions": {
"message": "Élő előrejelzések gázárak alakulására"
},
"loadMore": {
"message": "Továbbiak betöltése"
},
@ -1011,9 +1002,6 @@
"slow": {
"message": "Lassú"
},
"slower": {
"message": "Lassabban"
},
"somethingWentWrong": {
"message": "Hoppá! Valami hiba történt..."
},
@ -1155,9 +1143,6 @@
"transactionSubmitted": {
"message": "Tranzakció jóváhagyva $1 üzemanyag költséggel $2-kor."
},
"transactionTime": {
"message": "Tranzakció ideje"
},
"transactionUpdated": {
"message": "Tranzakció frissítve $2-nál"
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "ID Rantai"
},
"chartOnlyAvailableEth": {
"message": "Grafik hanya tersedia pada jaringan Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Anda harus menggunakan MetaMask di Google Chrome untuk menyambung ke dompet Perangkat Keras Anda."
},
@ -392,9 +389,6 @@
"fast": {
"message": "Cepat"
},
"faster": {
"message": "Lebih Cepat"
},
"fileImportFail": {
"message": "Impor berkas tidak tersedia? Klik di sini!",
"description": "Helps user import their account from a JSON file"
@ -569,9 +563,6 @@
"links": {
"message": "Tautan"
},
"liveGasPricePredictions": {
"message": "Prediksi Harga Gas Langsung"
},
"loadMore": {
"message": "Muat Lainnya"
},
@ -1002,9 +993,6 @@
"slow": {
"message": "Lambat"
},
"slower": {
"message": "Lebih Lambat"
},
"somethingWentWrong": {
"message": "Ups! Terjadi sesuatu."
},
@ -1143,9 +1131,6 @@
"transactionSubmitted": {
"message": "Transaksi diajukan dengan biaya gas sebesar $1 di $2."
},
"transactionTime": {
"message": "Waktu Transaksi"
},
"transactionUpdated": {
"message": "Transaksi diperbarui di $2."
},

View File

@ -229,9 +229,6 @@
"chainId": {
"message": "Blockchain ID"
},
"chartOnlyAvailableEth": {
"message": "Grafico disponibile solo per le reti Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Devi usare MetaMask con Google Chrome per connettere il tuo Portafoglio Hardware"
},
@ -630,9 +627,6 @@
"fast": {
"message": "Veloce"
},
"faster": {
"message": "Più veloce"
},
"feeAssociatedRequest": {
"message": "Una tassa è associata a questa richiesta."
},
@ -851,9 +845,6 @@
"links": {
"message": "Collegamenti"
},
"liveGasPricePredictions": {
"message": "Previsione del prezzo del gas in tempo reale"
},
"loadMore": {
"message": "Carica di più"
},
@ -1382,9 +1373,6 @@
"showSeedPhrase": {
"message": "Mostra frase seed"
},
"showTransactionTimeDescription": {
"message": "Seleziona per mostrare nella scheda attività una stima dei tempi di transazione per le transazioni in corso sulla rete Ethereum principale. Nota: la stima è approssimativa basata sulle condizioni della rete."
},
"sigRequest": {
"message": "Firma Richiesta"
},
@ -1406,9 +1394,6 @@
"slow": {
"message": "Lenta"
},
"slower": {
"message": "Più lenta"
},
"somethingWentWrong": {
"message": "Oops! Qualcosa è andato storto."
},
@ -1600,9 +1585,6 @@
"transactionSubmitted": {
"message": "Transazione inviata alle $2."
},
"transactionTime": {
"message": "Tempo Conferma Transazione"
},
"transactionUpdated": {
"message": "Transazione aggiornata alle $2."
},

View File

@ -115,9 +115,6 @@
"cancel": {
"message": "キャンセル"
},
"chartOnlyAvailableEth": {
"message": "チャートはEthereumネットワークでのみ利用可能です。"
},
"confirm": {
"message": "確認"
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "ಚೈನ್ ID"
},
"chartOnlyAvailableEth": {
"message": "ಎಥೆರಿಯಮ್ ನೆಟ್‌ವರ್ಕ್‌ಗಳಲ್ಲಿ ಮಾತ್ರವೇ ಚಾರ್ಟ್‌ಗಳು ಲಭ್ಯವಿರುತ್ತವೆ."
},
"chromeRequiredForHardwareWallets": {
"message": "ನಿಮ್ಮ ಹಾರ್ಡ್‌ವೇರ್ ವ್ಯಾಲೆಟ್‌ಗೆ ಸಂಪರ್ಕಪಡಿಸುವ ಸಲುವಾಗಿ Google Chrome ನಲ್ಲಿ ನಿಮಗೆ MetaMask ಅನ್ನು ಬಳಸುವ ಅಗತ್ಯವಿದೆ."
},
@ -398,9 +395,6 @@
"fast": {
"message": "ವೇಗ"
},
"faster": {
"message": "ವೇಗವಾಗಿ"
},
"fiat": {
"message": "ಫಿಯೆಟ್",
"description": "Exchange type"
@ -579,9 +573,6 @@
"links": {
"message": "ಲಿಂಕ್‌ಗಳು"
},
"liveGasPricePredictions": {
"message": "ಲೈವ್ ಗ್ಯಾಸ್ ಬೆಲೆಯ ಭವಿಷ್ಯಗಳು"
},
"loadMore": {
"message": "ಇನ್ನಷ್ಟು ಲೋಡ್ ಮಾಡಿ"
},
@ -1018,9 +1009,6 @@
"slow": {
"message": "ನಿಧಾನ"
},
"slower": {
"message": "ನಿಧಾನ"
},
"somethingWentWrong": {
"message": "ಓಹ್‌‍! ಏನೋ ತಪ್ಪಾಗಿದೆ."
},
@ -1165,9 +1153,6 @@
"transactionSubmitted": {
"message": "ವಹಿವಾಟನ್ನು $2 ನಲ್ಲಿ $1 ಗ್ಯಾಸ್ ಶುಲ್ಕದೊಂದಿಗೆ ರಚಿಸಲಾಗಿದೆ."
},
"transactionTime": {
"message": "ವಹಿವಾಟು ಸಮಯ"
},
"transactionUpdated": {
"message": "$2 ನಲ್ಲಿ ವಹಿವಾಟನ್ನು ನವೀಕರಿಸಲಾಗಿದೆ."
},

View File

@ -164,9 +164,6 @@
"chainId": {
"message": "체인 ID"
},
"chartOnlyAvailableEth": {
"message": "이더리움 네트워크에서만 사용 가능한 차트."
},
"chromeRequiredForHardwareWallets": {
"message": "하드웨어 지갑을 연결하기 위해서는 구글 크롬에서 메타마스크를 사용하셔야 합니다."
},
@ -395,9 +392,6 @@
"fast": {
"message": "빠름"
},
"faster": {
"message": "빨라짐"
},
"fiat": {
"message": "FIAT",
"description": "Exchange type"
@ -573,9 +567,6 @@
"links": {
"message": "링크"
},
"liveGasPricePredictions": {
"message": "실시간 가스 가격 예측"
},
"loadMore": {
"message": "더 많이 로딩"
},
@ -1009,9 +1000,6 @@
"slow": {
"message": "느림"
},
"slower": {
"message": "느려짐"
},
"somethingWentWrong": {
"message": "헉! 뭔가 잘못됐어요."
},
@ -1156,9 +1144,6 @@
"transactionSubmitted": {
"message": "$1의 가스 요금으로 트랜잭션이 제출됨 $2."
},
"transactionTime": {
"message": "트랜잭션 시간"
},
"transactionUpdated": {
"message": "트랜잭션이 수정됨 $2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "Grandinės ID"
},
"chartOnlyAvailableEth": {
"message": "Diagramos yra tik „Ethereum“ tinkluose."
},
"chromeRequiredForHardwareWallets": {
"message": "Norėdami prisijungti prie aparatinės įrangos slaptažodinės, „MetaMask“ naudokitės „Google Chrome“ naršyklėje."
},
@ -398,9 +395,6 @@
"fast": {
"message": "Greitas"
},
"faster": {
"message": "Greičiau"
},
"fiat": {
"message": "Standartinė valiuta",
"description": "Exchange type"
@ -579,9 +573,6 @@
"links": {
"message": "Nuorodos"
},
"liveGasPricePredictions": {
"message": "Tiesioginiai dujų kainos spėjimai"
},
"loadMore": {
"message": "Įkelti daugiau"
},
@ -1018,9 +1009,6 @@
"slow": {
"message": "Lėtas"
},
"slower": {
"message": "Lėčiau"
},
"somethingWentWrong": {
"message": "Vaje! Kažkas negerai."
},
@ -1165,9 +1153,6 @@
"transactionSubmitted": {
"message": "Operacija pateikta $2 su $1 dujų mokesčiu."
},
"transactionTime": {
"message": "Operacijos laikas"
},
"transactionUpdated": {
"message": "Operacija atnaujinta$2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "Ķēdes ID"
},
"chartOnlyAvailableEth": {
"message": "Grafiks pieejams vienīgi Ethereum tīklos."
},
"chromeRequiredForHardwareWallets": {
"message": "MetaMask ir jāpalaiž pārlūkprogrammā Google Chrome, lai varētu pievienot aparatūras maku."
},
@ -398,9 +395,6 @@
"fast": {
"message": "Ātrs"
},
"faster": {
"message": "Ātrāk"
},
"fileImportFail": {
"message": "Vai faila importēšanas iespēja nedarbojas? Klikšķiniet šeit!",
"description": "Helps user import their account from a JSON file"
@ -575,9 +569,6 @@
"links": {
"message": "Saites"
},
"liveGasPricePredictions": {
"message": "Reāllaika Gas cenu prognozes"
},
"loadMore": {
"message": "Ielādēt vairāk"
},
@ -1014,9 +1005,6 @@
"slow": {
"message": "Lēns"
},
"slower": {
"message": "Lēnāk"
},
"somethingWentWrong": {
"message": "Ak vai! Radās problēma."
},
@ -1161,9 +1149,6 @@
"transactionSubmitted": {
"message": "Darījums iesniegts ar maksu par Gas $1 pie $2."
},
"transactionTime": {
"message": "Darījuma ilgums"
},
"transactionUpdated": {
"message": "Darījums atjaunināts $2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "ID Rantaian"
},
"chartOnlyAvailableEth": {
"message": "Carta hanya tersedia di rangkaian Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Anda perlu menggunakan MetaMask di Google Chrome untuk menyambung kepada Dompet Perkakasan anda."
},
@ -392,9 +389,6 @@
"fast": {
"message": "Cepat"
},
"faster": {
"message": "Lebih cepat"
},
"fileImportFail": {
"message": "Pengimportan fail tidak berfungsi? Klik di sini!",
"description": "Helps user import their account from a JSON file"
@ -565,9 +559,6 @@
"links": {
"message": "Pautan"
},
"liveGasPricePredictions": {
"message": "Ramalan Harga Gas Langsung"
},
"loadMore": {
"message": "Muat Lagi"
},
@ -995,9 +986,6 @@
"slow": {
"message": "Perlahan"
},
"slower": {
"message": "Lebih Perlahan"
},
"somethingWentWrong": {
"message": "Alamak! Ada yang tak kena."
},
@ -1139,9 +1127,6 @@
"transactionSubmitted": {
"message": "Transaksi dihantar dengan fi gas sebanyak $1 pada $2."
},
"transactionTime": {
"message": "Masa Transaksi"
},
"transactionUpdated": {
"message": "Transaksi dikemaskini pada $2."
},

View File

@ -164,9 +164,6 @@
"chainId": {
"message": "Blokkjede "
},
"chartOnlyAvailableEth": {
"message": "Diagram kun tilgjengelig på Ethereum-nettverk."
},
"chromeRequiredForHardwareWallets": {
"message": "Du må bruke MetaMask på Google Chrome for å koble deg til maskinvare-lommeboken."
},
@ -395,9 +392,6 @@
"fast": {
"message": "Høy"
},
"faster": {
"message": "Raskere "
},
"fileImportFail": {
"message": "Virker ikke filimporteringen? Trykk her!",
"description": "Helps user import their account from a JSON file"
@ -566,9 +560,6 @@
"links": {
"message": "Lenker "
},
"liveGasPricePredictions": {
"message": "Prisforutsigelse av datakraft i sanntid"
},
"loadMore": {
"message": "Last mer "
},
@ -996,9 +987,6 @@
"slow": {
"message": "Lav"
},
"slower": {
"message": "Saktere"
},
"somethingWentWrong": {
"message": "Oisann! Noe gikk galt. "
},
@ -1137,9 +1125,6 @@
"transactionSubmitted": {
"message": "Transaksjon sendt med datakraftavgift på $1 til $2."
},
"transactionTime": {
"message": "Transaksjonstid"
},
"transactionUpdated": {
"message": "Transaksjonen oppdatert på $2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "Identyfikator łańcucha"
},
"chartOnlyAvailableEth": {
"message": "Wykres dostępny tylko w sieciach Ethereum"
},
"chromeRequiredForHardwareWallets": {
"message": "Żeby połączyć się z portfelem sprzętowym, należy uruchomić MetaMask z przeglądarką Google Chrome."
},
@ -398,9 +395,6 @@
"fast": {
"message": "Szybko"
},
"faster": {
"message": "Szybciej"
},
"fiat": {
"message": "FIAT",
"description": "Exchange type"
@ -579,9 +573,6 @@
"links": {
"message": "Łącza"
},
"liveGasPricePredictions": {
"message": "Przewidywanie ceny gazu na żywo"
},
"loadMore": {
"message": "Załaduj więcej"
},
@ -1012,9 +1003,6 @@
"slow": {
"message": "Powoli"
},
"slower": {
"message": "Wolniej"
},
"somethingWentWrong": {
"message": "Ups! Coś poszło nie tak."
},
@ -1153,9 +1141,6 @@
"transactionSubmitted": {
"message": "Transakcja wykonana z opłatą za gaz w wysokości $1 $2."
},
"transactionTime": {
"message": "Czas transakcji"
},
"transactionUpdated": {
"message": "Transakcja zaktualizowana $2."
},

View File

@ -161,9 +161,6 @@
"chainId": {
"message": "ID da Cadeia"
},
"chartOnlyAvailableEth": {
"message": "Tabela disponível apenas em redes de Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Você precisa usar o MetaMask no Google Chrome para se conectar à sua Carteira de Hardware."
},
@ -392,9 +389,6 @@
"fast": {
"message": "Rápido"
},
"faster": {
"message": "Mais rápido"
},
"fiat": {
"message": "Ordem",
"description": "Exchange type"
@ -570,9 +564,6 @@
"likeToAddTokens": {
"message": "Deseja adicionar esses tokens?"
},
"liveGasPricePredictions": {
"message": "Previsões de Preços de Gás Ao Vivo"
},
"loadMore": {
"message": "Carregar Mais"
},
@ -1006,9 +997,6 @@
"slow": {
"message": "Lento"
},
"slower": {
"message": "Mais lento"
},
"somethingWentWrong": {
"message": "Opa! Algo deu errado."
},
@ -1147,9 +1135,6 @@
"transactionSubmitted": {
"message": "Transação enviada com taxa de gás de $1 a $2."
},
"transactionTime": {
"message": "Hora da Transação"
},
"transactionUpdated": {
"message": "Transação atualizada às $2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "ID lanț"
},
"chartOnlyAvailableEth": {
"message": "Grafic disponibil numai pe rețelele Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Trebuie să folosiți MetaMask în Google Chrome pentru a vă conecta la portofelul hardware."
},
@ -398,9 +395,6 @@
"fast": {
"message": "Rapid"
},
"faster": {
"message": "Mai repede"
},
"fileImportFail": {
"message": "Importarea fișierului nu funcționează? Dați clic aici!",
"description": "Helps user import their account from a JSON file"
@ -569,9 +563,6 @@
"links": {
"message": "Link-uri"
},
"liveGasPricePredictions": {
"message": "Predicții live de preț în gas"
},
"loadMore": {
"message": "Încărcați mai multe"
},
@ -1005,9 +996,6 @@
"slow": {
"message": "Lent"
},
"slower": {
"message": "Mai încet"
},
"somethingWentWrong": {
"message": "Hopa! A apărut o eroare."
},
@ -1149,9 +1137,6 @@
"transactionSubmitted": {
"message": "Tranzacția a fost trimisă, cu o taxă gas de $1 la $2."
},
"transactionTime": {
"message": "Ora tranzacției"
},
"transactionUpdated": {
"message": "Tranzacție actualizată la $2."
},

View File

@ -166,9 +166,6 @@
"chainId": {
"message": "ID сети"
},
"chartOnlyAvailableEth": {
"message": "Диаграмма доступна только в сетях Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Вам необходимо использовать MetaMask в Google Chrome, чтобы подключиться к своему аппаратному кошельку."
},
@ -427,9 +424,6 @@
"fast": {
"message": "Быстро"
},
"faster": {
"message": "Быстрее"
},
"fiat": {
"message": "Валюта",
"description": "Exchange type"
@ -608,9 +602,6 @@
"links": {
"message": "Ссылки"
},
"liveGasPricePredictions": {
"message": "Прогноз цены газа в режиме реального времени"
},
"loadMore": {
"message": "Загрузить еще"
},
@ -1054,9 +1045,6 @@
"slow": {
"message": "Медленно"
},
"slower": {
"message": "Медленнее"
},
"somethingWentWrong": {
"message": "Опс! Что-то пошло не так."
},
@ -1201,9 +1189,6 @@
"transactionSubmitted": {
"message": "Сделка подана с оплатой за газ в размере 1$ за 2$."
},
"transactionTime": {
"message": "Время транзакции"
},
"transactionUpdated": {
"message": "Транзакция обновлена до $2."
},

View File

@ -161,9 +161,6 @@
"chainId": {
"message": "ID reťazca"
},
"chartOnlyAvailableEth": {
"message": "Graf je k dispozícii iba v sieťach Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Ak sa chcete pripojiť k svojej hardvérovej peňaženke, musíte v Google Chrome použiť MetaMask."
},
@ -392,9 +389,6 @@
"fast": {
"message": "Rýchle"
},
"faster": {
"message": "Rýchlejšie"
},
"fiat": {
"message": "FIAT",
"description": "Exchange type"
@ -563,9 +557,6 @@
"links": {
"message": "Odkazy"
},
"liveGasPricePredictions": {
"message": "Predpoveď cien GAS naživo"
},
"loadMore": {
"message": "Načítať viac"
},
@ -981,9 +972,6 @@
"slow": {
"message": "Pomalé"
},
"slower": {
"message": "Pomalší"
},
"somethingWentWrong": {
"message": "Och! Niečo zlyhalo."
},
@ -1122,9 +1110,6 @@
"transactionSubmitted": {
"message": "Transakcia bola odoslaná s poplatkom za GAS z $1 na $2."
},
"transactionTime": {
"message": "Čas transakcie"
},
"transactionUpdated": {
"message": "Transakcia bola aktualizovaná na $2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "ID verige"
},
"chartOnlyAvailableEth": {
"message": "Grafikon na voljo le v glavnih omrežjih."
},
"chromeRequiredForHardwareWallets": {
"message": "Za uporabo strojne denarnice potrebujete Google Chrome."
},
@ -398,9 +395,6 @@
"fast": {
"message": "Hiter"
},
"faster": {
"message": "Hitrejši"
},
"fiat": {
"message": "Klasične",
"description": "Exchange type"
@ -570,9 +564,6 @@
"links": {
"message": "Povezave"
},
"liveGasPricePredictions": {
"message": "Napovedi o gas price"
},
"loadMore": {
"message": "Naloži več"
},
@ -1000,9 +991,6 @@
"slow": {
"message": "Počasen"
},
"slower": {
"message": "Počasnejši"
},
"somethingWentWrong": {
"message": "Oops! Nekaj je šlo narobe."
},
@ -1147,9 +1135,6 @@
"transactionSubmitted": {
"message": "Transakcija z gas fee $1 oddana na $2."
},
"transactionTime": {
"message": "Transakcijski čas"
},
"transactionUpdated": {
"message": "Transakcija na $2 spremenjena."
},

View File

@ -164,9 +164,6 @@
"cancelled": {
"message": "Otkazano"
},
"chartOnlyAvailableEth": {
"message": "Grafikon dostupan jedino na mrežama Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Da biste se povezali sa Vašim hardverskim novčanikom morate da koristite MetaMask na Google Chrome-u."
},
@ -395,9 +392,6 @@
"fast": {
"message": "Брзо"
},
"faster": {
"message": "Brže"
},
"fiat": {
"message": "Dekret",
"description": "Exchange type"
@ -576,9 +570,6 @@
"links": {
"message": "Veze"
},
"liveGasPricePredictions": {
"message": "Predviđanja cene gasa uživo"
},
"loadMore": {
"message": "Učitati više"
},
@ -1009,9 +1000,6 @@
"slow": {
"message": "Споро"
},
"slower": {
"message": "Sporije"
},
"somethingWentWrong": {
"message": "Ups! Nešto nije u redu."
},
@ -1150,9 +1138,6 @@
"transactionSubmitted": {
"message": "Transakcija je podnešena sa gas naknadom od $1 na $2."
},
"transactionTime": {
"message": "Vreme transakcije"
},
"transactionUpdated": {
"message": "Transakcija je ažurirana na $2."
},

View File

@ -161,9 +161,6 @@
"cancelled": {
"message": "Avbruten"
},
"chartOnlyAvailableEth": {
"message": "Tabellen är endast tillgänglig på Ethereum-nätverk."
},
"chromeRequiredForHardwareWallets": {
"message": "Du måste använda MetaMask på Google Chrome för att ansluta till din hårdvaruplånbok."
},
@ -392,9 +389,6 @@
"fast": {
"message": "Snabb"
},
"faster": {
"message": "Snabbare"
},
"fileImportFail": {
"message": "Fungerar inte filimporten? Klicka här!",
"description": "Helps user import their account from a JSON file"
@ -569,9 +563,6 @@
"links": {
"message": "Länkar"
},
"liveGasPricePredictions": {
"message": "Liveuppdaterad gaspris-förutsägelser"
},
"loadMore": {
"message": "Ladda mer"
},
@ -1002,9 +993,6 @@
"slow": {
"message": "Långsamt"
},
"slower": {
"message": "Långsammare"
},
"somethingWentWrong": {
"message": "Hoppsan! Något gick fel."
},
@ -1140,9 +1128,6 @@
"transactionSubmitted": {
"message": "Överföring angedd med gasavgift på $1 vid $2."
},
"transactionTime": {
"message": "Transaktionstid"
},
"transactionUpdated": {
"message": "Transaktionen uppdaterades $2."
},

View File

@ -161,9 +161,6 @@
"chainId": {
"message": "Utambulisho wa Mnyororo"
},
"chartOnlyAvailableEth": {
"message": "Zogoa inapatikana kwenye mitandao ya Ethereum pekee."
},
"chromeRequiredForHardwareWallets": {
"message": "Unapaswa kutumia MetaMask kwenye Google Chrome ili kuungnisha kwenye Waleti yako ya Programu Maunzi."
},
@ -392,9 +389,6 @@
"fast": {
"message": "Haraka"
},
"faster": {
"message": "Ingiza"
},
"fileImportFail": {
"message": "Kuhamisha faili hakufanyi kazi? Bofya hapa!",
"description": "Helps user import their account from a JSON file"
@ -566,9 +560,6 @@
"links": {
"message": "Viungo"
},
"liveGasPricePredictions": {
"message": "Utabiri wa moja kwa moja wa Bei ya Gesi"
},
"loadMore": {
"message": "Pak zAIDI"
},
@ -996,9 +987,6 @@
"slow": {
"message": "Polepole"
},
"slower": {
"message": "Taratibu"
},
"somethingWentWrong": {
"message": "Ayaa! Hitilafu fulani imetokea."
},
@ -1143,9 +1131,6 @@
"transactionSubmitted": {
"message": "Muamala umewasilishwa ukiwa na ada ya gesi ya$1 mnamo $2."
},
"transactionTime": {
"message": "Muda wa Muamala"
},
"transactionUpdated": {
"message": "Muamala umesasishwa mnamo $2."
},

View File

@ -190,9 +190,6 @@
"fast": {
"message": "เร็ว"
},
"faster": {
"message": "เร็วขึ้น"
},
"fiat": {
"message": "เงินตรา",
"description": "Exchange type"
@ -477,9 +474,6 @@
"signed": {
"message": "ลงชื่อแล้ว"
},
"slower": {
"message": "ช้าลง"
},
"stateLogs": {
"message": "บันทึกของสถานะ"
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "ID мережі"
},
"chartOnlyAvailableEth": {
"message": "Таблиця доступна тільки в мережах Ethereum."
},
"chromeRequiredForHardwareWallets": {
"message": "Щоб підключитися до апаратного гаманця, розширення MetaMask потрібно використовувати в Google Chrome."
},
@ -398,9 +395,6 @@
"fast": {
"message": "Швидка"
},
"faster": {
"message": "Швидше"
},
"fiat": {
"message": "Вказівка",
"description": "Exchange type"
@ -579,9 +573,6 @@
"links": {
"message": "Посилання"
},
"liveGasPricePredictions": {
"message": "Прогнози ціни на пальне наживо"
},
"loadMore": {
"message": "Завантажити більше"
},
@ -1018,9 +1009,6 @@
"slow": {
"message": "Повільна"
},
"slower": {
"message": "Повільніше"
},
"somethingWentWrong": {
"message": "Ой! Щось пішло не так."
},
@ -1165,9 +1153,6 @@
"transactionSubmitted": {
"message": "Транзакція надіслана з оплатою за газ $1 о $2."
},
"transactionTime": {
"message": "Час транзакції"
},
"transactionUpdated": {
"message": "Час оновлення транзакції: $2."
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "链 ID"
},
"chartOnlyAvailableEth": {
"message": "聊天功能仅对以太坊网络开放。"
},
"chromeRequiredForHardwareWallets": {
"message": "您需要通过 Google Chrome 浏览器使用 MetaMask ,连接个人硬件钱包。"
},
@ -398,9 +395,6 @@
"fast": {
"message": "快"
},
"faster": {
"message": "快捷操作"
},
"fiat": {
"message": "FIAT",
"description": "Exchange type"
@ -570,9 +564,6 @@
"links": {
"message": "链接"
},
"liveGasPricePredictions": {
"message": "实时天然气价格预测"
},
"loadMore": {
"message": "加载更多"
},
@ -1000,9 +991,6 @@
"slow": {
"message": "慢"
},
"slower": {
"message": "降速"
},
"somethingWentWrong": {
"message": "哎呀!出问题了。"
},
@ -1147,9 +1135,6 @@
"transactionSubmitted": {
"message": "在 $2 提交的交易单,其天然气费为 $1 。"
},
"transactionTime": {
"message": "交易时间"
},
"transactionUpdated": {
"message": "交易单已于 $2 更新。"
},

View File

@ -167,9 +167,6 @@
"chainId": {
"message": "鏈 ID"
},
"chartOnlyAvailableEth": {
"message": "圖表僅適用於以太坊網路。"
},
"chromeRequiredForHardwareWallets": {
"message": "您需要在 Google Chrome 瀏覽器使用 MetaMask 連結您的硬體錢包"
},
@ -398,9 +395,6 @@
"fast": {
"message": "快"
},
"faster": {
"message": "更快"
},
"fiat": {
"message": "法定貨幣",
"description": "Exchange type"
@ -579,9 +573,6 @@
"links": {
"message": "連結"
},
"liveGasPricePredictions": {
"message": "即時 Gas 價格預估"
},
"loadMore": {
"message": "載入更多"
},
@ -997,9 +988,6 @@
"slow": {
"message": "慢"
},
"slower": {
"message": "更慢"
},
"somethingWentWrong": {
"message": "糟糕!出了點問題。"
},
@ -1144,9 +1132,6 @@
"transactionSubmitted": {
"message": "交易送出 手續費 $1 時間 $2"
},
"transactionTime": {
"message": "交易時間"
},
"transactionUpdated": {
"message": "交易狀態更新 時間 $2"
},

View File

@ -47,7 +47,6 @@ export default class PreferencesController {
// perform sensitive operations.
featureFlags: {
showIncomingTransactions: true,
transactionTime: false,
},
knownMethodData: {},
firstTimeFlowType: null,

View File

@ -39,11 +39,10 @@ const dependencies = Object.keys(
)
const materialUIDependencies = ['@material-ui/core']
const reactDepenendencies = dependencies.filter((dep) => dep.match(/react/u))
const d3Dependencies = ['c3', 'd3']
const externalDependenciesMap = {
background: ['3box'],
ui: [...materialUIDependencies, ...reactDepenendencies, ...d3Dependencies],
ui: [...materialUIDependencies, ...reactDepenendencies],
}
function createScriptTasks({ browserPlatforms, livereload }) {

View File

@ -94,12 +94,10 @@
"await-semaphore": "^0.1.1",
"bignumber.js": "^4.1.0",
"bn.js": "^4.11.7",
"c3": "^0.7.10",
"classnames": "^2.2.6",
"content-hash": "^2.5.2",
"copy-to-clipboard": "^3.0.8",
"currency-formatter": "^1.4.2",
"d3": "^5.15.0",
"debounce-stream": "^2.0.0",
"deep-freeze-strict": "1.1.1",
"dnode": "^1.2.2",

File diff suppressed because it is too large Load Diff

View File

@ -45,12 +45,11 @@ async function setupFetchMocking(driver) {
window.origFetch = window.fetch.bind(window)
window.fetch = async (...args) => {
const url = args[0]
if (url.match(/^http(s)?:\/\/ethgasstation\.info\/json\/ethgasAPI.*/u)) {
return { json: async () => clone(mockResponses.ethGasBasic) }
} else if (
url.match(/http(s?):\/\/ethgasstation\.info\/json\/predictTable.*/u)
// api.metaswap.codefi.network/gasPrices
if (
url.match(/^http(s)?:\/\/api\.metaswap\.codefi\.network\/gasPrices/u)
) {
return { json: async () => clone(mockResponses.ethGasPredictTable) }
return { json: async () => clone(mockResponses.gasPricesBasic) }
} else if (url.match(/chromeextensionmm/u)) {
return { json: async () => clone(mockResponses.metametrics) }
} else if (url.match(/^https:\/\/(api\.metaswap|.*airswap-dev)/u)) {

View File

@ -1,8 +1,5 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { decGWEIToHexWEI } from '../../../../../helpers/utils/conversions.util'
import Loading from '../../../../ui/loading-screen'
import GasPriceChart from '../../gas-price-chart'
import AdvancedGasInputs from '../../advanced-gas-inputs'
export default class AdvancedTabContent extends Component {
@ -15,65 +12,46 @@ export default class AdvancedTabContent extends Component {
updateCustomGasLimit: PropTypes.func,
customModalGasPriceInHex: PropTypes.string,
customModalGasLimitInHex: PropTypes.string,
gasEstimatesLoading: PropTypes.bool,
millisecondsRemaining: PropTypes.number,
transactionFee: PropTypes.string,
timeRemaining: PropTypes.string,
gasChartProps: PropTypes.object,
insufficientBalance: PropTypes.bool,
customPriceIsSafe: PropTypes.bool,
isSpeedUp: PropTypes.bool,
isEthereumNetwork: PropTypes.bool,
customGasLimitMessage: PropTypes.string,
minimumGasLimit: PropTypes.number,
}
renderDataSummary(transactionFee, timeRemaining) {
renderDataSummary(transactionFee) {
return (
<div className="advanced-tab__transaction-data-summary">
<div className="advanced-tab__transaction-data-summary__titles">
<span>{this.context.t('newTransactionFee')}</span>
<span>~{this.context.t('transactionTime')}</span>
</div>
<div className="advanced-tab__transaction-data-summary__container">
<div className="advanced-tab__transaction-data-summary__fee">
{transactionFee}
</div>
<div className="advanced-tab__transaction-data-summary__time-remaining">
{timeRemaining}
</div>
</div>
</div>
)
}
onGasChartUpdate = (price) => {
const { updateCustomGasPrice } = this.props
updateCustomGasPrice(decGWEIToHexWEI(price))
}
render() {
const { t } = this.context
const {
updateCustomGasPrice,
updateCustomGasLimit,
timeRemaining,
customModalGasPriceInHex,
customModalGasLimitInHex,
insufficientBalance,
gasChartProps,
gasEstimatesLoading,
customPriceIsSafe,
isSpeedUp,
transactionFee,
isEthereumNetwork,
customGasLimitMessage,
minimumGasLimit,
} = this.props
return (
<div className="advanced-tab">
{this.renderDataSummary(transactionFee, timeRemaining)}
{this.renderDataSummary(transactionFee)}
<div className="advanced-tab__fee-chart">
<div className="advanced-tab__gas-inputs">
<AdvancedGasInputs
@ -88,29 +66,6 @@ export default class AdvancedTabContent extends Component {
minimumGasLimit={minimumGasLimit}
/>
</div>
{isEthereumNetwork ? (
<div>
<div className="advanced-tab__fee-chart__title">
{t('liveGasPricePredictions')}
</div>
{gasEstimatesLoading ? (
<Loading />
) : (
<GasPriceChart
{...gasChartProps}
updateCustomGasPrice={this.onGasChartUpdate}
/>
)}
<div className="advanced-tab__fee-chart__speed-buttons">
<span>{t('slower')}</span>
<span>{t('faster')}</span>
</div>
</div>
) : (
<div className="advanced-tab__fee-chart__title">
{t('chartOnlyAvailableEth')}
</div>
)}
</div>
</div>
)

View File

@ -2,8 +2,7 @@
display: flex;
flex-flow: column;
&__transaction-data-summary,
&__fee-chart-title {
&__transaction-data-summary {
padding-left: 24px;
padding-right: 24px;
}

View File

@ -4,9 +4,6 @@ import sinon from 'sinon'
import shallow from '../../../../../../../lib/shallow-with-context'
import AdvancedTabContent from '../advanced-tab-content.component'
import GasPriceChart from '../../../gas-price-chart'
import Loading from '../../../../../ui/loading-screen'
describe('AdvancedTabContent Component', function () {
let wrapper
@ -23,12 +20,10 @@ describe('AdvancedTabContent Component', function () {
updateCustomGasLimit={propsMethodSpies.updateCustomGasLimit}
customModalGasPriceInHex="11"
customModalGasLimitInHex="23456"
timeRemaining="21500"
transactionFee="$0.25"
insufficientBalance={false}
customPriceIsSafe
isSpeedUp={false}
isEthereumNetwork
/>,
)
})
@ -42,7 +37,7 @@ describe('AdvancedTabContent Component', function () {
assert(wrapper.hasClass('advanced-tab'))
})
it('should render the expected four children of the advanced-tab div', function () {
it('should render the expected child of the advanced-tab div', function () {
const advancedTabChildren = wrapper.children()
assert.equal(advancedTabChildren.length, 2)
@ -51,59 +46,13 @@ describe('AdvancedTabContent Component', function () {
.at(0)
.hasClass('advanced-tab__transaction-data-summary'),
)
assert(advancedTabChildren.at(1).hasClass('advanced-tab__fee-chart'))
const feeChartDiv = advancedTabChildren.at(1)
assert(
feeChartDiv
.childAt(1)
.childAt(0)
.hasClass('advanced-tab__fee-chart__title'),
)
assert(feeChartDiv.childAt(1).childAt(1).is(GasPriceChart))
assert(
feeChartDiv
.childAt(1)
.childAt(2)
.hasClass('advanced-tab__fee-chart__speed-buttons'),
)
})
it('should render a loading component instead of the chart if gasEstimatesLoading is true', function () {
wrapper.setProps({ gasEstimatesLoading: true })
const advancedTabChildren = wrapper.children()
assert.equal(advancedTabChildren.length, 2)
assert(
advancedTabChildren
.at(0)
.hasClass('advanced-tab__transaction-data-summary'),
)
assert(advancedTabChildren.at(1).hasClass('advanced-tab__fee-chart'))
const feeChartDiv = advancedTabChildren.at(1)
assert(
feeChartDiv
.childAt(1)
.childAt(0)
.hasClass('advanced-tab__fee-chart__title'),
)
assert(feeChartDiv.childAt(1).childAt(1).is(Loading))
assert(
feeChartDiv
.childAt(1)
.childAt(2)
.hasClass('advanced-tab__fee-chart__speed-buttons'),
)
})
it('should call renderDataSummary with the expected params', function () {
const renderDataSummaryArgs = AdvancedTabContent.prototype.renderDataSummary.getCall(
0,
).args
assert.deepEqual(renderDataSummaryArgs, ['$0.25', '21500'])
assert.deepEqual(renderDataSummaryArgs, ['$0.25'])
})
})
@ -112,7 +61,7 @@ describe('AdvancedTabContent Component', function () {
beforeEach(function () {
dataSummary = shallow(
wrapper.instance().renderDataSummary('mockTotalFee', 'mockMsRemaining'),
wrapper.instance().renderDataSummary('mockTotalFee'),
)
})
@ -126,7 +75,6 @@ describe('AdvancedTabContent Component', function () {
titlesNode.hasClass('advanced-tab__transaction-data-summary__titles'),
)
assert.equal(titlesNode.children().at(0).text(), 'newTransactionFee')
assert.equal(titlesNode.children().at(1).text(), '~transactionTime')
})
it('should render the data', function () {
@ -135,13 +83,6 @@ describe('AdvancedTabContent Component', function () {
dataNode.hasClass('advanced-tab__transaction-data-summary__container'),
)
assert.equal(dataNode.children().at(0).text(), 'mockTotalFee')
assert(
dataNode
.children()
.at(1)
.hasClass('advanced-tab__transaction-data-summary__time-remaining'),
)
assert.equal(dataNode.children().at(1).text(), 'mockMsRemaining')
})
})
})

View File

@ -16,13 +16,9 @@ export default class GasModalPageContainer extends Component {
hideBasic: PropTypes.bool,
updateCustomGasPrice: PropTypes.func,
updateCustomGasLimit: PropTypes.func,
currentTimeEstimate: PropTypes.string,
insufficientBalance: PropTypes.bool,
fetchBasicGasAndTimeEstimates: PropTypes.func,
fetchGasEstimates: PropTypes.func,
fetchBasicGasEstimates: PropTypes.func,
gasPriceButtonGroupProps: PropTypes.object,
gasChartProps: PropTypes.object,
gasEstimatesLoading: PropTypes.bool,
infoRowProps: PropTypes.shape({
originalTotalFiat: PropTypes.string,
originalTotalEth: PropTypes.string,
@ -35,24 +31,14 @@ export default class GasModalPageContainer extends Component {
customModalGasPriceInHex: PropTypes.string,
customModalGasLimitInHex: PropTypes.string,
cancelAndClose: PropTypes.func,
blockTime: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
customPriceIsSafe: PropTypes.bool,
isSpeedUp: PropTypes.bool,
isRetry: PropTypes.bool,
disableSave: PropTypes.bool,
isEthereumNetwork: PropTypes.bool,
}
componentDidMount() {
const promise = this.props.hideBasic
? Promise.resolve(this.props.blockTime)
: this.props
.fetchBasicGasAndTimeEstimates()
.then((basicEstimates) => basicEstimates.blockTime)
promise.then((blockTime) => {
this.props.fetchGasEstimates(blockTime)
})
this.props.fetchBasicGasEstimates()
}
renderBasicTabContent(gasPriceButtonGroupProps) {
@ -67,15 +53,11 @@ export default class GasModalPageContainer extends Component {
updateCustomGasLimit,
customModalGasPriceInHex,
customModalGasLimitInHex,
gasChartProps,
currentTimeEstimate,
insufficientBalance,
gasEstimatesLoading,
customPriceIsSafe,
isSpeedUp,
isRetry,
infoRowProps: { transactionFee },
isEthereumNetwork,
} = this.props
return (
@ -84,15 +66,11 @@ export default class GasModalPageContainer extends Component {
updateCustomGasLimit={updateCustomGasLimit}
customModalGasPriceInHex={customModalGasPriceInHex}
customModalGasLimitInHex={customModalGasLimitInHex}
timeRemaining={currentTimeEstimate}
transactionFee={transactionFee}
gasChartProps={gasChartProps}
insufficientBalance={insufficientBalance}
gasEstimatesLoading={gasEstimatesLoading}
customPriceIsSafe={customPriceIsSafe}
isSpeedUp={isSpeedUp}
isRetry={isRetry}
isEthereumNetwork={isEthereumNetwork}
/>
)
}

View File

@ -1,5 +1,4 @@
import { connect } from 'react-redux'
import { captureException } from '@sentry/browser'
import { addHexPrefix } from '../../../../../../app/scripts/lib/util'
import {
hideModal,
@ -16,8 +15,7 @@ import {
setCustomGasPrice,
setCustomGasLimit,
resetCustomData,
fetchGasEstimates,
fetchBasicGasAndTimeEstimates,
fetchBasicGasEstimates,
} from '../../../../ducks/gas/gas.duck'
import {
hideGasButtonGroup,
@ -29,21 +27,16 @@ import {
getCurrentEthBalance,
getIsMainnet,
getSendToken,
isEthereumNetwork,
getPreferences,
getBasicGasEstimateLoadingStatus,
getGasEstimatesLoadingStatus,
getCustomGasLimit,
getCustomGasPrice,
getDefaultActiveButtonIndex,
getEstimatedGasPrices,
getEstimatedGasTimes,
getRenderableBasicEstimateData,
getBasicGasEstimateBlockTime,
isCustomPriceSafe,
getTokenBalance,
getSendMaxModeState,
getFastPriceEstimateInHexWEI,
getAveragePriceEstimateInHexWEI,
} from '../../../../selectors'
import {
@ -53,7 +46,6 @@ import {
getValueFromWeiHex,
sumHexWEIsToRenderableFiat,
} from '../../../../helpers/utils/conversions.util'
import { getRenderableTimeEstimate } from '../../../../helpers/utils/gas-time-estimates.util'
import { formatETHFee } from '../../../../helpers/utils/formatters'
import {
calcGasTotal,
@ -73,7 +65,6 @@ const mapStateToProps = (state, ownProps) => {
({ id }) => id === (transaction.id || txData.id),
)
const buttonDataLoading = getBasicGasEstimateLoadingStatus(state)
const gasEstimatesLoading = getGasEstimatesLoadingStatus(state)
const sendToken = getSendToken(state)
// a "default" txParams is used during the send flow, since the transaction doesn't exist yet in that case
@ -81,7 +72,7 @@ const mapStateToProps = (state, ownProps) => {
? selectedTransaction.txParams
: {
gas: send.gasLimit || '0x5208',
gasPrice: send.gasPrice || getFastPriceEstimateInHexWEI(state, true),
gasPrice: send.gasPrice || getAveragePriceEstimateInHexWEI(state, true),
value: sendToken ? '0x0' : send.amount,
}
@ -113,8 +104,6 @@ const mapStateToProps = (state, ownProps) => {
const maxModeOn = getSendMaxModeState(state)
const gasPrices = getEstimatedGasPrices(state)
const estimatedTimes = getEstimatedGasTimes(state)
const balance = getCurrentEthBalance(state)
const { showFiatInTestnets } = getPreferences(state)
@ -142,17 +131,6 @@ const mapStateToProps = (state, ownProps) => {
conversionRate,
})
let currentTimeEstimate = ''
try {
currentTimeEstimate = getRenderableTimeEstimate(
customGasPrice,
gasPrices,
estimatedTimes,
)
} catch (error) {
captureException(error)
}
return {
hideBasic,
isConfirm: isConfirm(state),
@ -162,8 +140,6 @@ const mapStateToProps = (state, ownProps) => {
customGasLimit: calcCustomGasLimit(customModalGasLimitInHex),
customGasTotal,
newTotalFiat,
currentTimeEstimate,
blockTime: getBasicGasEstimateBlockTime(state),
customPriceIsSafe: isCustomPriceSafe(state),
maxModeOn,
gasPriceButtonGroupProps: {
@ -174,13 +150,6 @@ const mapStateToProps = (state, ownProps) => {
),
gasButtonInfo,
},
gasChartProps: {
currentPrice: customGasPrice,
gasPrices,
estimatedTimes,
gasPricesMax: gasPrices[gasPrices.length - 1],
estimatedTimesMax: estimatedTimes[0],
},
infoRowProps: {
originalTotalFiat: sumHexWEIsToRenderableFiat(
[value, customGasTotal],
@ -198,9 +167,7 @@ const mapStateToProps = (state, ownProps) => {
isRetry: transaction.status === TRANSACTION_STATUSES.FAILED,
txId: transaction.id,
insufficientBalance,
gasEstimatesLoading,
isMainnet,
isEthereumNetwork: isEthereumNetwork(state),
sendToken,
balance,
tokenBalance: getTokenBalance(state),
@ -239,9 +206,7 @@ const mapDispatchToProps = (dispatch) => {
},
hideGasButtonGroup: () => dispatch(hideGasButtonGroup()),
hideSidebar: () => dispatch(hideSidebar()),
fetchGasEstimates: (blockTime) => dispatch(fetchGasEstimates(blockTime)),
fetchBasicGasAndTimeEstimates: () =>
dispatch(fetchBasicGasAndTimeEstimates()),
fetchBasicGasEstimates: () => dispatch(fetchBasicGasEstimates()),
setGasTotal: (total) => dispatch(setGasTotal(total)),
setAmountToMax: (maxAmountDataObject) => {
dispatch(updateSendErrors({ amount: null }))

View File

@ -3,23 +3,21 @@ import React from 'react'
import sinon from 'sinon'
import shallow from '../../../../../../lib/shallow-with-context'
import GasModalPageContainer from '../gas-modal-page-container.component'
import timeout from '../../../../../../lib/test-timeout'
import PageContainer from '../../../../ui/page-container'
import { Tab } from '../../../../ui/tabs'
const mockBasicGasEstimates = {
blockTime: 'mockBlockTime',
average: '20',
}
const propsMethodSpies = {
cancelAndClose: sinon.spy(),
onSubmit: sinon.spy(),
fetchBasicGasAndTimeEstimates: sinon
fetchBasicGasEstimates: sinon
.stub()
.returns(Promise.resolve(mockBasicGasEstimates)),
fetchGasEstimates: sinon.spy(),
}
const mockGasPriceButtonGroupProps = {
@ -70,17 +68,11 @@ describe('GasModalPageContainer Component', function () {
<GasModalPageContainer
cancelAndClose={propsMethodSpies.cancelAndClose}
onSubmit={propsMethodSpies.onSubmit}
fetchBasicGasAndTimeEstimates={
propsMethodSpies.fetchBasicGasAndTimeEstimates
}
fetchGasEstimates={propsMethodSpies.fetchGasEstimates}
fetchBasicGasEstimates={propsMethodSpies.fetchBasicGasEstimates}
updateCustomGasPrice={() => 'mockupdateCustomGasPrice'}
updateCustomGasLimit={() => 'mockupdateCustomGasLimit'}
customGasPrice={21}
customGasLimit={54321}
gasPriceButtonGroupProps={mockGasPriceButtonGroupProps}
infoRowProps={mockInfoRowProps}
currentTimeEstimate="1 min 31 sec"
customGasPriceInHex="mockCustomGasPriceInHex"
customGasLimitInHex="mockCustomGasLimitInHex"
insufficientBalance={false}
@ -94,23 +86,11 @@ describe('GasModalPageContainer Component', function () {
})
describe('componentDidMount', function () {
it('should call props.fetchBasicGasAndTimeEstimates', function () {
propsMethodSpies.fetchBasicGasAndTimeEstimates.resetHistory()
assert.equal(propsMethodSpies.fetchBasicGasAndTimeEstimates.callCount, 0)
it('should call props.fetchBasicGasEstimates', function () {
propsMethodSpies.fetchBasicGasEstimates.resetHistory()
assert.equal(propsMethodSpies.fetchBasicGasEstimates.callCount, 0)
wrapper.instance().componentDidMount()
assert.equal(propsMethodSpies.fetchBasicGasAndTimeEstimates.callCount, 1)
})
it('should call props.fetchGasEstimates with the block time returned by fetchBasicGasAndTimeEstimates', async function () {
propsMethodSpies.fetchGasEstimates.resetHistory()
assert.equal(propsMethodSpies.fetchGasEstimates.callCount, 0)
wrapper.instance().componentDidMount()
await timeout(250)
assert.equal(propsMethodSpies.fetchGasEstimates.callCount, 1)
assert.equal(
propsMethodSpies.fetchGasEstimates.getCall(0).args[0],
'mockBlockTime',
)
assert.equal(propsMethodSpies.fetchBasicGasEstimates.callCount, 1)
})
})
@ -139,9 +119,7 @@ describe('GasModalPageContainer Component', function () {
sinon.stub(GP, 'renderTabs').returns('mockTabs')
const renderTabsWrapperTester = shallow(
<GasModalPageContainer
fetchBasicGasAndTimeEstimates={
propsMethodSpies.fetchBasicGasAndTimeEstimates
}
fetchBasicGasEstimates={propsMethodSpies.fetchBasicGasEstimates}
fetchGasEstimates={propsMethodSpies.fetchGasEstimates}
/>,
{ context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } },
@ -208,17 +186,11 @@ describe('GasModalPageContainer Component', function () {
<GasModalPageContainer
cancelAndClose={propsMethodSpies.cancelAndClose}
onSubmit={propsMethodSpies.onSubmit}
fetchBasicGasAndTimeEstimates={
propsMethodSpies.fetchBasicGasAndTimeEstimates
}
fetchGasEstimates={propsMethodSpies.fetchGasEstimates}
fetchBasicGasEstimates={propsMethodSpies.fetchBasicGasEstimates}
updateCustomGasPrice={() => 'mockupdateCustomGasPrice'}
updateCustomGasLimit={() => 'mockupdateCustomGasLimit'}
customGasPrice={21}
customGasLimit={54321}
gasPriceButtonGroupProps={mockGasPriceButtonGroupProps}
infoRowProps={mockInfoRowProps}
currentTimeEstimate="1 min 31 sec"
customGasPriceInHex="mockCustomGasPriceInHex"
customGasLimitInHex="mockCustomGasLimitInHex"
insufficientBalance={false}

View File

@ -104,7 +104,6 @@ describe('gas-modal-page-container container', function () {
limit: 'aaaaaaaa',
price: 'ffffffff',
},
gasEstimatesLoading: false,
priceAndTimeEstimates: [
{ gasprice: 3, expectedTime: 31 },
{ gasprice: 4, expectedTime: 62 },
@ -127,27 +126,17 @@ describe('gas-modal-page-container container', function () {
isConfirm: true,
customGasPrice: 4.294967295,
customGasLimit: 2863311530,
currentTimeEstimate: '~1 min 11 sec',
newTotalFiat: '637.41',
blockTime: 12,
conversionRate: 50,
customModalGasLimitInHex: 'aaaaaaaa',
customModalGasPriceInHex: 'ffffffff',
customGasTotal: 'aaaaaaa955555556',
customPriceIsSafe: true,
gasChartProps: {
currentPrice: 4.294967295,
estimatedTimes: [31, 62, 93, 124],
estimatedTimesMax: 31,
gasPrices: [3, 4, 5, 6],
gasPricesMax: 6,
},
gasPriceButtonGroupProps: {
buttonDataLoading: 'mockBasicGasEstimateLoadingStatus:4',
defaultActiveButtonIndex: 'mockRenderableBasicEstimateData:4ffffffff',
gasButtonInfo: 'mockRenderableBasicEstimateData:4',
},
gasEstimatesLoading: false,
hideBasic: true,
infoRowProps: {
originalTotalFiat: '637.41',
@ -161,7 +150,6 @@ describe('gas-modal-page-container container', function () {
isSpeedUp: false,
isRetry: false,
txId: 34,
isEthereumNetwork: true,
isMainnet: true,
maxModeOn: false,
sendToken: null,

View File

@ -1,123 +0,0 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import * as d3 from 'd3'
import {
generateChart,
getCoordinateData,
handleChartUpdate,
hideDataUI,
setTickPosition,
handleMouseMove,
} from './gas-price-chart.utils'
export default class GasPriceChart extends Component {
static contextTypes = {
t: PropTypes.func,
}
static propTypes = {
gasPrices: PropTypes.array,
estimatedTimes: PropTypes.array,
gasPricesMax: PropTypes.number,
estimatedTimesMax: PropTypes.number,
currentPrice: PropTypes.number,
updateCustomGasPrice: PropTypes.func,
}
renderChart() {
const {
currentPrice,
gasPrices,
estimatedTimes,
gasPricesMax,
estimatedTimesMax,
updateCustomGasPrice,
} = this.props
const chart = generateChart(
gasPrices,
estimatedTimes,
gasPricesMax,
estimatedTimesMax,
this.context.t,
)
setTimeout(function () {
setTickPosition('y', 0, -5, 8)
setTickPosition('y', 1, -3, -5)
setTickPosition('x', 0, 3)
setTickPosition('x', 1, 3, -8)
const { x: domainX } = getCoordinateData('.domain')
const { x: yAxisX } = getCoordinateData('.c3-axis-y-label')
const { x: tickX } = getCoordinateData('.c3-axis-x .tick')
d3.select('.c3-axis-x .tick').attr(
'transform',
`translate(${(domainX - tickX) / 2}, 0)`,
)
d3.select('.c3-axis-x-label').attr('transform', 'translate(0,-15)')
d3.select('.c3-axis-y-label').attr(
'transform',
`translate(${domainX - yAxisX - 12}, 2) rotate(-90)`,
)
d3.select('.c3-xgrid-focus line').attr('y2', 98)
d3.select('.c3-chart').on('mouseout', () => {
hideDataUI(chart, '#overlayed-circle')
})
d3.select('.c3-chart').on('click', () => {
const { x: newGasPrice } = d3.select('#overlayed-circle').datum()
updateCustomGasPrice(newGasPrice)
})
const { x: chartXStart, width: chartWidth } = getCoordinateData(
'.c3-areas-data1',
)
handleChartUpdate({
chart,
gasPrices,
newPrice: currentPrice,
cssId: '#set-circle',
})
d3.select('.c3-chart').on('mousemove', function () {
handleMouseMove({
xMousePos: d3.event.clientX,
chartXStart,
chartWidth,
gasPrices,
estimatedTimes,
chart,
})
})
}, 0)
this.chart = chart
}
componentDidUpdate(prevProps) {
const { gasPrices, currentPrice: newPrice } = this.props
if (prevProps.currentPrice !== newPrice) {
handleChartUpdate({
chart: this.chart,
gasPrices,
newPrice,
cssId: '#set-circle',
})
}
}
componentDidMount() {
this.renderChart()
}
render() {
return (
<div className="gas-price-chart" id="container">
<div className="gas-price-chart__root" id="chart"></div>
</div>
)
}
}

View File

@ -1,422 +0,0 @@
import * as d3 from 'd3'
import c3 from 'c3'
import {
extrapolateY,
getAdjacentGasPrices,
newBigSigDig,
bigNumMinus,
bigNumDiv,
} from '../../../../helpers/utils/gas-time-estimates.util'
export function handleMouseMove({
xMousePos,
chartXStart,
chartWidth,
gasPrices,
estimatedTimes,
chart,
}) {
const { currentPosValue, newTimeEstimate } = getNewXandTimeEstimate({
xMousePos,
chartXStart,
chartWidth,
gasPrices,
estimatedTimes,
})
if (currentPosValue === null && newTimeEstimate === null) {
hideDataUI(chart, '#overlayed-circle')
return
}
const indexOfNewCircle = estimatedTimes.length + 1
const dataUIObj = generateDataUIObj(
currentPosValue,
indexOfNewCircle,
newTimeEstimate,
)
chart.internal.overlayPoint(dataUIObj, indexOfNewCircle)
chart.internal.showTooltip(
[dataUIObj],
d3.select('.c3-areas-data1')._groups[0],
)
chart.internal.showXGridFocus([dataUIObj])
}
export function getCoordinateData(selector) {
const node = d3.select(selector).node()
return node ? node.getBoundingClientRect() : {}
}
export function generateDataUIObj(x, index, value) {
return {
x,
value,
index,
id: 'data1',
name: 'data1',
}
}
export function handleChartUpdate({ chart, gasPrices, newPrice, cssId }) {
const {
closestLowerValueIndex,
closestLowerValue,
closestHigherValueIndex,
closestHigherValue,
} = getAdjacentGasPrices({ gasPrices, priceToPosition: newPrice })
if (closestLowerValue && closestHigherValue) {
setSelectedCircle({
chart,
newPrice,
closestLowerValueIndex,
closestLowerValue,
closestHigherValueIndex,
closestHigherValue,
})
} else {
hideDataUI(chart, cssId)
}
}
export function getNewXandTimeEstimate({
xMousePos,
chartXStart,
chartWidth,
gasPrices,
estimatedTimes,
}) {
const chartMouseXPos = bigNumMinus(xMousePos, chartXStart)
const posPercentile = bigNumDiv(chartMouseXPos, chartWidth)
const currentPosValue = bigNumMinus(
gasPrices[gasPrices.length - 1],
gasPrices[0],
)
.times(newBigSigDig(posPercentile))
.plus(newBigSigDig(gasPrices[0]))
.toNumber()
const {
closestLowerValueIndex,
closestLowerValue,
closestHigherValueIndex,
closestHigherValue,
} = getAdjacentGasPrices({ gasPrices, priceToPosition: currentPosValue })
return !closestHigherValue || !closestLowerValue
? {
currentPosValue: null,
newTimeEstimate: null,
}
: {
currentPosValue,
newTimeEstimate: extrapolateY({
higherY: estimatedTimes[closestHigherValueIndex],
lowerY: estimatedTimes[closestLowerValueIndex],
higherX: closestHigherValue,
lowerX: closestLowerValue,
xForExtrapolation: currentPosValue,
}),
}
}
export function hideDataUI(chart, dataNodeId) {
const overLayedCircle = d3.select(dataNodeId)
if (!overLayedCircle.empty()) {
overLayedCircle.remove()
}
d3.select('.c3-tooltip-container').style('display', 'none !important')
chart.internal.hideXGridFocus()
}
export function setTickPosition(axis, n, newPosition, secondNewPosition) {
const positionToShift = axis === 'y' ? 'x' : 'y'
const secondPositionToShift = axis === 'y' ? 'y' : 'x'
d3.select('#chart')
.select(`.c3-axis-${axis}`)
.selectAll('.tick')
.filter((_, i) => i === n)
.select('text')
.attr(positionToShift, 0)
.select('tspan')
.attr(positionToShift, newPosition)
.attr(secondPositionToShift, secondNewPosition || 0)
.style('visibility', 'visible')
}
/* eslint-disable @babel/no-invalid-this */
export function appendOrUpdateCircle({
data,
itemIndex,
cx,
cy,
cssId,
appendOnly,
}) {
const circle = this.main
.select(`.c3-selected-circles${this.getTargetSelectorSuffix(data.id)}`)
.selectAll(`.c3-selected-circle-${itemIndex}`)
if (appendOnly || circle.empty()) {
circle
.data([data])
.enter()
.append('circle')
.attr('class', () => this.generateClass('c3-selected-circle', itemIndex))
.attr('id', cssId)
.attr('cx', cx)
.attr('cy', cy)
.attr('stroke', () => this.color(data))
.attr('r', 6)
} else {
circle.data([data]).attr('cx', cx).attr('cy', cy)
}
}
/* eslint-enable @babel/no-invalid-this */
export function setSelectedCircle({
chart,
newPrice,
closestLowerValueIndex,
closestLowerValue,
closestHigherValueIndex,
closestHigherValue,
}) {
const numberOfValues = chart.internal.data.xs.data1.length
const { x: lowerX, y: lowerY } = getCoordinateData(
`.c3-circle-${closestLowerValueIndex}`,
)
let { x: higherX, y: higherY } = getCoordinateData(
`.c3-circle-${closestHigherValueIndex}`,
)
let count = closestHigherValueIndex + 1
if (lowerX && higherX) {
while (lowerX === higherX) {
higherX = getCoordinateData(`.c3-circle-${count}`).x
higherY = getCoordinateData(`.c3-circle-${count}`).y
count += 1
}
}
const currentX = bigNumMinus(higherX, lowerX)
.times(bigNumMinus(newPrice, closestLowerValue))
.div(bigNumMinus(closestHigherValue, closestLowerValue))
.plus(newBigSigDig(lowerX))
const newTimeEstimate = extrapolateY({
higherY,
lowerY,
higherX,
lowerX,
xForExtrapolation: currentX,
})
chart.internal.selectPoint(
generateDataUIObj(currentX.toNumber(), numberOfValues, newTimeEstimate),
numberOfValues,
)
}
export function generateChart(
gasPrices,
estimatedTimes,
gasPricesMax,
estimatedTimesMax,
) {
const gasPricesMaxPadded = gasPricesMax + 1
const chart = c3.generate({
size: {
height: 165,
},
transition: {
duration: 0,
},
padding: { left: 20, right: 15, top: 6, bottom: 10 },
data: {
x: 'x',
columns: [
['x', ...gasPrices],
['data1', ...estimatedTimes],
],
types: {
data1: 'area',
},
selection: {
enabled: false,
},
},
color: {
data1: '#259de5',
},
axis: {
x: {
min: gasPrices[0],
max: gasPricesMax,
tick: {
values: [Math.floor(gasPrices[0]), Math.ceil(gasPricesMax)],
outer: false,
format(val) {
return `${val} GWEI`
},
},
padding: { left: gasPricesMax / 50, right: gasPricesMax / 50 },
label: {
text: 'Gas Price ($)',
position: 'outer-center',
},
},
y: {
padding: { top: 7, bottom: 7 },
tick: {
values: [
Math.floor(estimatedTimesMax * 0.05),
Math.ceil(estimatedTimesMax * 0.97),
],
outer: false,
},
label: {
text: 'Confirmation time (sec)',
position: 'outer-middle',
},
min: 0,
},
},
legend: {
show: false,
},
grid: {
x: {},
lines: {
front: false,
},
},
point: {
focus: {
expand: {
enabled: false,
r: 3.5,
},
},
},
tooltip: {
format: {
title: (v) => v.toPrecision(4),
},
contents(d) {
const titleFormat = this.config.tooltip_format_title
let text
d.forEach((el) => {
if (el && (el.value || el.value === 0) && !text) {
text = `<table class='custom-tooltip'><tr><th colspan='2'>${titleFormat(
el.x,
)}</th></tr>`
}
})
return `${text}</table><div class='tooltip-arrow'></div>`
},
position() {
if (d3.select('#overlayed-circle').empty()) {
return { top: -100, left: -100 }
}
const {
x: circleX,
y: circleY,
width: circleWidth,
} = getCoordinateData('#overlayed-circle')
const { x: chartXStart, y: chartYStart } = getCoordinateData(
'.c3-chart',
)
// TODO: Confirm the below constants work with all data sets and screen sizes
const flipTooltip = circleY - circleWidth < chartYStart + 5
d3.select('.tooltip-arrow').style(
'margin-top',
flipTooltip ? '-16px' : '4px',
)
return {
top: bigNumMinus(circleY, chartYStart)
.minus(19)
.plus(flipTooltip ? circleWidth + 38 : 0)
.toNumber(),
left: bigNumMinus(circleX, chartXStart)
.plus(newBigSigDig(circleWidth))
.minus(bigNumDiv(gasPricesMaxPadded, 50))
.toNumber(),
}
},
show: true,
},
})
chart.internal.selectPoint = function (data, itemIndex = data.index || 0) {
const { x: chartXStart, y: chartYStart } = getCoordinateData(
'.c3-areas-data1',
)
d3.select('#set-circle').remove()
appendOrUpdateCircle.bind(this)({
data,
itemIndex,
cx: () => bigNumMinus(data.x, chartXStart).plus(11).toNumber(),
cy: () => bigNumMinus(data.value, chartYStart).plus(10).toNumber(),
cssId: 'set-circle',
appendOnly: true,
})
}
chart.internal.overlayPoint = function (data, itemIndex) {
appendOrUpdateCircle.bind(this)({
data,
itemIndex,
cx: this.circleX.bind(this),
cy: this.circleY.bind(this),
cssId: 'overlayed-circle',
})
}
chart.internal.showTooltip = function (selectedData, element) {
const dataToShow = selectedData.filter(
(d) => d && (d.value || d.value === 0),
)
if (dataToShow.length) {
this.tooltip
.html(
this.config.tooltip_contents.call(
this,
selectedData,
this.axis.getXAxisTickFormat(),
this.getYFormat(),
this.color,
),
)
.style('display', 'flex')
// Get tooltip dimensions
const tWidth = this.tooltip.property('offsetWidth')
const tHeight = this.tooltip.property('offsetHeight')
const position = this.config.tooltip_position.call(
this,
dataToShow,
tWidth,
tHeight,
element,
)
// Set tooltip
this.tooltip
.style('top', `${position.top}px`)
.style('left', `${position.left}px`)
}
}
return chart
}

View File

@ -1 +0,0 @@
export { default } from './gas-price-chart.component'

View File

@ -1,134 +0,0 @@
.gas-price-chart {
display: flex;
position: relative;
justify-content: center;
&__root {
max-height: 154px;
max-width: 391px;
position: relative;
overflow: hidden;
@media screen and (max-width: $break-small) {
max-width: 326px;
}
}
.tick text,
.c3-axis-x-label,
.c3-axis-y-label {
@include H9;
line-height: normal;
font-weight: bold;
text-align: center;
fill: #9a9ca6 !important;
}
.c3-tooltip-container {
display: flex;
justify-content: center !important;
align-items: flex-end !important;
}
.custom-tooltip {
background: rgba(0, 0, 0, 1);
box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25);
border-radius: 3px;
opacity: 1 !important;
height: 21px;
z-index: 1;
}
.tooltip-arrow {
background: black;
box-shadow: 0 4px 4px rgba(0, 0, 0, 0.5);
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
opacity: 1 !important;
width: 9px;
height: 9px;
margin-top: 4px;
}
.custom-tooltip th {
@include H8;
font-weight: 500;
text-align: center;
padding: 3px;
color: #fff;
}
.c3-circle {
visibility: hidden;
}
.c3-selected-circle,
.c3-circle._expanded_ {
fill: #fff !important;
stroke-width: 2.4px !important;
stroke: #2d9fd9 !important;
/* visibility: visible; */
}
#set-circle {
fill: #313a5e !important;
stroke: #313a5e !important;
}
.c3-axis-x-label,
.c3-axis-y-label {
font-weight: normal;
}
.tick text tspan {
visibility: hidden;
}
.c3-circle {
fill: #2d9fd9 !important;
}
.c3-line-data1 {
stroke: #2d9fd9 !important;
background: rgba(0, 0, 0, 0) !important;
color: rgba(0, 0, 0, 0) !important;
}
.c3 path {
fill: none;
}
.c3 path.c3-area-data1 {
opacity: 1;
fill: #e9edf1 !important;
}
.c3-xgrid-line line {
stroke: #b8b8b8 !important;
}
.c3-xgrid-focus {
stroke: #aaa;
}
.c3-axis-x .domain {
fill: none;
stroke: none;
}
.c3-axis-y .domain {
fill: none;
stroke: #c8ccd6;
}
.c3-event-rect {
cursor: pointer;
}
}
#chart {
background: #f8f9fb;
}

View File

@ -1,258 +0,0 @@
import assert from 'assert'
import React from 'react'
import proxyquire from 'proxyquire'
import sinon from 'sinon'
import * as d3 from 'd3'
import shallow from '../../../../../../lib/shallow-with-context'
function timeout(time) {
return new Promise((resolve) => {
setTimeout(resolve, time)
})
}
describe('GasPriceChart Component', function () {
let GasPriceChart
let gasPriceChartUtilsSpies
let propsMethodSpies
let selectReturnSpies
let testProps
let wrapper
beforeEach(function () {
propsMethodSpies = {
updateCustomGasPrice: sinon.spy(),
}
selectReturnSpies = {
empty: sinon.spy(),
remove: sinon.spy(),
style: sinon.spy(),
select: d3.select,
attr: sinon.spy(),
on: sinon.spy(),
datum: sinon.stub().returns({ x: 'mockX' }),
}
const mockSelectReturn = {
...d3.select('div'),
node: () => ({
getBoundingClientRect: () => ({ x: 123, y: 321, width: 400 }),
}),
...selectReturnSpies,
}
gasPriceChartUtilsSpies = {
appendOrUpdateCircle: sinon.spy(),
generateChart: sinon.stub().returns({ mockChart: true }),
generateDataUIObj: sinon.spy(),
getAdjacentGasPrices: sinon.spy(),
getCoordinateData: sinon
.stub()
.returns({ x: 'mockCoordinateX', width: 'mockWidth' }),
getNewXandTimeEstimate: sinon.spy(),
handleChartUpdate: sinon.spy(),
hideDataUI: sinon.spy(),
setSelectedCircle: sinon.spy(),
setTickPosition: sinon.spy(),
handleMouseMove: sinon.spy(),
}
testProps = {
gasPrices: [1.5, 2.5, 4, 8],
estimatedTimes: [100, 80, 40, 10],
gasPricesMax: 9,
estimatedTimesMax: 100,
currentPrice: 6,
updateCustomGasPrice: propsMethodSpies.updateCustomGasPrice,
}
GasPriceChart = proxyquire('../gas-price-chart.component.js', {
'./gas-price-chart.utils.js': gasPriceChartUtilsSpies,
d3: {
...d3,
select(...args) {
const result = d3.select(...args)
return result.empty() ? mockSelectReturn : result
},
event: {
clientX: 'mockClientX',
},
},
}).default
sinon.spy(GasPriceChart.prototype, 'renderChart')
wrapper = shallow(<GasPriceChart {...testProps} />)
})
afterEach(function () {
sinon.restore()
})
describe('render()', function () {
it('should render', function () {
assert(wrapper.hasClass('gas-price-chart'))
})
it('should render the chart div', function () {
assert(wrapper.childAt(0).hasClass('gas-price-chart__root'))
assert.equal(wrapper.childAt(0).props().id, 'chart')
})
})
describe('componentDidMount', function () {
it('should call this.renderChart', function () {
assert(GasPriceChart.prototype.renderChart.callCount, 1)
wrapper.instance().componentDidMount()
assert(GasPriceChart.prototype.renderChart.callCount, 2)
})
})
describe('componentDidUpdate', function () {
it('should call handleChartUpdate if props.currentPrice has changed', function () {
gasPriceChartUtilsSpies.handleChartUpdate.resetHistory()
wrapper.instance().componentDidUpdate({ currentPrice: 7 })
assert.equal(gasPriceChartUtilsSpies.handleChartUpdate.callCount, 1)
})
it('should call handleChartUpdate with the correct props', function () {
gasPriceChartUtilsSpies.handleChartUpdate.resetHistory()
wrapper.instance().componentDidUpdate({ currentPrice: 7 })
assert.deepEqual(
gasPriceChartUtilsSpies.handleChartUpdate.getCall(0).args,
[
{
chart: { mockChart: true },
gasPrices: [1.5, 2.5, 4, 8],
newPrice: 6,
cssId: '#set-circle',
},
],
)
})
it('should not call handleChartUpdate if props.currentPrice has not changed', function () {
gasPriceChartUtilsSpies.handleChartUpdate.resetHistory()
wrapper.instance().componentDidUpdate({ currentPrice: 6 })
assert.equal(gasPriceChartUtilsSpies.handleChartUpdate.callCount, 0)
})
})
describe('renderChart', function () {
it('should call setTickPosition 4 times, with the expected props', async function () {
await timeout(0)
gasPriceChartUtilsSpies.setTickPosition.resetHistory()
assert.equal(gasPriceChartUtilsSpies.setTickPosition.callCount, 0)
wrapper.instance().renderChart(testProps)
await timeout(0)
assert.equal(gasPriceChartUtilsSpies.setTickPosition.callCount, 4)
assert.deepEqual(
gasPriceChartUtilsSpies.setTickPosition.getCall(0).args,
['y', 0, -5, 8],
)
assert.deepEqual(
gasPriceChartUtilsSpies.setTickPosition.getCall(1).args,
['y', 1, -3, -5],
)
assert.deepEqual(
gasPriceChartUtilsSpies.setTickPosition.getCall(2).args,
['x', 0, 3],
)
assert.deepEqual(
gasPriceChartUtilsSpies.setTickPosition.getCall(3).args,
['x', 1, 3, -8],
)
})
it('should call handleChartUpdate with the correct props', async function () {
await timeout(0)
gasPriceChartUtilsSpies.handleChartUpdate.resetHistory()
wrapper.instance().renderChart(testProps)
await timeout(0)
assert.deepEqual(
gasPriceChartUtilsSpies.handleChartUpdate.getCall(0).args,
[
{
chart: { mockChart: true },
gasPrices: [1.5, 2.5, 4, 8],
newPrice: 6,
cssId: '#set-circle',
},
],
)
})
it('should add three events to the chart', async function () {
await timeout(0)
selectReturnSpies.on.resetHistory()
assert.equal(selectReturnSpies.on.callCount, 0)
wrapper.instance().renderChart(testProps)
await timeout(0)
assert.equal(selectReturnSpies.on.callCount, 3)
const firstOnEventArgs = selectReturnSpies.on.getCall(0).args
assert.equal(firstOnEventArgs[0], 'mouseout')
const secondOnEventArgs = selectReturnSpies.on.getCall(1).args
assert.equal(secondOnEventArgs[0], 'click')
const thirdOnEventArgs = selectReturnSpies.on.getCall(2).args
assert.equal(thirdOnEventArgs[0], 'mousemove')
})
it('should hide the data UI on mouseout', async function () {
await timeout(0)
selectReturnSpies.on.resetHistory()
wrapper.instance().renderChart(testProps)
gasPriceChartUtilsSpies.hideDataUI.resetHistory()
await timeout(0)
const mouseoutEventArgs = selectReturnSpies.on.getCall(0).args
assert.equal(gasPriceChartUtilsSpies.hideDataUI.callCount, 0)
mouseoutEventArgs[1]()
assert.equal(gasPriceChartUtilsSpies.hideDataUI.callCount, 1)
assert.deepEqual(gasPriceChartUtilsSpies.hideDataUI.getCall(0).args, [
{ mockChart: true },
'#overlayed-circle',
])
})
it('should updateCustomGasPrice on click', async function () {
await timeout(0)
selectReturnSpies.on.resetHistory()
wrapper.instance().renderChart(testProps)
propsMethodSpies.updateCustomGasPrice.resetHistory()
await timeout(0)
const mouseoutEventArgs = selectReturnSpies.on.getCall(1).args
assert.equal(propsMethodSpies.updateCustomGasPrice.callCount, 0)
mouseoutEventArgs[1]()
assert.equal(propsMethodSpies.updateCustomGasPrice.callCount, 1)
assert.equal(
propsMethodSpies.updateCustomGasPrice.getCall(0).args[0],
'mockX',
)
})
it('should handle mousemove', async function () {
await timeout(0)
selectReturnSpies.on.resetHistory()
wrapper.instance().renderChart(testProps)
gasPriceChartUtilsSpies.handleMouseMove.resetHistory()
await timeout(0)
const mouseoutEventArgs = selectReturnSpies.on.getCall(2).args
assert.equal(gasPriceChartUtilsSpies.handleMouseMove.callCount, 0)
mouseoutEventArgs[1]()
assert.equal(gasPriceChartUtilsSpies.handleMouseMove.callCount, 1)
assert.deepEqual(
gasPriceChartUtilsSpies.handleMouseMove.getCall(0).args,
[
{
xMousePos: 'mockClientX',
chartXStart: 'mockCoordinateX',
chartWidth: 'mockWidth',
gasPrices: testProps.gasPrices,
estimatedTimes: testProps.estimatedTimes,
chart: { mockChart: true },
},
],
)
})
})
})

View File

@ -1,4 +1,3 @@
@import './gas-slider/index';
@import './gas-modal-page-container/index';
@import './gas-price-chart/index';
@import './advanced-gas-inputs/index';

View File

@ -23,14 +23,6 @@
}
}
.gas-price-chart {
margin-left: 10px;
&__root {
max-height: 160px !important;
}
}
.page-container__bottom {
display: flex;
flex-direction: column;

View File

@ -4,7 +4,6 @@ import classnames from 'classnames'
import { useHistory } from 'react-router-dom'
import ListItem from '../../ui/list-item'
import { useTransactionDisplayData } from '../../../hooks/useTransactionDisplayData'
import Preloader from '../../ui/icon/preloader'
import { useI18nContext } from '../../../hooks/useI18nContext'
import { useCancelTransaction } from '../../../hooks/useCancelTransaction'
import { useRetryTransaction } from '../../../hooks/useRetryTransaction'
@ -15,8 +14,6 @@ import { CONFIRM_TRANSACTION_ROUTE } from '../../../helpers/constants/routes'
import { useShouldShowSpeedUp } from '../../../hooks/useShouldShowSpeedUp'
import TransactionStatus from '../transaction-status/transaction-status.component'
import TransactionIcon from '../transaction-icon'
import { useTransactionTimeRemaining } from '../../../hooks/useTransactionTimeRemaining'
import IconWithLabel from '../../ui/icon-with-label'
import {
TRANSACTION_GROUP_CATEGORIES,
TRANSACTION_STATUSES,
@ -33,7 +30,7 @@ export default function TransactionListItem({
const {
initialTransaction: { id },
primaryTransaction: { err, gasPrice, status, submittedTime },
primaryTransaction: { err, status },
} = transactionGroup
const [cancelEnabled, cancelTransaction] = useCancelTransaction(
transactionGroup,
@ -56,16 +53,8 @@ export default function TransactionListItem({
displayedStatusKey,
isPending,
senderAddress,
isSubmitted,
} = useTransactionDisplayData(transactionGroup)
const timeRemaining = useTransactionTimeRemaining(
isSubmitted,
isEarliestNonce,
submittedTime,
gasPrice,
)
const isSignatureReq =
category === TRANSACTION_GROUP_CATEGORIES.SIGNATURE_REQUEST
const isApproval = category === TRANSACTION_GROUP_CATEGORIES.APPROVAL
@ -143,16 +132,6 @@ export default function TransactionListItem({
onClick={toggleShowDetails}
className={className}
title={title}
titleIcon={
!isUnapproved &&
isPending &&
isEarliestNonce && (
<IconWithLabel
icon={<Preloader size={16} color="#D73A49" />}
label={timeRemaining}
/>
)
}
icon={
<TransactionIcon category={category} status={displayedStatusKey} />
}

View File

@ -1,12 +1,10 @@
import React, { useMemo, useEffect, useRef, useState, useCallback } from 'react'
import React, { useMemo, useState, useCallback } from 'react'
import PropTypes from 'prop-types'
import { useSelector, useDispatch } from 'react-redux'
import { useSelector } from 'react-redux'
import {
nonceSortedCompletedTransactionsSelector,
nonceSortedPendingTransactionsSelector,
} from '../../../selectors/transactions'
import { getFeatureFlags } from '../../../selectors/selectors'
import * as actions from '../../../ducks/gas/gas.duck'
import { useI18nContext } from '../../../hooks/useI18nContext'
import TransactionListItem from '../transaction-list-item'
import Button from '../../ui/button'
@ -63,16 +61,12 @@ export default function TransactionList({
const [limit, setLimit] = useState(PAGE_INCREMENT)
const t = useI18nContext()
const dispatch = useDispatch()
const unfilteredPendingTransactions = useSelector(
nonceSortedPendingTransactionsSelector,
)
const unfilteredCompletedTransactions = useSelector(
nonceSortedCompletedTransactionsSelector,
)
const { transactionTime: transactionTimeFeatureActive } = useSelector(
getFeatureFlags,
)
const pendingTransactions = useMemo(
() =>
@ -93,55 +87,6 @@ export default function TransactionList({
[hideTokenTransactions, tokenAddress, unfilteredCompletedTransactions],
)
const { fetchGasEstimates, fetchBasicGasAndTimeEstimates } = useMemo(
() => ({
fetchGasEstimates: (blockTime) =>
dispatch(actions.fetchGasEstimates(blockTime)),
fetchBasicGasAndTimeEstimates: () =>
dispatch(actions.fetchBasicGasAndTimeEstimates()),
}),
[dispatch],
)
// keep track of previous values from state.
// loaded is used here to determine if our effect has ran at least once.
const prevState = useRef({
loaded: false,
pendingTransactions,
transactionTimeFeatureActive,
})
useEffect(() => {
const { loaded } = prevState.current
const pendingTransactionAdded =
pendingTransactions.length > 0 &&
prevState.current.pendingTransactions.length === 0
const transactionTimeFeatureWasActivated =
!prevState.current.transactionTimeFeatureActive &&
transactionTimeFeatureActive
if (
transactionTimeFeatureActive &&
pendingTransactions.length > 0 &&
(loaded === false ||
transactionTimeFeatureWasActivated ||
pendingTransactionAdded)
) {
fetchBasicGasAndTimeEstimates().then(({ blockTime }) =>
fetchGasEstimates(blockTime),
)
}
prevState.current = {
loaded: true,
pendingTransactions,
transactionTimeFeatureActive,
}
}, [
fetchGasEstimates,
fetchBasicGasAndTimeEstimates,
transactionTimeFeatureActive,
pendingTransactions,
])
const viewMore = useCallback(
() => setLimit((prev) => prev + PAGE_INCREMENT),
[],

View File

@ -17,140 +17,21 @@ const {
setCustomGasTotal,
setCustomGasErrors,
resetCustomGasState,
fetchBasicGasAndTimeEstimates,
fetchBasicGasEstimates,
gasEstimatesLoadingStarted,
gasEstimatesLoadingFinished,
setPricesAndTimeEstimates,
fetchGasEstimates,
setApiEstimatesLastRetrieved,
} = GasDuck
const GasReducer = GasDuck.default
describe('Gas Duck', function () {
let tempFetch
let tempDateNow
const mockEthGasApiResponse = {
average: 20,
avgWait: 'mockAvgWait',
block_time: 'mockBlock_time',
blockNum: 'mockBlockNum',
fast: 30,
fastest: 40,
fastestWait: 'mockFastestWait',
fastWait: 'mockFastWait',
safeLow: 10,
safeLowWait: 'mockSafeLowWait',
speed: 'mockSpeed',
standard: 20,
const mockGasPriceApiResponse = {
SafeGasPrice: 10,
ProposeGasPrice: 20,
FastGasPrice: 30,
}
const mockPredictTableResponse = [
{
expectedTime: 400,
expectedWait: 40,
gasprice: 0.25,
somethingElse: 'foobar',
},
{
expectedTime: 200,
expectedWait: 20,
gasprice: 0.5,
somethingElse: 'foobar',
},
{
expectedTime: 100,
expectedWait: 10,
gasprice: 1,
somethingElse: 'foobar',
},
{
expectedTime: 75,
expectedWait: 7.5,
gasprice: 1.5,
somethingElse: 'foobar',
},
{ expectedTime: 50, expectedWait: 5, gasprice: 2, somethingElse: 'foobar' },
{
expectedTime: 35,
expectedWait: 4.5,
gasprice: 3,
somethingElse: 'foobar',
},
{
expectedTime: 34,
expectedWait: 4.4,
gasprice: 3.1,
somethingElse: 'foobar',
},
{
expectedTime: 25,
expectedWait: 4.2,
gasprice: 3.5,
somethingElse: 'foobar',
},
{ expectedTime: 20, expectedWait: 4, gasprice: 4, somethingElse: 'foobar' },
{
expectedTime: 19,
expectedWait: 3.9,
gasprice: 4.1,
somethingElse: 'foobar',
},
{ expectedTime: 15, expectedWait: 3, gasprice: 7, somethingElse: 'foobar' },
{
expectedTime: 14,
expectedWait: 2.9,
gasprice: 7.1,
somethingElse: 'foobar',
},
{
expectedTime: 12,
expectedWait: 2.5,
gasprice: 8,
somethingElse: 'foobar',
},
{
expectedTime: 10,
expectedWait: 2,
gasprice: 10,
somethingElse: 'foobar',
},
{
expectedTime: 9,
expectedWait: 1.9,
gasprice: 10.1,
somethingElse: 'foobar',
},
{ expectedTime: 5, expectedWait: 1, gasprice: 15, somethingElse: 'foobar' },
{
expectedTime: 4,
expectedWait: 0.9,
gasprice: 15.1,
somethingElse: 'foobar',
},
{
expectedTime: 2,
expectedWait: 0.8,
gasprice: 17,
somethingElse: 'foobar',
},
{
expectedTime: 1.1,
expectedWait: 0.6,
gasprice: 19.9,
somethingElse: 'foobar',
},
{
expectedTime: 1,
expectedWait: 0.5,
gasprice: 20,
somethingElse: 'foobar',
},
]
const fakeFetch = (url) =>
const fakeFetch = () =>
new Promise((resolve) => {
const dataToResolve = url.match(/ethgasAPI/u)
? mockEthGasApiResponse
: mockPredictTableResponse
const dataToResolve = mockGasPriceApiResponse
resolve({
json: () => Promise.resolve(dataToResolve),
})
@ -183,45 +64,23 @@ describe('Gas Duck', function () {
},
basicEstimates: {
average: null,
fastestWait: null,
fastWait: null,
fast: null,
safeLowWait: null,
blockNum: null,
avgWait: null,
blockTime: null,
speed: null,
fastest: null,
safeLow: null,
},
basicEstimateIsLoading: true,
errors: {},
gasEstimatesLoading: true,
priceAndTimeEstimates: [],
priceAndTimeEstimatesLastRetrieved: 0,
basicPriceAndTimeEstimatesLastRetrieved: 0,
basicPriceEstimatesLastRetrieved: 0,
}
const BASIC_GAS_ESTIMATE_LOADING_FINISHED =
'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_FINISHED'
const BASIC_GAS_ESTIMATE_LOADING_STARTED =
'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_STARTED'
const GAS_ESTIMATE_LOADING_FINISHED =
'metamask/gas/GAS_ESTIMATE_LOADING_FINISHED'
const GAS_ESTIMATE_LOADING_STARTED =
'metamask/gas/GAS_ESTIMATE_LOADING_STARTED'
const RESET_CUSTOM_GAS_STATE = 'metamask/gas/RESET_CUSTOM_GAS_STATE'
const SET_BASIC_GAS_ESTIMATE_DATA = 'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA'
const SET_CUSTOM_GAS_ERRORS = 'metamask/gas/SET_CUSTOM_GAS_ERRORS'
const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT'
const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE'
const SET_CUSTOM_GAS_TOTAL = 'metamask/gas/SET_CUSTOM_GAS_TOTAL'
const SET_PRICE_AND_TIME_ESTIMATES =
'metamask/gas/SET_PRICE_AND_TIME_ESTIMATES'
const SET_API_ESTIMATES_LAST_RETRIEVED =
'metamask/gas/SET_API_ESTIMATES_LAST_RETRIEVED'
const SET_BASIC_API_ESTIMATES_LAST_RETRIEVED =
'metamask/gas/SET_BASIC_API_ESTIMATES_LAST_RETRIEVED'
const SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED =
'metamask/gas/SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED'
@ -254,20 +113,6 @@ describe('Gas Duck', function () {
)
})
it('should set gasEstimatesLoading to true when receiving a GAS_ESTIMATE_LOADING_STARTED action', function () {
assert.deepEqual(
GasReducer(mockState, { type: GAS_ESTIMATE_LOADING_STARTED }),
{ gasEstimatesLoading: true, ...mockState },
)
})
it('should set gasEstimatesLoading to false when receiving a GAS_ESTIMATE_LOADING_FINISHED action', function () {
assert.deepEqual(
GasReducer(mockState, { type: GAS_ESTIMATE_LOADING_FINISHED }),
{ gasEstimatesLoading: false, ...mockState },
)
})
it('should set basicEstimates when receiving a SET_BASIC_GAS_ESTIMATE_DATA action', function () {
assert.deepEqual(
GasReducer(mockState, {
@ -278,16 +123,6 @@ describe('Gas Duck', function () {
)
})
it('should set priceAndTimeEstimates when receiving a SET_PRICE_AND_TIME_ESTIMATES action', function () {
assert.deepEqual(
GasReducer(mockState, {
type: SET_PRICE_AND_TIME_ESTIMATES,
value: { someProp: 'someData123' },
}),
{ priceAndTimeEstimates: { someProp: 'someData123' }, ...mockState },
)
})
it('should set customData.price when receiving a SET_CUSTOM_GAS_PRICE action', function () {
assert.deepEqual(
GasReducer(mockState, {
@ -318,29 +153,6 @@ describe('Gas Duck', function () {
)
})
it('should set priceAndTimeEstimatesLastRetrieved when receiving a SET_API_ESTIMATES_LAST_RETRIEVED action', function () {
assert.deepEqual(
GasReducer(mockState, {
type: SET_API_ESTIMATES_LAST_RETRIEVED,
value: 1500000000000,
}),
{ priceAndTimeEstimatesLastRetrieved: 1500000000000, ...mockState },
)
})
it('should set priceAndTimeEstimatesLastRetrieved when receiving a SET_BASIC_API_ESTIMATES_LAST_RETRIEVED action', function () {
assert.deepEqual(
GasReducer(mockState, {
type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED,
value: 1700000000000,
}),
{
basicPriceAndTimeEstimatesLastRetrieved: 1700000000000,
...mockState,
},
)
})
it('should set errors when receiving a SET_CUSTOM_GAS_ERRORS action', function () {
assert.deepEqual(
GasReducer(mockState, {
@ -388,8 +200,8 @@ describe('Gas Duck', function () {
assert.ok(
window.fetch
.getCall(0)
.args[0].startsWith('https://ethgasstation.info/json/ethgasAPI.json'),
'should fetch ETH Gas Station',
.args[0].startsWith('https://api.metaswap.codefi.network/gasPrices'),
'should fetch metaswap /gasPrices',
)
assert.deepEqual(mockDistpatch.getCall(1).args, [
{ type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 },
@ -398,12 +210,9 @@ describe('Gas Duck', function () {
{
type: SET_BASIC_GAS_ESTIMATE_DATA,
value: {
average: 2,
blockTime: 'mockBlock_time',
blockNum: 'mockBlockNum',
fast: 3,
fastest: 4,
safeLow: 1,
average: 20,
fast: 30,
safeLow: 10,
},
},
])
@ -419,10 +228,7 @@ describe('Gas Duck', function () {
.returns(2000000 - 1) // one second ago from "now"
fakeStorage.getStorageItem.withArgs('BASIC_PRICE_ESTIMATES').returns({
average: 25,
blockTime: 'mockBlock_time',
blockNum: 'mockBlockNum',
fast: 35,
fastest: 45,
safeLow: 15,
})
@ -438,10 +244,7 @@ describe('Gas Duck', function () {
type: SET_BASIC_GAS_ESTIMATE_DATA,
value: {
average: 25,
blockTime: 'mockBlock_time',
blockNum: 'mockBlockNum',
fast: 35,
fastest: 45,
safeLow: 15,
},
},
@ -466,8 +269,8 @@ describe('Gas Duck', function () {
assert.ok(
window.fetch
.getCall(0)
.args[0].startsWith('https://ethgasstation.info/json/ethgasAPI.json'),
'should fetch ETH Gas Station',
.args[0].startsWith('https://api.metaswap.codefi.network/gasPrices'),
'should fetch metaswap /gasPrices',
)
assert.deepEqual(mockDistpatch.getCall(1).args, [
{ type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 },
@ -476,12 +279,9 @@ describe('Gas Duck', function () {
{
type: SET_BASIC_GAS_ESTIMATE_DATA,
value: {
average: 2,
blockTime: 'mockBlock_time',
blockNum: 'mockBlockNum',
fast: 3,
fastest: 4,
safeLow: 1,
safeLow: 10,
average: 20,
fast: 30,
},
},
])
@ -491,280 +291,6 @@ describe('Gas Duck', function () {
})
})
describe('fetchBasicGasAndTimeEstimates', function () {
it('should call fetch with the expected params', async function () {
const mockDistpatch = sinon.spy()
await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({
gas: {
...initState,
basicPriceAndTimeEstimatesLastRetrieved: 1000000,
},
metamask: { provider: { type: 'ropsten' } },
}))
assert.deepEqual(mockDistpatch.getCall(0).args, [
{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED },
])
assert.ok(
window.fetch
.getCall(0)
.args[0].startsWith('https://ethgasstation.info/json/ethgasAPI.json'),
'should fetch ETH Gas Station',
)
assert.deepEqual(mockDistpatch.getCall(1).args, [
{ type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED, value: 2000000 },
])
assert.deepEqual(mockDistpatch.getCall(2).args, [
{
type: SET_BASIC_GAS_ESTIMATE_DATA,
value: {
average: 2,
avgWait: 'mockAvgWait',
blockTime: 'mockBlock_time',
blockNum: 'mockBlockNum',
fast: 3,
fastest: 4,
fastestWait: 'mockFastestWait',
fastWait: 'mockFastWait',
safeLow: 1,
safeLowWait: 'mockSafeLowWait',
speed: 'mockSpeed',
},
},
])
assert.deepEqual(mockDistpatch.getCall(3).args, [
{ type: BASIC_GAS_ESTIMATE_LOADING_FINISHED },
])
})
it('should fetch recently retrieved estimates from storage', async function () {
const mockDistpatch = sinon.spy()
fakeStorage.getStorageItem
.withArgs('BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED')
.returns(2000000 - 1) // one second ago from "now"
fakeStorage.getStorageItem
.withArgs('BASIC_GAS_AND_TIME_API_ESTIMATES')
.returns({
average: 5,
avgWait: 'mockAvgWait',
blockTime: 'mockBlock_time',
blockNum: 'mockBlockNum',
fast: 6,
fastest: 7,
fastestWait: 'mockFastestWait',
fastWait: 'mockFastWait',
safeLow: 1,
safeLowWait: 'mockSafeLowWait',
speed: 'mockSpeed',
})
await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({
gas: {
...initState,
},
metamask: { provider: { type: 'ropsten' } },
}))
assert.deepEqual(mockDistpatch.getCall(0).args, [
{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED },
])
assert.ok(window.fetch.notCalled)
assert.deepEqual(mockDistpatch.getCall(1).args, [
{
type: SET_BASIC_GAS_ESTIMATE_DATA,
value: {
average: 5,
avgWait: 'mockAvgWait',
blockTime: 'mockBlock_time',
blockNum: 'mockBlockNum',
fast: 6,
fastest: 7,
fastestWait: 'mockFastestWait',
fastWait: 'mockFastWait',
safeLow: 1,
safeLowWait: 'mockSafeLowWait',
speed: 'mockSpeed',
},
},
])
assert.deepEqual(mockDistpatch.getCall(2).args, [
{ type: BASIC_GAS_ESTIMATE_LOADING_FINISHED },
])
})
it('should fallback to network if retrieving estimates from storage fails', async function () {
const mockDistpatch = sinon.spy()
fakeStorage.getStorageItem
.withArgs('BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED')
.returns(2000000 - 1) // one second ago from "now"
await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({
gas: {
...initState,
},
metamask: { provider: { type: 'ropsten' } },
}))
assert.deepEqual(mockDistpatch.getCall(0).args, [
{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED },
])
assert.ok(
window.fetch
.getCall(0)
.args[0].startsWith('https://ethgasstation.info/json/ethgasAPI.json'),
'should fetch ETH Gas Station',
)
assert.deepEqual(mockDistpatch.getCall(1).args, [
{ type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED, value: 2000000 },
])
assert.deepEqual(mockDistpatch.getCall(2).args, [
{
type: SET_BASIC_GAS_ESTIMATE_DATA,
value: {
average: 2,
avgWait: 'mockAvgWait',
blockTime: 'mockBlock_time',
blockNum: 'mockBlockNum',
fast: 3,
fastest: 4,
fastestWait: 'mockFastestWait',
fastWait: 'mockFastWait',
safeLow: 1,
safeLowWait: 'mockSafeLowWait',
speed: 'mockSpeed',
},
},
])
assert.deepEqual(mockDistpatch.getCall(3).args, [
{ type: BASIC_GAS_ESTIMATE_LOADING_FINISHED },
])
})
})
describe('fetchGasEstimates', function () {
it('should call fetch with the expected params', async function () {
const mockDistpatch = sinon.spy()
await fetchGasEstimates(5)(mockDistpatch, () => ({
gas: {
...initState,
priceAndTimeEstimatesLastRetrieved: 1000000,
},
metamask: { provider: { type: 'ropsten' } },
}))
assert.deepEqual(mockDistpatch.getCall(0).args, [
{ type: GAS_ESTIMATE_LOADING_STARTED },
])
assert.ok(
window.fetch
.getCall(0)
.args[0].startsWith(
'https://ethgasstation.info/json/predictTable.json',
),
'should fetch ETH Gas Station',
)
assert.deepEqual(mockDistpatch.getCall(1).args, [
{ type: SET_API_ESTIMATES_LAST_RETRIEVED, value: 2000000 },
])
const {
type: thirdDispatchCallType,
value: priceAndTimeEstimateResult,
} = mockDistpatch.getCall(2).args[0]
assert.equal(thirdDispatchCallType, SET_PRICE_AND_TIME_ESTIMATES)
assert(
priceAndTimeEstimateResult.length <
mockPredictTableResponse.length * 3 - 2,
)
assert(!priceAndTimeEstimateResult.find((d) => d.expectedTime > 100))
assert(
!priceAndTimeEstimateResult.find(
(d, _, a) => a[a + 1] && d.expectedTime > a[a + 1].expectedTime,
),
)
assert(
!priceAndTimeEstimateResult.find(
(d, _, a) => a[a + 1] && d.gasprice > a[a + 1].gasprice,
),
)
assert.deepEqual(mockDistpatch.getCall(3).args, [
{ type: GAS_ESTIMATE_LOADING_FINISHED },
])
})
it('should not call fetch if the estimates were retrieved < 75000 ms ago', async function () {
const mockDistpatch = sinon.spy()
await fetchGasEstimates(5)(mockDistpatch, () => ({
gas: {
...initState,
priceAndTimeEstimatesLastRetrieved: Date.now(),
priceAndTimeEstimates: [
{
expectedTime: '10',
expectedWait: 2,
gasprice: 50,
},
],
},
metamask: { provider: { type: 'ropsten' } },
}))
assert.deepEqual(mockDistpatch.getCall(0).args, [
{ type: GAS_ESTIMATE_LOADING_STARTED },
])
assert.equal(window.fetch.callCount, 0)
assert.deepEqual(mockDistpatch.getCall(1).args, [
{
type: SET_PRICE_AND_TIME_ESTIMATES,
value: [
{
expectedTime: '10',
expectedWait: 2,
gasprice: 50,
},
],
},
])
assert.deepEqual(mockDistpatch.getCall(2).args, [
{ type: GAS_ESTIMATE_LOADING_FINISHED },
])
})
})
describe('gasEstimatesLoadingStarted', function () {
it('should create the correct action', function () {
assert.deepEqual(gasEstimatesLoadingStarted(), {
type: GAS_ESTIMATE_LOADING_STARTED,
})
})
})
describe('gasEstimatesLoadingFinished', function () {
it('should create the correct action', function () {
assert.deepEqual(gasEstimatesLoadingFinished(), {
type: GAS_ESTIMATE_LOADING_FINISHED,
})
})
})
describe('setPricesAndTimeEstimates', function () {
it('should create the correct action', function () {
assert.deepEqual(
setPricesAndTimeEstimates('mockPricesAndTimeEstimates'),
{
type: SET_PRICE_AND_TIME_ESTIMATES,
value: 'mockPricesAndTimeEstimates',
},
)
})
})
describe('setBasicGasEstimateData', function () {
it('should create the correct action', function () {
assert.deepEqual(setBasicGasEstimateData('mockBasicEstimatData'), {
@ -810,15 +336,6 @@ describe('Gas Duck', function () {
})
})
describe('setApiEstimatesLastRetrieved', function () {
it('should create the correct action', function () {
assert.deepEqual(setApiEstimatesLastRetrieved(1234), {
type: SET_API_ESTIMATES_LAST_RETRIEVED,
value: 1234,
})
})
})
describe('resetCustomGasState', function () {
it('should create the correct action', function () {
assert.deepEqual(resetCustomGasState(), { type: RESET_CUSTOM_GAS_STATE })

View File

@ -1,18 +1,14 @@
import { uniqBy, cloneDeep, flatten } from 'lodash'
import { cloneDeep } from 'lodash'
import BigNumber from 'bignumber.js'
import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers'
import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util'
import { isEthereumNetwork } from '../../selectors'
// Actions
const BASIC_GAS_ESTIMATE_LOADING_FINISHED =
'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_FINISHED'
const BASIC_GAS_ESTIMATE_LOADING_STARTED =
'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_STARTED'
const GAS_ESTIMATE_LOADING_FINISHED =
'metamask/gas/GAS_ESTIMATE_LOADING_FINISHED'
const GAS_ESTIMATE_LOADING_STARTED = 'metamask/gas/GAS_ESTIMATE_LOADING_STARTED'
const RESET_CUSTOM_GAS_STATE = 'metamask/gas/RESET_CUSTOM_GAS_STATE'
const RESET_CUSTOM_DATA = 'metamask/gas/RESET_CUSTOM_DATA'
const SET_BASIC_GAS_ESTIMATE_DATA = 'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA'
@ -20,11 +16,6 @@ const SET_CUSTOM_GAS_ERRORS = 'metamask/gas/SET_CUSTOM_GAS_ERRORS'
const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT'
const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE'
const SET_CUSTOM_GAS_TOTAL = 'metamask/gas/SET_CUSTOM_GAS_TOTAL'
const SET_PRICE_AND_TIME_ESTIMATES = 'metamask/gas/SET_PRICE_AND_TIME_ESTIMATES'
const SET_API_ESTIMATES_LAST_RETRIEVED =
'metamask/gas/SET_API_ESTIMATES_LAST_RETRIEVED'
const SET_BASIC_API_ESTIMATES_LAST_RETRIEVED =
'metamask/gas/SET_BASIC_API_ESTIMATES_LAST_RETRIEVED'
const SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED =
'metamask/gas/SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED'
@ -34,23 +25,11 @@ const initState = {
limit: null,
},
basicEstimates: {
average: null,
fastestWait: null,
fastWait: null,
fast: null,
safeLowWait: null,
blockNum: null,
avgWait: null,
blockTime: null,
speed: null,
fastest: null,
safeLow: null,
average: null,
fast: null,
},
basicEstimateIsLoading: true,
gasEstimatesLoading: true,
priceAndTimeEstimates: [],
priceAndTimeEstimatesLastRetrieved: 0,
basicPriceAndTimeEstimatesLastRetrieved: 0,
basicPriceEstimatesLastRetrieved: 0,
errors: {},
}
@ -68,16 +47,6 @@ export default function reducer(state = initState, action) {
...state,
basicEstimateIsLoading: false,
}
case GAS_ESTIMATE_LOADING_STARTED:
return {
...state,
gasEstimatesLoading: true,
}
case GAS_ESTIMATE_LOADING_FINISHED:
return {
...state,
gasEstimatesLoading: false,
}
case SET_BASIC_GAS_ESTIMATE_DATA:
return {
...state,
@ -107,11 +76,6 @@ export default function reducer(state = initState, action) {
total: action.value,
},
}
case SET_PRICE_AND_TIME_ESTIMATES:
return {
...state,
priceAndTimeEstimates: action.value,
}
case SET_CUSTOM_GAS_ERRORS:
return {
...state,
@ -120,16 +84,6 @@ export default function reducer(state = initState, action) {
...action.value,
},
}
case SET_API_ESTIMATES_LAST_RETRIEVED:
return {
...state,
priceAndTimeEstimatesLastRetrieved: action.value,
}
case SET_BASIC_API_ESTIMATES_LAST_RETRIEVED:
return {
...state,
basicPriceAndTimeEstimatesLastRetrieved: action.value,
}
case SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED:
return {
...state,
@ -160,41 +114,11 @@ export function basicGasEstimatesLoadingFinished() {
}
}
export function gasEstimatesLoadingStarted() {
return {
type: GAS_ESTIMATE_LOADING_STARTED,
}
}
export function gasEstimatesLoadingFinished() {
return {
type: GAS_ESTIMATE_LOADING_FINISHED,
}
}
async function queryEthGasStationBasic() {
const apiKey = process.env.ETH_GAS_STATION_API_KEY
? `?api-key=${process.env.ETH_GAS_STATION_API_KEY}`
: ''
const url = `https://ethgasstation.info/json/ethgasAPI.json${apiKey}`
async function basicGasPriceQuery() {
const url = `https://api.metaswap.codefi.network/gasPrices`
return await window.fetch(url, {
headers: {},
referrer: 'http://ethgasstation.info/json/',
referrerPolicy: 'no-referrer-when-downgrade',
body: null,
method: 'GET',
mode: 'cors',
})
}
async function queryEthGasStationPredictionTable() {
const apiKey = process.env.ETH_GAS_STATION_API_KEY
? `?api-key=${process.env.ETH_GAS_STATION_API_KEY}`
: ''
const url = `https://ethgasstation.info/json/predictTable.json${apiKey}`
return await window.fetch(url, {
headers: {},
referrer: 'http://ethgasstation.info/json/',
referrer: 'https://api.metaswap.codefi.network/gasPrices',
referrerPolicy: 'no-referrer-when-downgrade',
body: null,
method: 'GET',
@ -229,31 +153,20 @@ export function fetchBasicGasEstimates() {
}
async function fetchExternalBasicGasEstimates(dispatch) {
const response = await queryEthGasStationBasic()
const response = await basicGasPriceQuery()
const {
safeLow: safeLowTimes10,
average: averageTimes10,
fast: fastTimes10,
fastest: fastestTimes10,
block_time: blockTime,
blockNum,
} = await response.json()
const { SafeGasPrice, ProposeGasPrice, FastGasPrice } = await response.json()
const [average, fast, fastest, safeLow] = [
averageTimes10,
fastTimes10,
fastestTimes10,
safeLowTimes10,
].map((price) => new BigNumber(price).div(10).toNumber())
const [safeLow, average, fast] = [
SafeGasPrice,
ProposeGasPrice,
FastGasPrice,
].map((price) => new BigNumber(price, 10).toNumber())
const basicEstimates = {
safeLow,
average,
fast,
fastest,
blockTime,
blockNum,
}
const timeRetrieved = Date.now()
@ -266,262 +179,6 @@ async function fetchExternalBasicGasEstimates(dispatch) {
return basicEstimates
}
export function fetchBasicGasAndTimeEstimates() {
return async (dispatch, getState) => {
const { basicPriceAndTimeEstimatesLastRetrieved } = getState().gas
const timeLastRetrieved =
basicPriceAndTimeEstimatesLastRetrieved ||
(await getStorageItem(
'BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED',
)) ||
0
dispatch(basicGasEstimatesLoadingStarted())
let basicEstimates
if (Date.now() - timeLastRetrieved > 75000) {
basicEstimates = await fetchExternalBasicGasAndTimeEstimates(dispatch)
} else {
const cachedBasicEstimates = await getStorageItem(
'BASIC_GAS_AND_TIME_API_ESTIMATES',
)
basicEstimates =
cachedBasicEstimates ||
(await fetchExternalBasicGasAndTimeEstimates(dispatch))
}
dispatch(setBasicGasEstimateData(basicEstimates))
dispatch(basicGasEstimatesLoadingFinished())
return basicEstimates
}
}
async function fetchExternalBasicGasAndTimeEstimates(dispatch) {
const response = await queryEthGasStationBasic()
const {
average: averageTimes10,
avgWait,
block_time: blockTime,
blockNum,
fast: fastTimes10,
fastest: fastestTimes10,
fastestWait,
fastWait,
safeLow: safeLowTimes10,
safeLowWait,
speed,
} = await response.json()
const [average, fast, fastest, safeLow] = [
averageTimes10,
fastTimes10,
fastestTimes10,
safeLowTimes10,
].map((price) => new BigNumber(price).div(10).toNumber())
const basicEstimates = {
average,
avgWait,
blockTime,
blockNum,
fast,
fastest,
fastestWait,
fastWait,
safeLow,
safeLowWait,
speed,
}
const timeRetrieved = Date.now()
await Promise.all([
setStorageItem('BASIC_GAS_AND_TIME_API_ESTIMATES', basicEstimates),
setStorageItem(
'BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED',
timeRetrieved,
),
])
dispatch(setBasicApiEstimatesLastRetrieved(timeRetrieved))
return basicEstimates
}
function extrapolateY({ higherY, lowerY, higherX, lowerX, xForExtrapolation }) {
/* eslint-disable no-param-reassign */
higherY = new BigNumber(higherY, 10)
lowerY = new BigNumber(lowerY, 10)
higherX = new BigNumber(higherX, 10)
lowerX = new BigNumber(lowerX, 10)
xForExtrapolation = new BigNumber(xForExtrapolation, 10)
/* eslint-enable no-param-reassign */
const slope = higherY.minus(lowerY).div(higherX.minus(lowerX))
const newTimeEstimate = slope
.times(higherX.minus(xForExtrapolation))
.minus(higherY)
.negated()
return Number(newTimeEstimate.toPrecision(10))
}
function getRandomArbitrary(minStr, maxStr) {
const min = new BigNumber(minStr, 10)
const max = new BigNumber(maxStr, 10)
const random = new BigNumber(String(Math.random()), 10)
return new BigNumber(random.times(max.minus(min)).plus(min)).toPrecision(10)
}
function calcMedian(list) {
const medianPos =
(Math.floor(list.length / 2) + Math.ceil(list.length / 2)) / 2
return medianPos === Math.floor(medianPos)
? (list[medianPos - 1] + list[medianPos]) / 2
: list[Math.floor(medianPos)]
}
function quartiles(data) {
const lowerHalf = data.slice(0, Math.floor(data.length / 2))
const upperHalf = data.slice(
Math.floor(data.length / 2) + (data.length % 2 === 0 ? 0 : 1),
)
const median = calcMedian(data)
const lowerQuartile = calcMedian(lowerHalf)
const upperQuartile = calcMedian(upperHalf)
return {
median,
lowerQuartile,
upperQuartile,
}
}
function inliersByIQR(data, prop) {
const { lowerQuartile, upperQuartile } = quartiles(
data.map((d) => (prop ? d[prop] : d)),
)
const IQR = upperQuartile - lowerQuartile
const lowerBound = lowerQuartile - 1.5 * IQR
const upperBound = upperQuartile + 1.5 * IQR
return data.filter((d) => {
const value = prop ? d[prop] : d
return value >= lowerBound && value <= upperBound
})
}
export function fetchGasEstimates(blockTime) {
return async (dispatch, getState) => {
const state = getState()
if (!isEthereumNetwork(state)) {
return
}
const {
priceAndTimeEstimatesLastRetrieved,
priceAndTimeEstimates,
} = state.gas
const timeLastRetrieved =
priceAndTimeEstimatesLastRetrieved ||
(await getStorageItem('GAS_API_ESTIMATES_LAST_RETRIEVED')) ||
0
dispatch(gasEstimatesLoadingStarted())
const shouldGetFreshGasQuote = Date.now() - timeLastRetrieved > 75000
let estimates
if (shouldGetFreshGasQuote) {
const response = await queryEthGasStationPredictionTable()
const tableJson = await response.json()
const estimatedPricesAndTimes = tableJson.map(
({ expectedTime, expectedWait, gasprice }) => ({
expectedTime,
expectedWait,
gasprice,
}),
)
const estimatedTimeWithUniquePrices = uniqBy(
estimatedPricesAndTimes,
({ expectedTime }) => expectedTime,
)
const withSupplementalTimeEstimates = flatten(
estimatedTimeWithUniquePrices.map(
({ expectedWait, gasprice }, i, arr) => {
const next = arr[i + 1]
if (!next) {
return [{ expectedWait, gasprice }]
}
const supplementalPrice = getRandomArbitrary(
gasprice,
next.gasprice,
)
const supplementalTime = extrapolateY({
higherY: next.expectedWait,
lowerY: expectedWait,
higherX: next.gasprice,
lowerX: gasprice,
xForExtrapolation: supplementalPrice,
})
const supplementalPrice2 = getRandomArbitrary(
supplementalPrice,
next.gasprice,
)
const supplementalTime2 = extrapolateY({
higherY: next.expectedWait,
lowerY: supplementalTime,
higherX: next.gasprice,
lowerX: supplementalPrice,
xForExtrapolation: supplementalPrice2,
})
return [
{ expectedWait, gasprice },
{
expectedWait: supplementalTime,
gasprice: supplementalPrice,
},
{
expectedWait: supplementalTime2,
gasprice: supplementalPrice2,
},
]
},
),
)
const withOutliersRemoved = inliersByIQR(
withSupplementalTimeEstimates.slice(0).reverse(),
'expectedWait',
).reverse()
const timeMappedToSeconds = withOutliersRemoved.map(
({ expectedWait, gasprice }) => {
const expectedTime = new BigNumber(expectedWait)
.times(Number(blockTime), 10)
.toNumber()
return {
expectedTime,
gasprice: new BigNumber(gasprice, 10).toNumber(),
}
},
)
const timeRetrieved = Date.now()
dispatch(setApiEstimatesLastRetrieved(timeRetrieved))
await Promise.all([
setStorageItem('GAS_API_ESTIMATES_LAST_RETRIEVED', timeRetrieved),
setStorageItem('GAS_API_ESTIMATES', timeMappedToSeconds),
])
estimates = timeMappedToSeconds
} else if (priceAndTimeEstimates.length) {
estimates = priceAndTimeEstimates
} else {
estimates = await getStorageItem('GAS_API_ESTIMATES')
}
dispatch(setPricesAndTimeEstimates(estimates))
dispatch(gasEstimatesLoadingFinished())
}
}
export function setCustomGasPriceForRetry(newPrice) {
return async (dispatch) => {
if (newPrice === '0x0') {
@ -540,13 +197,6 @@ export function setBasicGasEstimateData(basicGasEstimateData) {
}
}
export function setPricesAndTimeEstimates(estimatedPricesAndTimes) {
return {
type: SET_PRICE_AND_TIME_ESTIMATES,
value: estimatedPricesAndTimes,
}
}
export function setCustomGasPrice(newPrice) {
return {
type: SET_CUSTOM_GAS_PRICE,
@ -575,20 +225,6 @@ export function setCustomGasErrors(newErrors) {
}
}
export function setApiEstimatesLastRetrieved(retrievalTime) {
return {
type: SET_API_ESTIMATES_LAST_RETRIEVED,
value: retrievalTime,
}
}
export function setBasicApiEstimatesLastRetrieved(retrievalTime) {
return {
type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED,
value: retrievalTime,
}
}
export function setBasicPriceEstimatesLastRetrieved(retrievalTime) {
return {
type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED,

View File

@ -1,125 +0,0 @@
import BigNumber from 'bignumber.js'
export function newBigSigDig(n) {
return new BigNumber(new BigNumber(String(n)).toPrecision(15))
}
const createOp = (a, b, op) => newBigSigDig(a)[op](newBigSigDig(b))
export function bigNumMinus(a = 0, b = 0) {
return createOp(a, b, 'minus')
}
export function bigNumDiv(a = 0, b = 1) {
return createOp(a, b, 'div')
}
export function extrapolateY({
higherY = 0,
lowerY = 0,
higherX = 0,
lowerX = 0,
xForExtrapolation = 0,
}) {
const slope = bigNumMinus(higherY, lowerY).div(bigNumMinus(higherX, lowerX))
const newTimeEstimate = slope
.times(bigNumMinus(higherX, xForExtrapolation))
.minus(newBigSigDig(higherY))
.negated()
return newTimeEstimate.toNumber()
}
export function getAdjacentGasPrices({ gasPrices, priceToPosition }) {
const closestLowerValueIndex = gasPrices.findIndex(
(e, i, a) => e <= priceToPosition && a[i + 1] >= priceToPosition,
)
const closestHigherValueIndex = gasPrices.findIndex(
(e) => e > priceToPosition,
)
return {
closestLowerValueIndex,
closestHigherValueIndex,
closestHigherValue: gasPrices[closestHigherValueIndex],
closestLowerValue: gasPrices[closestLowerValueIndex],
}
}
export function formatTimeEstimate(totalSeconds, greaterThanMax, lessThanMin) {
const minutes = Math.floor(totalSeconds / 60)
const seconds = Math.floor(totalSeconds % 60)
if (!minutes && !seconds) {
return '...'
}
let symbol = '~'
if (greaterThanMax) {
symbol = '< '
} else if (lessThanMin) {
symbol = '> '
}
const formattedMin = `${minutes ? `${minutes} min` : ''}`
const formattedSec = `${seconds ? `${seconds} sec` : ''}`
const formattedCombined =
formattedMin && formattedSec
? `${symbol}${formattedMin} ${formattedSec}`
: symbol + (formattedMin || formattedSec)
return formattedCombined
}
export function getRawTimeEstimateData(
currentGasPrice,
gasPrices,
estimatedTimes,
) {
const minGasPrice = gasPrices[0]
const maxGasPrice = gasPrices[gasPrices.length - 1]
let priceForEstimation = currentGasPrice
if (currentGasPrice < minGasPrice) {
priceForEstimation = minGasPrice
} else if (currentGasPrice > maxGasPrice) {
priceForEstimation = maxGasPrice
}
const {
closestLowerValueIndex,
closestHigherValueIndex,
closestHigherValue,
closestLowerValue,
} = getAdjacentGasPrices({ gasPrices, priceToPosition: priceForEstimation })
const newTimeEstimate = extrapolateY({
higherY: estimatedTimes[closestHigherValueIndex],
lowerY: estimatedTimes[closestLowerValueIndex],
higherX: closestHigherValue,
lowerX: closestLowerValue,
xForExtrapolation: priceForEstimation,
})
return {
newTimeEstimate,
minGasPrice,
maxGasPrice,
}
}
export function getRenderableTimeEstimate(
currentGasPrice,
gasPrices,
estimatedTimes,
) {
const { newTimeEstimate, minGasPrice, maxGasPrice } = getRawTimeEstimateData(
currentGasPrice,
gasPrices,
estimatedTimes,
)
return formatTimeEstimate(
newTimeEstimate,
currentGasPrice > maxGasPrice,
currentGasPrice < minGasPrice,
)
}

View File

@ -52,8 +52,6 @@ describe('useRetryTransaction', function () {
)
const retry = result.current
await retry(event)
const calls = dispatch.getCalls()
assert.equal(calls.length, 5)
assert.equal(
dispatch.calledWith(
showSidebar({

View File

@ -2,8 +2,7 @@ import { useDispatch } from 'react-redux'
import { useCallback } from 'react'
import { showSidebar } from '../store/actions'
import {
fetchBasicGasAndTimeEstimates,
fetchGasEstimates,
fetchBasicGasEstimates,
setCustomGasPriceForRetry,
setCustomGasLimit,
} from '../ducks/gas/gas.duck'
@ -34,8 +33,7 @@ export function useRetryTransaction(transactionGroup) {
event.stopPropagation()
trackMetricsEvent()
const basicEstimates = await dispatch(fetchBasicGasAndTimeEstimates)
await dispatch(fetchGasEstimates(basicEstimates.blockTime))
await dispatch(fetchBasicGasEstimates)
const transaction = initialTransaction
const increasedGasPrice = increaseLastGasPrice(gasPrice)
await dispatch(

View File

@ -1,126 +0,0 @@
import { useSelector } from 'react-redux'
import { useRef, useEffect, useState, useMemo } from 'react'
import { isEqual } from 'lodash'
import { captureException } from '@sentry/browser'
import { hexWEIToDecGWEI } from '../helpers/utils/conversions.util'
import {
getEstimatedGasPrices,
getEstimatedGasTimes,
getFeatureFlags,
getIsMainnet,
} from '../selectors'
import { getRawTimeEstimateData } from '../helpers/utils/gas-time-estimates.util'
import { getCurrentLocale } from '../ducks/metamask/metamask'
/**
* Calculate the number of minutes remaining until the transaction completes.
* @param {number} initialTimeEstimate - timestamp for the projected completion time
* @param {number} submittedTime - timestamp of when the tx was submitted
* @return {number} minutes remaining
*/
function calcTransactionTimeRemaining(initialTimeEstimate, submittedTime) {
const currentTime = new Date().getTime()
const timeElapsedSinceSubmission = (currentTime - submittedTime) / 1000
const timeRemainingOnEstimate =
initialTimeEstimate - timeElapsedSinceSubmission
const renderingTimeRemainingEstimate = Math.round(
timeRemainingOnEstimate / 60,
)
return renderingTimeRemainingEstimate
}
/**
* returns a string representing the number of minutes predicted for the transaction to be
* completed. Only returns this prediction if the transaction is the earliest pending
* transaction, and the feature flag for showing timing is enabled.
* @param {bool} isSubmitted - is the transaction currently in the 'submitted' state
* @param {bool} isEarliestNonce - is this transaction the earliest nonce in list
* @param {number} submittedTime - the timestamp for when the transaction was submitted
* @param {number} currentGasPrice - gas price to use for calculation of time
* @param {boolean} dontFormat - Whether the result should be be formatted, or just a number of minutes
* @returns {string | undefined} i18n formatted string if applicable
*/
export function useTransactionTimeRemaining(
isSubmitted,
isEarliestNonce,
submittedTime,
currentGasPrice,
forceAllow,
dontFormat,
) {
// the following two selectors return the result of mapping over an array, as such they
// will always be new objects and trigger effects. To avoid this, we use isEqual as the
// equalityFn to only update when the data is new.
const gasPrices = useSelector(getEstimatedGasPrices, isEqual)
const estimatedTimes = useSelector(getEstimatedGasTimes, isEqual)
const locale = useSelector(getCurrentLocale)
const isMainNet = useSelector(getIsMainnet)
const interval = useRef()
const [timeRemaining, setTimeRemaining] = useState(null)
const featureFlags = useSelector(getFeatureFlags)
const transactionTimeFeatureActive = featureFlags?.transactionTime
const rtf = new Intl.RelativeTimeFormat(locale.replace('_', '-'), {
numeric: 'auto',
style: 'narrow',
})
// Memoize this value so it can be used as a dependency in the effect below
const initialTimeEstimate = useMemo(() => {
const customGasPrice = Number(hexWEIToDecGWEI(currentGasPrice))
try {
const { newTimeEstimate } = getRawTimeEstimateData(
customGasPrice,
gasPrices,
estimatedTimes,
)
return newTimeEstimate
} catch (error) {
captureException(error)
return NaN
}
}, [currentGasPrice, gasPrices, estimatedTimes])
useEffect(() => {
if (
isMainNet &&
(transactionTimeFeatureActive || forceAllow) &&
isSubmitted &&
isEarliestNonce &&
!isNaN(initialTimeEstimate)
) {
clearInterval(interval.current)
setTimeRemaining(
calcTransactionTimeRemaining(initialTimeEstimate, submittedTime),
)
interval.current = setInterval(() => {
setTimeRemaining(
calcTransactionTimeRemaining(initialTimeEstimate, submittedTime),
)
}, 10000)
return () => clearInterval(interval.current)
}
return undefined
}, [
isMainNet,
transactionTimeFeatureActive,
isEarliestNonce,
submittedTime,
initialTimeEstimate,
forceAllow,
isSubmitted,
])
// there are numerous checks to determine if time should be displayed.
// if any of the following are true, the timeRemaining will be null
// User is currently not on the mainnet
// User does not have the transactionTime feature flag enabled
// The transaction is not pending, or isn't the earliest nonce
if (timeRemaining && dontFormat) {
return timeRemaining
} else if (timeRemaining) {
return rtf.format(timeRemaining, 'minute')
}
return undefined
}

View File

@ -37,7 +37,7 @@ export default class ConfirmTransaction extends Component {
send: PropTypes.object,
setTransactionToConfirm: PropTypes.func,
clearConfirmTransaction: PropTypes.func,
fetchBasicGasAndTimeEstimates: PropTypes.func,
fetchBasicGasEstimates: PropTypes.func,
mostRecentOverviewPage: PropTypes.string.isRequired,
transaction: PropTypes.object,
getContractMethodData: PropTypes.func,
@ -54,7 +54,7 @@ export default class ConfirmTransaction extends Component {
history,
mostRecentOverviewPage,
transaction: { txParams: { data, to } = {} } = {},
fetchBasicGasAndTimeEstimates,
fetchBasicGasEstimates,
getContractMethodData,
transactionId,
paramsTransactionId,
@ -67,7 +67,7 @@ export default class ConfirmTransaction extends Component {
return
}
fetchBasicGasAndTimeEstimates()
fetchBasicGasEstimates()
getContractMethodData(data)
if (isTokenMethodAction) {
getTokenParams(to)

View File

@ -6,7 +6,7 @@ import {
clearConfirmTransaction,
} from '../../ducks/confirm-transaction/confirm-transaction.duck'
import { isTokenMethodAction } from '../../helpers/utils/transactions.util'
import { fetchBasicGasAndTimeEstimates } from '../../ducks/gas/gas.duck'
import { fetchBasicGasEstimates } from '../../ducks/gas/gas.duck'
import { getContractMethodData, getTokenParams } from '../../store/actions'
import { unconfirmedTransactionsListSelector } from '../../selectors'
@ -48,8 +48,7 @@ const mapDispatchToProps = (dispatch) => {
dispatch(setTransactionToConfirm(transactionId))
},
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
fetchBasicGasAndTimeEstimates: () =>
dispatch(fetchBasicGasAndTimeEstimates()),
fetchBasicGasEstimates: () => dispatch(fetchBasicGasEstimates()),
getContractMethodData: (data) => dispatch(getContractMethodData(data)),
getTokenParams: (tokenAddress) => dispatch(getTokenParams(tokenAddress)),
}

View File

@ -24,8 +24,6 @@ export default class AdvancedTab extends PureComponent {
sendHexData: PropTypes.bool,
setAdvancedInlineGasFeatureFlag: PropTypes.func,
advancedInlineGas: PropTypes.bool,
setTransactionTimeFeatureFlag: PropTypes.func,
transactionTime: PropTypes.bool,
showFiatInTestnets: PropTypes.bool,
autoLockTimeLimit: PropTypes.number,
setAutoLockTimeLimit: PropTypes.func.isRequired,
@ -211,35 +209,6 @@ export default class AdvancedTab extends PureComponent {
)
}
renderTransactionTimeEstimates() {
const { t } = this.context
const { transactionTime, setTransactionTimeFeatureFlag } = this.props
return (
<div
className="settings-page__content-row"
data-testid="advanced-setting-transaction-time-inline"
>
<div className="settings-page__content-item">
<span>{t('transactionTime')}</span>
<div className="settings-page__content-description">
{t('showTransactionTimeDescription')}
</div>
</div>
<div className="settings-page__content-item">
<div className="settings-page__content-item-col">
<ToggleButton
value={transactionTime}
onToggle={(value) => setTransactionTimeFeatureFlag(!value)}
offLabel={t('off')}
onLabel={t('on')}
/>
</div>
</div>
</div>
)
}
renderShowConversionInTestnets() {
const { t } = this.context
const {
@ -503,7 +472,6 @@ export default class AdvancedTab extends PureComponent {
{this.renderMobileSync()}
{this.renderResetAccount()}
{this.renderAdvancedGasInputInline()}
{this.renderTransactionTimeEstimates()}
{this.renderHexDataOptIn()}
{this.renderShowConversionInTestnets()}
{this.renderUseNonceOptIn()}

View File

@ -21,7 +21,7 @@ export const mapStateToProps = (state) => {
metamask,
} = state
const {
featureFlags: { sendHexData, transactionTime, advancedInlineGas } = {},
featureFlags: { sendHexData, advancedInlineGas } = {},
threeBoxSyncingAllowed,
threeBoxDisabled,
useNonceField,
@ -33,7 +33,6 @@ export const mapStateToProps = (state) => {
warning,
sendHexData,
advancedInlineGas,
transactionTime,
showFiatInTestnets,
autoLockTimeLimit,
threeBoxSyncingAllowed,
@ -52,8 +51,6 @@ export const mapDispatchToProps = (dispatch) => {
dispatch(showModal({ name: 'CONFIRM_RESET_ACCOUNT' })),
setAdvancedInlineGasFeatureFlag: (shouldShow) =>
dispatch(setFeatureFlag('advancedInlineGas', shouldShow)),
setTransactionTimeFeatureFlag: (shouldShow) =>
dispatch(setFeatureFlag('transactionTime', shouldShow)),
setUseNonceField: (value) => dispatch(setUseNonceField(value)),
setShowFiatConversionOnTestnetsPreference: (value) => {
return dispatch(setShowFiatConversionOnTestnetsPreference(value))

View File

@ -24,7 +24,7 @@ describe('AdvancedTab Component', function () {
},
)
assert.equal(root.find('.settings-page__content-row').length, 11)
assert.equal(root.find('.settings-page__content-row').length, 10)
})
it('should update autoLockTimeLimit', function () {
@ -46,7 +46,7 @@ describe('AdvancedTab Component', function () {
},
)
const autoTimeout = root.find('.settings-page__content-row').at(8)
const autoTimeout = root.find('.settings-page__content-row').at(7)
const textField = autoTimeout.find(TextField)
textField.props().onChange({ target: { value: 1440 } })

View File

@ -1,8 +1,7 @@
import EventEmitter from 'events'
import React, { useContext, useRef, useState, useEffect } from 'react'
import React, { useContext, useRef, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import { useHistory } from 'react-router-dom'
import { I18nContext } from '../../../contexts/i18n'
import { useNewMetricEvent } from '../../../hooks/useMetricEvent'
@ -18,15 +17,9 @@ import {
prepareForRetryGetQuotes,
prepareToLeaveSwaps,
} from '../../../ducks/swaps/swaps'
import { useTransactionTimeRemaining } from '../../../hooks/useTransactionTimeRemaining'
import { usePrevious } from '../../../hooks/usePrevious'
import Mascot from '../../../components/ui/mascot'
import PulseLoader from '../../../components/ui/pulse-loader'
import {
getBlockExplorerUrlForTx,
getStatusKey,
} from '../../../helpers/utils/transactions.util'
import CountdownTimer from '../countdown-timer'
import { getBlockExplorerUrlForTx } from '../../../helpers/utils/transactions.util'
import {
QUOTES_EXPIRED_ERROR,
SWAP_FAILED_ERROR,
@ -38,7 +31,6 @@ import { ASSET_ROUTE, DEFAULT_ROUTE } from '../../../helpers/constants/routes'
import { getRenderableNetworkFeesForQuote } from '../swaps.util'
import SwapsFooter from '../swaps-footer'
import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction'
import SwapFailureIcon from './swap-failure-icon'
import SwapSuccessIcon from './swap-success-icon'
import QuotesTimeoutIcon from './quotes-timeout-icon'
@ -52,8 +44,6 @@ export default function AwaitingSwap({
tokensReceived,
rpcPrefs,
submittingSwap,
tradeTxData,
usedGasPrice,
inputValue,
maxSlippage,
}) {
@ -71,7 +61,6 @@ export default function AwaitingSwap({
const currentCurrency = useSelector(getCurrentCurrency)
const usdConversionRate = useSelector(getUSDConversionRate)
const [timeRemainingExpired, setTimeRemainingExpired] = useState(false)
const [trackedQuotesExpiredEvent, setTrackedQuotesExpiredEvent] = useState(
false,
)
@ -109,56 +98,6 @@ export default function AwaitingSwap({
const blockExplorerUrl =
txHash && getBlockExplorerUrlForTx(networkId, txHash, rpcPrefs)
const statusKey = tradeTxData && getStatusKey(tradeTxData)
const timeRemaining = useTransactionTimeRemaining(
statusKey === TRANSACTION_STATUSES.SUBMITTED,
true,
tradeTxData?.submittedTime,
usedGasPrice,
true,
true,
)
const previousTimeRemaining = usePrevious(timeRemaining)
const timeRemainingIsNumber =
typeof timeRemaining === 'number' && !isNaN(timeRemaining)
const previousTimeRemainingIsNumber =
typeof previousTimeRemaining === 'number' && !isNaN(previousTimeRemaining)
const estimatedTransactionWaitTime = timeRemaining * 1000 * 60
useEffect(() => {
if (
!timeRemainingIsNumber &&
previousTimeRemainingIsNumber &&
!timeRemainingExpired
) {
setTimeRemainingExpired(true)
}
}, [
timeRemainingIsNumber,
previousTimeRemainingIsNumber,
timeRemainingExpired,
])
let countdownText
if (
timeRemainingIsNumber &&
!timeRemainingExpired &&
tradeTxData?.submittedTime
) {
countdownText = (
<CountdownTimer
key="countdown-timer"
timeStarted={tradeTxData?.submittedTime}
timerBase={estimatedTransactionWaitTime}
timeOnly
/>
)
} else if (tradeTxData?.submittedTime) {
countdownText = t('swapsAlmostDone')
} else {
countdownText = t('swapEstimatedTimeCalculating')
}
let headerText
let statusImage
let descriptionText
@ -203,13 +142,6 @@ export default function AwaitingSwap({
submitText = t('tryAgain')
statusImage = <SwapFailureIcon />
} else if (!errorKey && !swapComplete) {
/**
* only show estimated time if the transaction has a submitted time, the swap has
* not yet completed and there isn't an error. If the swap has not completed and
* there is no error, but also has no submitted time (has not yet been published),
* then we apply the invisible class to the time estimate div. This creates consistent
* spacing before and after display of the time estimate.
*/
headerText = t('swapProcessing')
statusImage = <PulseLoader />
submitText = t('swapsViewInActivity')
@ -221,31 +153,12 @@ export default function AwaitingSwap({
{destinationTokenInfo.symbol}
</span>,
])
content = (
<>
<div
className={classnames('awaiting-swap__time-estimate', {
'awaiting-swap__time-estimate--invisible': !tradeTxData?.submittedTime,
})}
>
{t('swapEstimatedTimeFull', [
<span
className="awaiting-swap__time-estimate-text"
key="swapEstimatedTime-1"
>
{t('swapEstimatedTime')}
</span>,
countdownText,
])}
</div>
{blockExplorerUrl && (
content = blockExplorerUrl && (
<ViewOnEtherScanLink
txHash={txHash}
blockExplorerUrl={blockExplorerUrl}
isCustomBlockExplorerUrl={Boolean(rpcPrefs.blockExplorerUrl)}
/>
)}
</>
)
} else if (!errorKey && swapComplete) {
headerText = t('swapTransactionComplete')
@ -329,8 +242,6 @@ AwaitingSwap.propTypes = {
OFFLINE_FOR_MAINTENANCE,
]),
submittingSwap: PropTypes.bool,
tradeTxData: PropTypes.object,
usedGasPrice: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
inputValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
maxSlippage: PropTypes.number,
}

View File

@ -22,7 +22,6 @@ import {
getFetchingQuotes,
setBalanceError,
setTopAssets,
getUsedSwapsGasPrice,
getFetchParams,
setAggregatorMetadata,
getAggregatorMetadata,
@ -94,7 +93,6 @@ export default function Swap() {
const [maxSlippage, setMaxSlippage] = useState(fetchParams?.slippage || 2)
const routeState = useSelector(getBackgroundSwapRouteState)
const usedGasPrice = useSelector(getUsedSwapsGasPrice)
const selectedAccount = useSelector(getSelectedAccount)
const quotes = useSelector(getQuotes)
const txList = useSelector(currentNetworkTxListSelector)
@ -397,8 +395,6 @@ export default function Swap() {
networkId={networkId}
txHash={tradeTxData?.hash}
tokensReceived={tokensReceived}
tradeTxData={tradeTxData}
usedGasPrice={usedGasPrice}
submittingSwap={
routeState === 'awaiting' && !(approveTxId || tradeTxId)
}

View File

@ -1,7 +1,6 @@
import { addHexPrefix } from '../../../app/scripts/lib/util'
import {
conversionUtil,
multiplyCurrencies,
conversionGreaterThan,
} from '../helpers/utils/conversion-util'
import { formatCurrency } from '../helpers/utils/confirm-tx.util'
@ -34,22 +33,6 @@ export function getBasicGasEstimateLoadingStatus(state) {
return state.gas.basicEstimateIsLoading
}
export function getGasEstimatesLoadingStatus(state) {
return state.gas.gasEstimatesLoading
}
export function getPriceAndTimeEstimates(state) {
return state.gas.priceAndTimeEstimates
}
export function getEstimatedGasPrices(state) {
return getPriceAndTimeEstimates(state).map(({ gasprice }) => gasprice)
}
export function getEstimatedGasTimes(state) {
return getPriceAndTimeEstimates(state).map(({ expectedTime }) => expectedTime)
}
export function getAveragePriceEstimateInHexWEI(state) {
const averagePriceEstimate = state.gas.basicEstimates.average
return getGasPriceInHexWei(averagePriceEstimate || '0x0')
@ -106,10 +89,6 @@ export function isCustomPriceSafe(state) {
return customPriceSafe
}
export function getBasicGasEstimateBlockTime(state) {
return state.gas.basicEstimates.blockTime
}
export function basicPriceEstimateToETHTotal(
estimate,
gasLimit,
@ -151,44 +130,6 @@ export function getRenderableConvertedCurrencyFee(
return formatCurrency(feeInCurrency, convertedCurrency)
}
export function getTimeEstimateInSeconds(blockWaitEstimate) {
return multiplyCurrencies(blockWaitEstimate, 60, {
toNumericBase: 'dec',
multiplicandBase: 10,
multiplierBase: 10,
numberOfDecimals: 1,
})
}
export function formatTimeEstimate(totalSeconds, greaterThanMax, lessThanMin) {
const minutes = Math.floor(totalSeconds / 60)
const seconds = Math.floor(totalSeconds % 60)
if (!minutes && !seconds) {
return '...'
}
let symbol = '~'
if (greaterThanMax) {
symbol = '< '
} else if (lessThanMin) {
symbol = '> '
}
const formattedMin = `${minutes ? `${minutes} min` : ''}`
const formattedSec = `${seconds ? `${seconds} sec` : ''}`
const formattedCombined =
formattedMin && formattedSec
? `${symbol}${formattedMin} ${formattedSec}`
: symbol + [formattedMin, formattedSec].find((t) => t)
return formattedCombined
}
export function getRenderableTimeEstimate(blockWaitEstimate) {
return formatTimeEstimate(getTimeEstimateInSeconds(blockWaitEstimate))
}
export function priceEstimateToWei(priceEstimate) {
return conversionUtil(priceEstimate, {
fromNumericBase: 'hex',
@ -214,16 +155,7 @@ export function getRenderableGasButtonData(
conversionRate,
currentCurrency,
) {
const {
safeLow,
average,
fast,
safeLowWait,
avgWait,
fastWait,
fastest,
fastestWait,
} = estimates
const { safeLow, average, fast } = estimates
const slowEstimateData = {
gasEstimateType: GAS_ESTIMATE_TYPES.SLOW,
@ -236,7 +168,6 @@ export function getRenderableGasButtonData(
conversionRate,
)
: '',
timeEstimate: safeLowWait && getRenderableTimeEstimate(safeLowWait),
priceInHexWei: getGasPriceInHexWei(safeLow),
}
const averageEstimateData = {
@ -250,7 +181,6 @@ export function getRenderableGasButtonData(
conversionRate,
)
: '',
timeEstimate: avgWait && getRenderableTimeEstimate(avgWait),
priceInHexWei: getGasPriceInHexWei(average),
}
const fastEstimateData = {
@ -264,29 +194,13 @@ export function getRenderableGasButtonData(
conversionRate,
)
: '',
timeEstimate: fastWait && getRenderableTimeEstimate(fastWait),
priceInHexWei: getGasPriceInHexWei(fast),
}
const fastestEstimateData = {
gasEstimateType: GAS_ESTIMATE_TYPES.FASTEST,
feeInPrimaryCurrency: getRenderableEthFee(fastest, gasLimit),
feeInSecondaryCurrency: showFiat
? getRenderableConvertedCurrencyFee(
fastest,
gasLimit,
currentCurrency,
conversionRate,
)
: '',
timeEstimate: fastestWait && getRenderableTimeEstimate(fastestWait),
priceInHexWei: getGasPriceInHexWei(fastest),
}
return {
slowEstimateData,
averageEstimateData,
fastEstimateData,
fastestEstimateData,
}
}

View File

@ -284,13 +284,6 @@ export function getIsMainnet(state) {
return networkType === NETWORK_TYPES.MAINNET
}
export function isEthereumNetwork(state) {
const networkType = getNetworkIdentifier(state)
const { KOVAN, MAINNET, RINKEBY, ROPSTEN, GOERLI } = NETWORK_TYPES
return [KOVAN, MAINNET, RINKEBY, ROPSTEN, GOERLI].includes(networkType)
}
export function getPreferences({ metamask }) {
return metamask.preferences
}

View File

@ -6,9 +6,6 @@ const {
getCustomGasLimit,
getCustomGasPrice,
getCustomGasTotal,
getEstimatedGasPrices,
getEstimatedGasTimes,
getPriceAndTimeEstimates,
getRenderableBasicEstimateData,
getRenderableEstimateDataForSmallButtonsFromGWEI,
} = proxyquire('../custom-gas', {})
@ -42,48 +39,6 @@ describe('custom-gas selectors', function () {
})
})
describe('getPriceAndTimeEstimates', function () {
it('should return price and time estimates', function () {
const mockState = {
gas: { priceAndTimeEstimates: 'mockPriceAndTimeEstimates' },
}
assert.equal(
getPriceAndTimeEstimates(mockState),
'mockPriceAndTimeEstimates',
)
})
})
describe('getEstimatedGasPrices', function () {
it('should return price and time estimates', function () {
const mockState = {
gas: {
priceAndTimeEstimates: [
{ gasprice: 12, somethingElse: 20 },
{ gasprice: 22, expectedTime: 30 },
{ gasprice: 32, somethingElse: 40 },
],
},
}
assert.deepEqual(getEstimatedGasPrices(mockState), [12, 22, 32])
})
})
describe('getEstimatedGasTimes', function () {
it('should return price and time estimates', function () {
const mockState = {
gas: {
priceAndTimeEstimates: [
{ somethingElse: 12, expectedTime: 20 },
{ gasPrice: 22, expectedTime: 30 },
{ somethingElse: 32, expectedTime: 40 },
],
},
}
assert.deepEqual(getEstimatedGasTimes(mockState), [20, 30, 40])
})
})
describe('getRenderableBasicEstimateData()', function () {
const tests = [
{
@ -92,7 +47,6 @@ describe('custom-gas selectors', function () {
gasEstimateType: 'SLOW',
feeInSecondaryCurrency: '$0.01',
feeInPrimaryCurrency: '0.0000525 ETH',
timeEstimate: '~6 min 36 sec',
priceInHexWei: '0x9502f900',
},
{
@ -100,13 +54,11 @@ describe('custom-gas selectors', function () {
feeInPrimaryCurrency: '0.000084 ETH',
feeInSecondaryCurrency: '$0.02',
priceInHexWei: '0xee6b2800',
timeEstimate: '~5 min 18 sec',
},
{
gasEstimateType: 'FAST',
feeInSecondaryCurrency: '$0.03',
feeInPrimaryCurrency: '0.000105 ETH',
timeEstimate: '~3 min 18 sec',
priceInHexWei: '0x12a05f200',
},
],
@ -142,7 +94,6 @@ describe('custom-gas selectors', function () {
gasEstimateType: 'SLOW',
feeInSecondaryCurrency: '$0.27',
feeInPrimaryCurrency: '0.000105 ETH',
timeEstimate: '~13 min 12 sec',
priceInHexWei: '0x12a05f200',
},
{
@ -150,13 +101,11 @@ describe('custom-gas selectors', function () {
feeInSecondaryCurrency: '$0.38',
gasEstimateType: 'AVERAGE',
priceInHexWei: '0x1a13b8600',
timeEstimate: '~10 min 6 sec',
},
{
gasEstimateType: 'FAST',
feeInSecondaryCurrency: '$0.54',
feeInPrimaryCurrency: '0.00021 ETH',
timeEstimate: '~6 min 36 sec',
priceInHexWei: '0x2540be400',
},
],
@ -195,21 +144,18 @@ describe('custom-gas selectors', function () {
gasEstimateType: 'SLOW',
feeInSecondaryCurrency: '',
feeInPrimaryCurrency: '0.000105 ETH',
timeEstimate: '~13 min 12 sec',
priceInHexWei: '0x12a05f200',
},
{
gasEstimateType: 'AVERAGE',
feeInPrimaryCurrency: '0.000147 ETH',
feeInSecondaryCurrency: '',
timeEstimate: '~10 min 6 sec',
priceInHexWei: '0x1a13b8600',
},
{
gasEstimateType: 'FAST',
feeInSecondaryCurrency: '',
feeInPrimaryCurrency: '0.00021 ETH',
timeEstimate: '~6 min 36 sec',
priceInHexWei: '0x2540be400',
},
],
@ -248,7 +194,6 @@ describe('custom-gas selectors', function () {
gasEstimateType: 'SLOW',
feeInSecondaryCurrency: '$0.27',
feeInPrimaryCurrency: '0.000105 ETH',
timeEstimate: '~13 min 12 sec',
priceInHexWei: '0x12a05f200',
},
{
@ -256,13 +201,11 @@ describe('custom-gas selectors', function () {
feeInPrimaryCurrency: '0.000147 ETH',
feeInSecondaryCurrency: '$0.38',
priceInHexWei: '0x1a13b8600',
timeEstimate: '~10 min 6 sec',
},
{
gasEstimateType: 'FAST',
feeInSecondaryCurrency: '$0.54',
feeInPrimaryCurrency: '0.00021 ETH',
timeEstimate: '~6 min 36 sec',
priceInHexWei: '0x2540be400',
},
],
@ -282,15 +225,9 @@ describe('custom-gas selectors', function () {
},
gas: {
basicEstimates: {
blockTime: 14.16326530612245,
safeLow: 5,
safeLowWait: 13.2,
average: 7,
avgWait: 10.1,
fast: 10,
fastWait: 6.6,
fastest: 20,
fastestWait: 1.0,
},
},
},
@ -301,7 +238,6 @@ describe('custom-gas selectors', function () {
gasEstimateType: 'SLOW',
feeInSecondaryCurrency: '$0.27',
feeInPrimaryCurrency: '0.000105 ETH',
timeEstimate: '~13 min 12 sec',
priceInHexWei: '0x12a05f200',
},
{
@ -309,13 +245,11 @@ describe('custom-gas selectors', function () {
feeInPrimaryCurrency: '0.000147 ETH',
feeInSecondaryCurrency: '$0.38',
priceInHexWei: '0x1a13b8600',
timeEstimate: '~10 min 6 sec',
},
{
gasEstimateType: 'FAST',
feeInSecondaryCurrency: '$0.54',
feeInPrimaryCurrency: '0.00021 ETH',
timeEstimate: '~6 min 36 sec',
priceInHexWei: '0x2540be400',
},
],
@ -335,15 +269,9 @@ describe('custom-gas selectors', function () {
},
gas: {
basicEstimates: {
blockTime: 14.16326530612245,
safeLow: 5,
safeLowWait: 13.2,
average: 7,
avgWait: 10.1,
fast: 10,
fastWait: 6.6,
fastest: 20,
fastestWait: 1.0,
},
},
},
@ -402,15 +330,9 @@ describe('custom-gas selectors', function () {
},
gas: {
basicEstimates: {
blockTime: 14.16326530612245,
safeLow: 25,
safeLowWait: 6.6,
average: 30,
avgWait: 5.5,
fast: 50,
fastWait: 3.3,
fastest: 100,
fastestWait: 0.5,
},
},
},
@ -552,15 +474,9 @@ describe('custom-gas selectors', function () {
},
gas: {
basicEstimates: {
blockTime: 14.16326530612245,
safeLow: 50,
safeLowWait: 13.2,
average: 75,
avgWait: 9.6,
fast: 100,
fastWait: 6.6,
fastest: 200,
fastestWait: 1.0,
},
},
},
@ -602,15 +518,9 @@ describe('custom-gas selectors', function () {
},
gas: {
basicEstimates: {
blockTime: 14.16326530612245,
safeLow: 50,
safeLowWait: 13.2,
average: 75,
avgWait: 9.6,
fast: 100,
fastWait: 6.6,
fastest: 200,
fastestWait: 1.0,
},
},
},

274
yarn.lock
View File

@ -6290,13 +6290,6 @@ bytewise@~1.1.0:
bytewise-core "^1.2.2"
typewise "^1.0.3"
c3@^0.7.10:
version "0.7.12"
resolved "https://registry.yarnpkg.com/c3/-/c3-0.7.12.tgz#ad6205703bab9c2cbedc0223ba7fb2aabc31e94b"
integrity sha512-8gXyKMr9oM171aRGCOqezwEbWwEtIKmEkyvdfgH4oIunSsiTVWyw9Cz6os78LkYPRLMbHDgKcjkQh4EPCrRupQ==
dependencies:
d3 "^5.8.0"
cacache@^12.0.2:
version "12.0.3"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390"
@ -7152,7 +7145,7 @@ comma-separated-tokens@^1.0.0:
resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.7.tgz#419cd7fb3258b1ed838dc0953167a25e152f5b59"
integrity sha512-Jrx3xsP4pPv4AwJUDWY9wOXGtwPXARej6Xd99h4TUGotmf8APuquKMpK+dnD3UgyxK7OEWaisjZz+3b5jtL6xQ==
commander@2, commander@^2.15.0, commander@^2.15.1, commander@^2.16.0, commander@^2.19.0, commander@^2.20.0, commander@^2.6.0:
commander@^2.15.0, commander@^2.15.1, commander@^2.16.0, commander@^2.19.0, commander@^2.20.0, commander@^2.6.0:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
@ -7835,254 +7828,6 @@ cyclist@~0.2.2:
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=
d3-array@1, d3-array@^1.1.1, d3-array@^1.2.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f"
integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==
d3-axis@1:
version "1.0.12"
resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-1.0.12.tgz#cdf20ba210cfbb43795af33756886fb3638daac9"
integrity sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==
d3-brush@1:
version "1.0.6"
resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-1.0.6.tgz#33691f2032d9db6c5d8cb684ff255a9883629e21"
integrity sha512-lGSiF5SoSqO5/mYGD5FAeGKKS62JdA1EV7HPrU2b5rTX4qEJJtpjaGLJngjnkewQy7UnGstnFd3168wpf5z76w==
dependencies:
d3-dispatch "1"
d3-drag "1"
d3-interpolate "1"
d3-selection "1"
d3-transition "1"
d3-chord@1:
version "1.0.6"
resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-1.0.6.tgz#309157e3f2db2c752f0280fedd35f2067ccbb15f"
integrity sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==
dependencies:
d3-array "1"
d3-path "1"
d3-collection@1:
version "1.0.7"
resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.7.tgz#349bd2aa9977db071091c13144d5e4f16b5b310e"
integrity sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==
d3-color@1:
version "1.2.3"
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.2.3.tgz#6c67bb2af6df3cc8d79efcc4d3a3e83e28c8048f"
integrity sha512-x37qq3ChOTLd26hnps36lexMRhNXEtVxZ4B25rL0DVdDsGQIJGB18S7y9XDwlDD6MD/ZBzITCf4JjGMM10TZkw==
d3-contour@1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-1.3.2.tgz#652aacd500d2264cb3423cee10db69f6f59bead3"
integrity sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==
dependencies:
d3-array "^1.1.1"
d3-dispatch@1:
version "1.0.5"
resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.5.tgz#e25c10a186517cd6c82dd19ea018f07e01e39015"
integrity sha512-vwKx+lAqB1UuCeklr6Jh1bvC4SZgbSqbkGBLClItFBIYH4vqDJCA7qfoy14lXmJdnBOdxndAMxjCbImJYW7e6g==
d3-drag@1:
version "1.2.3"
resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-1.2.3.tgz#46e206ad863ec465d88c588098a1df444cd33c64"
integrity sha512-8S3HWCAg+ilzjJsNtWW1Mutl74Nmzhb9yU6igspilaJzeZVFktmY6oO9xOh5TDk+BM2KrNFjttZNoJJmDnkjkg==
dependencies:
d3-dispatch "1"
d3-selection "1"
d3-dsv@1:
version "1.0.10"
resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-1.0.10.tgz#4371c489a2a654a297aca16fcaf605a6f31a6f51"
integrity sha512-vqklfpxmtO2ZER3fq/B33R/BIz3A1PV0FaZRuFM8w6jLo7sUX1BZDh73fPlr0s327rzq4H6EN1q9U+eCBCSN8g==
dependencies:
commander "2"
iconv-lite "0.4"
rw "1"
d3-ease@1:
version "1.0.5"
resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.5.tgz#8ce59276d81241b1b72042d6af2d40e76d936ffb"
integrity sha512-Ct1O//ly5y5lFM9YTdu+ygq7LleSgSE4oj7vUt9tPLHUi8VCV7QoizGpdWRWAwCO9LdYzIrQDg97+hGVdsSGPQ==
d3-fetch@1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-1.1.2.tgz#957c8fbc6d4480599ba191b1b2518bf86b3e1be2"
integrity sha512-S2loaQCV/ZeyTyIF2oP8D1K9Z4QizUzW7cWeAOAS4U88qOt3Ucf6GsmgthuYSdyB2HyEm4CeGvkQxWsmInsIVA==
dependencies:
d3-dsv "1"
d3-force@1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-1.1.2.tgz#16664d0ac71d8727ef5effe0b374feac8050d6cd"
integrity sha512-p1vcHAUF1qH7yR+e8ip7Bs61AHjLeKkIn8Z2gzwU2lwEf2wkSpWdjXG0axudTHsVFnYGlMkFaEsVy2l8tAg1Gw==
dependencies:
d3-collection "1"
d3-dispatch "1"
d3-quadtree "1"
d3-timer "1"
d3-format@1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.3.2.tgz#6a96b5e31bcb98122a30863f7d92365c00603562"
integrity sha512-Z18Dprj96ExragQ0DeGi+SYPQ7pPfRMtUXtsg/ChVIKNBCzjO8XYJvRTC1usblx52lqge56V5ect+frYTQc8WQ==
d3-geo@1:
version "1.11.3"
resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.11.3.tgz#5bb08388f45e4b281491faa72d3abd43215dbd1c"
integrity sha512-n30yN9qSKREvV2fxcrhmHUdXP9TNH7ZZj3C/qnaoU0cVf/Ea85+yT7HY7i8ySPwkwjCNYtmKqQFTvLFngfkItQ==
dependencies:
d3-array "1"
d3-hierarchy@1:
version "1.1.8"
resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.8.tgz#7a6317bd3ed24e324641b6f1e76e978836b008cc"
integrity sha512-L+GHMSZNwTpiq4rt9GEsNcpLa4M96lXMR8M/nMG9p5hBE0jy6C+3hWtyZMenPQdwla249iJy7Nx0uKt3n+u9+w==
d3-interpolate@1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.3.2.tgz#417d3ebdeb4bc4efcc8fd4361c55e4040211fd68"
integrity sha512-NlNKGopqaz9qM1PXh9gBF1KSCVh+jSFErrSlD/4hybwoNX/gt1d8CDbDW+3i+5UOHhjC6s6nMvRxcuoMVNgL2w==
dependencies:
d3-color "1"
d3-path@1:
version "1.0.7"
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.7.tgz#8de7cd693a75ac0b5480d3abaccd94793e58aae8"
integrity sha512-q0cW1RpvA5c5ma2rch62mX8AYaiLX0+bdaSM2wxSU9tXjU4DNvkx9qiUvjkuWCj3p22UO/hlPivujqMiR9PDzA==
d3-polygon@1:
version "1.0.5"
resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-1.0.5.tgz#9a645a0a64ff6cbf9efda96ee0b4a6909184c363"
integrity sha512-RHhh1ZUJZfhgoqzWWuRhzQJvO7LavchhitSTHGu9oj6uuLFzYZVeBzaWTQ2qSO6bz2w55RMoOCf0MsLCDB6e0w==
d3-quadtree@1:
version "1.0.5"
resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-1.0.5.tgz#305394840b01f51a341a0da5008585e837fe7e9b"
integrity sha512-U2tjwDFbZ75JRAg8A+cqMvqPg1G3BE7UTJn3h8DHjY/pnsAfWdbJKgyfcy7zKjqGtLAmI0q8aDSeG1TVIKRaHQ==
d3-random@1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-1.1.2.tgz#2833be7c124360bf9e2d3fd4f33847cfe6cab291"
integrity sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==
d3-scale-chromatic@1:
version "1.3.3"
resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-1.3.3.tgz#dad4366f0edcb288f490128979c3c793583ed3c0"
integrity sha512-BWTipif1CimXcYfT02LKjAyItX5gKiwxuPRgr4xM58JwlLocWbjPLI7aMEjkcoOQXMkYsmNsvv3d2yl/OKuHHw==
dependencies:
d3-color "1"
d3-interpolate "1"
d3-scale@2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-2.1.2.tgz#4e932b7b60182aee9073ede8764c98423e5f9a94"
integrity sha512-bESpd64ylaKzCDzvULcmHKZTlzA/6DGSVwx7QSDj/EnX9cpSevsdiwdHFYI9ouo9tNBbV3v5xztHS2uFeOzh8Q==
dependencies:
d3-array "^1.2.0"
d3-collection "1"
d3-format "1"
d3-interpolate "1"
d3-time "1"
d3-time-format "2"
d3-selection@1, d3-selection@^1.1.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.3.2.tgz#6e70a9df60801c8af28ac24d10072d82cbfdf652"
integrity sha512-OoXdv1nZ7h2aKMVg3kaUFbLLK5jXUFAMLD/Tu5JA96mjf8f2a9ZUESGY+C36t8R1WFeWk/e55hy54Ml2I62CRQ==
d3-shape@1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.2.2.tgz#f9dba3777a5825f9a8ce8bc928da08c17679e9a7"
integrity sha512-hUGEozlKecFZ2bOSNt7ENex+4Tk9uc/m0TtTEHBvitCBxUNjhzm5hS2GrrVRD/ae4IylSmxGeqX5tWC2rASMlQ==
dependencies:
d3-path "1"
d3-time-format@2:
version "2.1.3"
resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.1.3.tgz#ae06f8e0126a9d60d6364eac5b1533ae1bac826b"
integrity sha512-6k0a2rZryzGm5Ihx+aFMuO1GgelgIz+7HhB4PH4OEndD5q2zGn1mDfRdNrulspOfR6JXkb2sThhDK41CSK85QA==
dependencies:
d3-time "1"
d3-time@1:
version "1.0.10"
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.0.10.tgz#8259dd71288d72eeacfd8de281c4bf5c7393053c"
integrity sha512-hF+NTLCaJHF/JqHN5hE8HVGAXPStEq6/omumPE/SxyHVrR7/qQxusFDo0t0c/44+sCGHthC7yNGFZIEgju0P8g==
d3-timer@1:
version "1.0.9"
resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.9.tgz#f7bb8c0d597d792ff7131e1c24a36dd471a471ba"
integrity sha512-rT34J5HnQUHhcLvhSB9GjCkN0Ddd5Y8nCwDBG2u6wQEeYxT/Lf51fTFFkldeib/sE/J0clIe0pnCfs6g/lRbyg==
d3-transition@1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-1.1.3.tgz#3a435b05ce9cef9524fe0d38121cfb6905331ca6"
integrity sha512-tEvo3qOXL6pZ1EzcXxFcPNxC/Ygivu5NoBY6mbzidATAeML86da+JfVIUzon3dNM6UX6zjDx+xbYDmMVtTSjuA==
dependencies:
d3-color "1"
d3-dispatch "1"
d3-ease "1"
d3-interpolate "1"
d3-selection "^1.1.0"
d3-timer "1"
d3-voronoi@1:
version "1.1.4"
resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.4.tgz#dd3c78d7653d2bb359284ae478645d95944c8297"
integrity sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==
d3-zoom@1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-1.7.3.tgz#f444effdc9055c38077c4299b4df999eb1d47ccb"
integrity sha512-xEBSwFx5Z9T3/VrwDkMt+mr0HCzv7XjpGURJ8lWmIC8wxe32L39eWHIasEe/e7Ox8MPU4p1hvH8PKN2olLzIBg==
dependencies:
d3-dispatch "1"
d3-drag "1"
d3-interpolate "1"
d3-selection "1"
d3-transition "1"
d3@^5.15.0, d3@^5.8.0:
version "5.15.0"
resolved "https://registry.yarnpkg.com/d3/-/d3-5.15.0.tgz#ffd44958e6a3cb8a59a84429c45429b8bca5677a"
integrity sha512-C+E80SL2nLLtmykZ6klwYj5rPqB5nlfN5LdWEAVdWPppqTD8taoJi2PxLZjPeYT8FFRR2yucXq+kBlOnnvZeLg==
dependencies:
d3-array "1"
d3-axis "1"
d3-brush "1"
d3-chord "1"
d3-collection "1"
d3-color "1"
d3-contour "1"
d3-dispatch "1"
d3-drag "1"
d3-dsv "1"
d3-ease "1"
d3-fetch "1"
d3-force "1"
d3-format "1"
d3-geo "1"
d3-hierarchy "1"
d3-interpolate "1"
d3-path "1"
d3-polygon "1"
d3-quadtree "1"
d3-random "1"
d3-scale "2"
d3-scale-chromatic "1"
d3-selection "1"
d3-shape "1"
d3-time "1"
d3-time-format "2"
d3-timer "1"
d3-transition "1"
d3-voronoi "1"
d3-zoom "1"
d64@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/d64/-/d64-1.0.0.tgz#4002a87e850cbfc9f9d9706b60fca613a3336e90"
@ -13469,18 +13214,18 @@ hyphenate-style-name@^1.0.3:
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48"
integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==
iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
iconv-lite@0.4.19:
version "0.4.19"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==
iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
dependencies:
safer-buffer ">= 2.1.2 < 3"
iconv-lite@0.4.19:
version "0.4.19"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==
icss-replace-symbols@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
@ -22614,11 +22359,6 @@ rustbn.js@~0.2.0:
resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca"
integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==
rw@1:
version "1.3.3"
resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=
rx-lite@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"