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

Feature: Transaction Insights (#12881)

* integration for tx decoding confirmation and history view

* upgrading @truffle/decoder to latest release 5.1.0

* Update acorn and colors patches

* feat: remove redundant styling

* feat: basic integration for nickname components

* feat: wiring functionality of adding new nickname

* feat: wire functionality of showing nickname modal

* feat: link the nickname popover with add/update popover

* feat: moving forward with address nicknames integration

* feat: fixing a bug related to passing chainId in addressBook

* feat: populating memo prop in addressbook entry

* feat: add explorer link

* feat: bug fixing update nickname component

* feat: fix proptypes

* feat: adding tooltip for copying nickname address

* featL fix styling for tx-details page

* feat: optimize code for error handling

* feat: limiting transaction decoding to tx with data

* feat: remove tree UI component

* feat: adding request to check for tx decoding supported networks

* feat: showing data hex component

* feat: fix react warnings

* feat: remove extra margin in tx decoding

* Remove unused package @truffle/source-map-utils

* Ensure messages get translated

* feat: link tx-decoding addresses with nicknames

* Omit value for boolean attributes

* Fix props reading in CopyRawData

* fix: fixing issue with transaltion

* Fix lint errors in TransactionDecoding

- Remove unused import
- Reorder imports
- Address conflict between caught `error` and error state flag by
  renaming state flag to `hasError`
- Fix requestUrl identifier casing and use of template string
- Ensure `useEffect` gets passed the deps it needs
- Add scope braces around case statement where it's needed
- Omit literal `true` for boolean jsx attribute
- Refactor nested ternary as `if` statements

* fix: revert fetchWithCache modifications

* Fix linting for TransactionListItemDetails

- Remove unused import
- Fix import spacing
- Remove unused prop dereference
- Fix string interpolation for translated From/To

* Moving to popover pattern

* fix: sass color variable

* Omit value for boolean attribute

* Remove changes from modal.js

* fix: refactor nickname popovers

* Ensure const gets declared before it's used

* Fix linting for ConfirmTransactionBase

- Remove unused prop chainId
- Stop destructuring an unused field

* fix: refactor usage of nicknames popovers in send-content-container

* fix: remove extra prop updateAccountNicknameModal

* fix: refactor code for address.component

* fix: remove extra tooltip

* Ensure NicknamePopovers always returns component

* Fix linting for NicknamePopover component

- Fix useCallback deps
- Switch ternary to logical-or

* Fix linting for SenderToRecipient

... by fixing import order

* Remove unused addressCopied state

* Delete empty file

* fix: remove sender-to-recipient.container

* fix: refactor usage of nickname popovers in confirm-page-container

* fix: bug related to state variable

* Stylelint fix

* Lint fix

* Change "Total Amount" to "Total"

* Lint fix locales

* Update address-book.spec.js

* e2e test update

* Update e2e tests

* Fix issue where absence of function params in data hex tab would result in rendering a  string

* Fix border radius, and width and height in small notification windows, of the update-nickname-popover

* Remove fake await

* Clean up

* Clean up

Co-authored-by: Alaa Hadad <alaahd@Alaas-MacBook-M1-Pro-14-inch.local>
Co-authored-by: Dan Miller <danjm.com@gmail.com>
Co-authored-by: g. nicholas d'andrea <gnidan@trufflesuite.com>
This commit is contained in:
Alaa Hadad 2021-12-01 21:22:08 +04:00 committed by GitHub
parent fb60b14367
commit e056c88ba7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
93 changed files with 1573 additions and 365 deletions

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "ተቀድቷል" "message": "ተቀድቷል"
}, },
"copiedTransactionId": {
"message": "የተቀዳ የግብይት መለያ ቁጥር"
},
"copyAddress": { "copyAddress": {
"message": "አድራሻን ወደ ቅንጥብ ሰሌዳ ቅዳ" "message": "አድራሻን ወደ ቅንጥብ ሰሌዳ ቅዳ"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "تم النسخ." "message": "تم النسخ."
}, },
"copiedTransactionId": {
"message": "تم نسخ معرف المعاملة"
},
"copyAddress": { "copyAddress": {
"message": "نسخ العنوان إلى الحافظة" "message": "نسخ العنوان إلى الحافظة"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Копирано!" "message": "Копирано!"
}, },
"copiedTransactionId": {
"message": "Копиран идентификационен номер на транзакцията"
},
"copyAddress": { "copyAddress": {
"message": "Копирайте адреса в клипборда" "message": "Копирайте адреса в клипборда"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "কপি করা হয়েছে!" "message": "কপি করা হয়েছে!"
}, },
"copiedTransactionId": {
"message": "কপি করা লেনদেনের আইডি"
},
"copyAddress": { "copyAddress": {
"message": "ক্লিপবোর্ডে ঠিকানা কপি করুন" "message": "ক্লিপবোর্ডে ঠিকানা কপি করুন"
}, },

View File

@ -215,9 +215,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "S'ha copiat!" "message": "S'ha copiat!"
}, },
"copiedTransactionId": {
"message": "ID de transacció copiada"
},
"copyAddress": { "copyAddress": {
"message": "Copiar adreça al porta-retalls" "message": "Copiar adreça al porta-retalls"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Kopieret!" "message": "Kopieret!"
}, },
"copiedTransactionId": {
"message": "Kopieret transaktions-id"
},
"copyAddress": { "copyAddress": {
"message": "Kopier adresse til udklipsholder" "message": "Kopier adresse til udklipsholder"
}, },

View File

@ -209,9 +209,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Kopiert!" "message": "Kopiert!"
}, },
"copiedTransactionId": {
"message": "Transaktions-ID kopiert"
},
"copyAddress": { "copyAddress": {
"message": "Adresse in die Zwischenablage kopieren" "message": "Adresse in die Zwischenablage kopieren"
}, },

View File

@ -215,9 +215,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Έγινε αντιγραφή!" "message": "Έγινε αντιγραφή!"
}, },
"copiedTransactionId": {
"message": "Αντιγράφηκε το Αναγνωριστικό Συναλλαγής"
},
"copyAddress": { "copyAddress": {
"message": "Αντιγράψτε τη διεύθυνση στο πρόχειρο" "message": "Αντιγράψτε τη διεύθυνση στο πρόχειρο"
}, },

View File

@ -351,10 +351,6 @@
"message": "Swap", "message": "Swap",
"description": "This is used with viewOnEtherscan e.g View Swap on Etherscan" "description": "This is used with viewOnEtherscan e.g View Swap on Etherscan"
}, },
"blockExplorerTransactionAction": {
"message": "Transaction",
"description": "This is used with viewOnCustomBlockExplorer and viewOnEtherscan e.g View Transaction on Etherscan"
},
"blockExplorerUrl": { "blockExplorerUrl": {
"message": "Block Explorer URL" "message": "Block Explorer URL"
}, },
@ -581,15 +577,15 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Copied!" "message": "Copied!"
}, },
"copiedTransactionId": {
"message": "Copied Transaction ID"
},
"copyAddress": { "copyAddress": {
"message": "Copy address to clipboard" "message": "Copy address to clipboard"
}, },
"copyPrivateKey": { "copyPrivateKey": {
"message": "This is your private key (click to copy)" "message": "This is your private key (click to copy)"
}, },
"copyRawTransactionData": {
"message": "Copy raw transaction data"
},
"copyToClipboard": { "copyToClipboard": {
"message": "Copy to clipboard" "message": "Copy to clipboard"
}, },
@ -666,6 +662,9 @@
"dataBackupFoundInfo": { "dataBackupFoundInfo": {
"message": "Some of your account data was backed up during a previous installation of MetaMask. This could include your settings, contacts, and tokens. Would you like to restore this data now?" "message": "Some of your account data was backed up during a previous installation of MetaMask. This could include your settings, contacts, and tokens. Would you like to restore this data now?"
}, },
"dataHex": {
"message": "Hex"
},
"decimal": { "decimal": {
"message": "Token Decimal" "message": "Token Decimal"
}, },
@ -767,6 +766,9 @@
"edit": { "edit": {
"message": "Edit" "message": "Edit"
}, },
"editANickname": {
"message": "Edit nickname"
},
"editAddressNickname": { "editAddressNickname": {
"message": "Edit address nickname" "message": "Edit address nickname"
}, },
@ -3043,6 +3045,12 @@
"transactionCreated": { "transactionCreated": {
"message": "Transaction created with a value of $1 at $2." "message": "Transaction created with a value of $1 at $2."
}, },
"transactionData": {
"message": "Transaction data"
},
"transactionDecodingUnsupportedNetworkError": {
"message": "Transaction decoding is not available for chainId $1"
},
"transactionDetailDappGasMoreInfo": { "transactionDetailDappGasMoreInfo": {
"message": "Site suggested" "message": "Site suggested"
}, },

View File

@ -416,9 +416,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "¡Copiado!" "message": "¡Copiado!"
}, },
"copiedTransactionId": {
"message": "Id. de transacción copiado"
},
"copyAddress": { "copyAddress": {
"message": "Copiar dirección al Portapapeles" "message": "Copiar dirección al Portapapeles"
}, },

View File

@ -416,9 +416,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "¡Copiado!" "message": "¡Copiado!"
}, },
"copiedTransactionId": {
"message": "Id. de transacción copiado"
},
"copyAddress": { "copyAddress": {
"message": "Copiar dirección al Portapapeles" "message": "Copiar dirección al Portapapeles"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Kopeeritud!" "message": "Kopeeritud!"
}, },
"copiedTransactionId": {
"message": "Kopeeritud tehingu ID"
},
"copyAddress": { "copyAddress": {
"message": "Kopeeri aadress lõikelauale" "message": "Kopeeri aadress lõikelauale"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "کپی شد!" "message": "کپی شد!"
}, },
"copiedTransactionId": {
"message": "آی دی معامله کاپی شده"
},
"copyAddress": { "copyAddress": {
"message": "کاپی آدرس به کلیپ بورد" "message": "کاپی آدرس به کلیپ بورد"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Kopioitu" "message": "Kopioitu"
}, },
"copiedTransactionId": {
"message": "Kopioitu tapahtuman tunnus"
},
"copyAddress": { "copyAddress": {
"message": "Kopioi osoite leikepöydälle" "message": "Kopioi osoite leikepöydälle"
}, },

View File

@ -197,9 +197,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Nakopya!" "message": "Nakopya!"
}, },
"copiedTransactionId": {
"message": "Nakopya ang Transaction ID"
},
"copyAddress": { "copyAddress": {
"message": "Kopyahin ang address sa clipboard" "message": "Kopyahin ang address sa clipboard"
}, },

View File

@ -209,9 +209,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Copié!" "message": "Copié!"
}, },
"copiedTransactionId": {
"message": "ID de transaction copié"
},
"copyAddress": { "copyAddress": {
"message": "Copier l'addresse dans le presse-papier" "message": "Copier l'addresse dans le presse-papier"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "הועתק!" "message": "הועתק!"
}, },
"copiedTransactionId": {
"message": "מזהה עסקה הועתק"
},
"copyAddress": { "copyAddress": {
"message": "העתק כתובת ללוח" "message": "העתק כתובת ללוח"
}, },

View File

@ -416,9 +416,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "कॉपी किया गया!" "message": "कॉपी किया गया!"
}, },
"copiedTransactionId": {
"message": "कॉपी की गई लेनदेन ID"
},
"copyAddress": { "copyAddress": {
"message": "क्लिपबोर्ड पर पता कॉपी करें" "message": "क्लिपबोर्ड पर पता कॉपी करें"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Kopirano!" "message": "Kopirano!"
}, },
"copiedTransactionId": {
"message": "Kopirana identifikacijska oznaka transakcije"
},
"copyAddress": { "copyAddress": {
"message": "Kopiraj adresu u međuspremnik" "message": "Kopiraj adresu u međuspremnik"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Kimásolva!" "message": "Kimásolva!"
}, },
"copiedTransactionId": {
"message": "Másolt tranzakció-azonosító"
},
"copyAddress": { "copyAddress": {
"message": "Másolja a címet a vágólapra" "message": "Másolja a címet a vágólapra"
}, },

View File

@ -416,9 +416,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Disalin!" "message": "Disalin!"
}, },
"copiedTransactionId": {
"message": "ID Transaksi yang Disalin"
},
"copyAddress": { "copyAddress": {
"message": "Salin alamat ke clipboard" "message": "Salin alamat ke clipboard"
}, },

View File

@ -356,9 +356,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Copiato!" "message": "Copiato!"
}, },
"copiedTransactionId": {
"message": "ID Transazione Copiato"
},
"copyAddress": { "copyAddress": {
"message": "Copia l'indirizzo" "message": "Copia l'indirizzo"
}, },

View File

@ -416,9 +416,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "コピーされました!" "message": "コピーされました!"
}, },
"copiedTransactionId": {
"message": "コピーされたトランザクション ID"
},
"copyAddress": { "copyAddress": {
"message": "アドレスをクリップボードにコピー" "message": "アドレスをクリップボードにコピー"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "ನಕಲಿಸಲಾಗಿದೆ!" "message": "ನಕಲಿಸಲಾಗಿದೆ!"
}, },
"copiedTransactionId": {
"message": "ವ್ಯವಹಾರ ID ಅನ್ನು ನಕಲಿಸಲಾಗಿದೆ"
},
"copyAddress": { "copyAddress": {
"message": "ವಿಳಾಸವನ್ನು ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ಗೆ ನಕಲಿಸಿ" "message": "ವಿಳಾಸವನ್ನು ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ಗೆ ನಕಲಿಸಿ"
}, },

View File

@ -416,9 +416,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "복사 완료!" "message": "복사 완료!"
}, },
"copiedTransactionId": {
"message": "거래 ID 복사됨"
},
"copyAddress": { "copyAddress": {
"message": "주소를 클립보드에 복사" "message": "주소를 클립보드에 복사"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Nukopijuota!" "message": "Nukopijuota!"
}, },
"copiedTransactionId": {
"message": "Nukopijuotas operacijos ID"
},
"copyAddress": { "copyAddress": {
"message": "Kopijuoti adresą į iškarpinę" "message": "Kopijuoti adresą į iškarpinę"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Nokopēts!" "message": "Nokopēts!"
}, },
"copiedTransactionId": {
"message": "Nokopētais darījuma ID"
},
"copyAddress": { "copyAddress": {
"message": "Iekopēt adresi starpliktuvē" "message": "Iekopēt adresi starpliktuvē"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Disalin!" "message": "Disalin!"
}, },
"copiedTransactionId": {
"message": "ID Transaksi yang Disalin"
},
"copyAddress": { "copyAddress": {
"message": "Salin alamat kepada papan klip" "message": "Salin alamat kepada papan klip"
}, },

View File

@ -215,9 +215,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Kopiert!" "message": "Kopiert!"
}, },
"copiedTransactionId": {
"message": "Kopiert transaksjonsidentifikasjon"
},
"copyAddress": { "copyAddress": {
"message": "Kopier adresse til utklippstavlen " "message": "Kopier adresse til utklippstavlen "
}, },

View File

@ -416,9 +416,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Nakopya na!" "message": "Nakopya na!"
}, },
"copiedTransactionId": {
"message": "Nakopya ang Transaction ID"
},
"copyAddress": { "copyAddress": {
"message": "Kopyahin ang address sa clipboard" "message": "Kopyahin ang address sa clipboard"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Skopiowane!" "message": "Skopiowane!"
}, },
"copiedTransactionId": {
"message": "Skopiowano identyfikator transakcji"
},
"copyAddress": { "copyAddress": {
"message": "Skopiuj adres do schowka" "message": "Skopiuj adres do schowka"
}, },

View File

@ -416,9 +416,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Copiado!" "message": "Copiado!"
}, },
"copiedTransactionId": {
"message": "ID da transação copiado"
},
"copyAddress": { "copyAddress": {
"message": "Copiar endereço para área de transferência" "message": "Copiar endereço para área de transferência"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Copiat!" "message": "Copiat!"
}, },
"copiedTransactionId": {
"message": "ID-ul tranzacției a fost copiat"
},
"copyAddress": { "copyAddress": {
"message": "Copiere adresă în clipboard" "message": "Copiere adresă în clipboard"
}, },

View File

@ -416,9 +416,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Скопировано!" "message": "Скопировано!"
}, },
"copiedTransactionId": {
"message": "Скопированный идентификатор транзакции"
},
"copyAddress": { "copyAddress": {
"message": "Скопировать адрес в буфер обмена" "message": "Скопировать адрес в буфер обмена"
}, },

View File

@ -212,9 +212,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Zkopírováno!" "message": "Zkopírováno!"
}, },
"copiedTransactionId": {
"message": "Kopírované ID transakcie"
},
"copyAddress": { "copyAddress": {
"message": "Kopírovať adresu do schránky" "message": "Kopírovať adresu do schránky"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Kopirano!" "message": "Kopirano!"
}, },
"copiedTransactionId": {
"message": "ID transakcije skopirana"
},
"copyAddress": { "copyAddress": {
"message": "Kopiraj naslov v odložišče" "message": "Kopiraj naslov v odložišče"
}, },

View File

@ -215,9 +215,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Kopirano!" "message": "Kopirano!"
}, },
"copiedTransactionId": {
"message": "Kopiran identifikator transakcije"
},
"copyAddress": { "copyAddress": {
"message": "Kopirajte adresu u ostavu" "message": "Kopirajte adresu u ostavu"
}, },

View File

@ -212,9 +212,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Kopierades!" "message": "Kopierades!"
}, },
"copiedTransactionId": {
"message": "Kopierade transaktions-ID"
},
"copyAddress": { "copyAddress": {
"message": "Kopiera adress till urklipp" "message": "Kopiera adress till urklipp"
}, },

View File

@ -212,9 +212,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Imenakiliwa!" "message": "Imenakiliwa!"
}, },
"copiedTransactionId": {
"message": "Imenakili Utambulisho wa Muamala"
},
"copyAddress": { "copyAddress": {
"message": "Nakili anwani kwenye ubao wa kunakilia" "message": "Nakili anwani kwenye ubao wa kunakilia"
}, },

View File

@ -344,9 +344,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Nakopya na!" "message": "Nakopya na!"
}, },
"copiedTransactionId": {
"message": "Nakopya ang ID ng Transaksyon"
},
"copyAddress": { "copyAddress": {
"message": "Kopyahin ang address sa clipboard" "message": "Kopyahin ang address sa clipboard"
}, },

View File

@ -218,9 +218,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Скопійовано!" "message": "Скопійовано!"
}, },
"copiedTransactionId": {
"message": "ID Скопійованої транзакції"
},
"copyAddress": { "copyAddress": {
"message": "Копіювати адресу в буфер обміну" "message": "Копіювати адресу в буфер обміну"
}, },

View File

@ -416,9 +416,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "Đã sao chép!" "message": "Đã sao chép!"
}, },
"copiedTransactionId": {
"message": "Đã sao chép mã giao dịch"
},
"copyAddress": { "copyAddress": {
"message": "Sao chép địa chỉ vào khay nhớ tạm" "message": "Sao chép địa chỉ vào khay nhớ tạm"
}, },

View File

@ -395,9 +395,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "已复制" "message": "已复制"
}, },
"copiedTransactionId": {
"message": "交易 ID 复制成功"
},
"copyAddress": { "copyAddress": {
"message": "复制地址到剪贴板" "message": "复制地址到剪贴板"
}, },

View File

@ -227,9 +227,6 @@
"copiedExclamation": { "copiedExclamation": {
"message": "已複製!" "message": "已複製!"
}, },
"copiedTransactionId": {
"message": "已複製的交易 ID"
},
"copyAddress": { "copyAddress": {
"message": "複製到剪貼簿" "message": "複製到剪貼簿"
}, },

View File

@ -0,0 +1,26 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="16" height="16" fill="#E5E5E5"/>
<g clip-path="url(#clip0_0_1)">
<rect width="413" height="679" transform="translate(-57 -402)" fill="white"/>
<g filter="url(#filter0_d_0_1)">
<path d="M-31 -376C-31 -380.418 -27.4183 -384 -23 -384H321C325.418 -384 329 -380.418 329 -376V252C329 256.418 325.418 260 321 260H-23C-27.4183 260 -31 256.418 -31 252V-376Z" fill="white"/>
</g>
<circle cx="8" cy="8" r="7.5" fill="#F2F3F4" stroke="#D6D9DC"/>
<line x1="4.1001" y1="7.83325" x2="11.7668" y2="7.83325" stroke="#D6D9DC" stroke-linecap="round"/>
</g>
<rect x="-2918.5" y="-1621.5" width="9747" height="4874" stroke="black"/>
<defs>
<filter id="filter0_d_0_1" x="-58" y="-409" width="414" height="698" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feGaussianBlur stdDeviation="13.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.12594 0 0 0 0 0.182502 0 0 0 0 0.305378 0 0 0 0.26 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_0_1"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_0_1" result="shape"/>
</filter>
<clipPath id="clip0_0_1">
<rect width="413" height="679" fill="white" transform="translate(-57 -402)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,28 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="16" height="16" fill="#E5E5E5"/>
<g clip-path="url(#clip0_0_1)">
<rect width="413" height="679" transform="translate(-57 -546)" fill="white"/>
<g filter="url(#filter0_d_0_1)">
<path d="M-31 -520C-31 -524.418 -27.4183 -528 -23 -528H321C325.418 -528 329 -524.418 329 -520V108C329 112.418 325.418 116 321 116H-23C-27.4183 116 -31 112.418 -31 108V-520Z" fill="white"/>
</g>
<line x1="7.5" y1="-128" x2="7.49999" y2="8" stroke="#D6D9DC"/>
<circle cx="8" cy="8" r="7.5" fill="white" stroke="#D6D9DC"/>
<line x1="4.1001" y1="7.83325" x2="11.7668" y2="7.83325" stroke="#D6D9DC" stroke-linecap="round"/>
<line x1="8.1001" y1="4.16699" x2="8.1001" y2="11.8337" stroke="#D6D9DC" stroke-linecap="round"/>
</g>
<rect x="-2918.5" y="-1765.5" width="9747" height="4874" stroke="black"/>
<defs>
<filter id="filter0_d_0_1" x="-58" y="-553" width="414" height="698" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feGaussianBlur stdDeviation="13.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.12594 0 0 0 0 0.182502 0 0 0 0 0.305378 0 0 0 0.26 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_0_1"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_0_1" result="shape"/>
</filter>
<clipPath id="clip0_0_1">
<rect width="413" height="679" fill="white" transform="translate(-57 -546)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -125,6 +125,8 @@
"@reduxjs/toolkit": "^1.6.2", "@reduxjs/toolkit": "^1.6.2",
"@sentry/browser": "^6.0.0", "@sentry/browser": "^6.0.0",
"@sentry/integrations": "^6.0.0", "@sentry/integrations": "^6.0.0",
"@truffle/codec": "^0.11.18",
"@truffle/decoder": "^5.1.0",
"@zxing/browser": "^0.0.10", "@zxing/browser": "^0.0.10",
"@zxing/library": "0.8.0", "@zxing/library": "0.8.0",
"analytics-node": "^3.4.0-beta.3", "analytics-node": "^3.4.0-beta.3",
@ -260,6 +262,7 @@
"babelify": "^10.0.0", "babelify": "^10.0.0",
"bify-module-groups": "^1.0.0", "bify-module-groups": "^1.0.0",
"brfs": "^2.0.2", "brfs": "^2.0.2",
"browser-util-inspect": "^0.2.0",
"browserify": "^16.5.1", "browserify": "^16.5.1",
"chalk": "^3.0.0", "chalk": "^3.0.0",
"chromedriver": "^95.0.0", "chromedriver": "^95.0.0",

13
patches/acorn+7.4.1.patch Normal file
View File

@ -0,0 +1,13 @@
diff --git a/node_modules/acorn/dist/acorn.js b/node_modules/acorn/dist/acorn.js
index 0523f0e..9d3d5c2 100644
--- a/node_modules/acorn/dist/acorn.js
+++ b/node_modules/acorn/dist/acorn.js
@@ -1835,7 +1835,7 @@
if (checkClashes) {
if (has(checkClashes, expr.name))
{ this.raiseRecoverable(expr.start, "Argument name clash"); }
- checkClashes[expr.name] = true;
+ Object.defineProperty(checkClashes, expr.name, { value: true, writable: true, enumerable: true, configurable: true })
}
if (bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); }
break

View File

@ -0,0 +1,14 @@
diff --git a/node_modules/colors/lib/extendStringPrototype.js b/node_modules/colors/lib/extendStringPrototype.js
index 46fd386..c7d0fc5 100644
--- a/node_modules/colors/lib/extendStringPrototype.js
+++ b/node_modules/colors/lib/extendStringPrototype.js
@@ -5,7 +5,8 @@ module['exports'] = function() {
// Extends prototype of native string object to allow for "foo".red syntax
//
var addProperty = function(color, func) {
- String.prototype.__defineGetter__(color, func);
+ // remove prototype mutation so this plays well with LavaMoat
+ // String.prototype.__defineGetter__(color, func);
};
addProperty('strip', function() {

View File

@ -349,14 +349,14 @@ describe('MetaMask', function () {
}); });
it('displays the token transfer data', async function () { it('displays the token transfer data', async function () {
await driver.clickElement({ text: 'Data', tag: 'button' }); await driver.clickElement({ text: 'Hex', tag: 'button' });
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
const functionType = await driver.findElement( const functionType = await driver.findElement(
'.confirm-page-container-content__function-type', '.confirm-page-container-content__function-type',
); );
const functionTypeText = await functionType.getText(); const functionTypeText = await functionType.getText();
assert.equal(functionTypeText, 'Transfer'); assert(functionTypeText.match('Transfer'));
const tokenAmount = await driver.findElement( const tokenAmount = await driver.findElement(
'.confirm-page-container-summary__title-text', '.confirm-page-container-summary__title-text',

View File

@ -34,13 +34,16 @@ describe('Address Book', function () {
await driver.clickElement('.dialog.send__dialog.dialog--message'); await driver.clickElement('.dialog.send__dialog.dialog--message');
// wait for address book modal to be visible // wait for address book modal to be visible
const addressModal = await driver.findElement('span .modal'); const addressModal = await driver.findElement('.nickname-popover');
await driver.findElement('.add-to-address-book-modal'); await driver.clickElement('.nickname-popover__footer-button');
await driver.fill('.add-to-address-book-modal__input', 'Test Name 1'); await driver.findElement('.update-nickname__wrapper');
await driver.clickElement(
'.add-to-address-book-modal__footer .btn-primary', await driver.fill(
'.update-nickname__content__text-field input',
'Test Name 1',
); );
await driver.clickElement('.update-nickname__save');
// wait for address book modal to be removed from DOM // wait for address book modal to be removed from DOM
await addressModal.waitForElementState('hidden'); await addressModal.waitForElementState('hidden');

View File

@ -58,3 +58,4 @@
@import 'advanced-gas-fee-popover/advanced-gas-fee-inputs/index'; @import 'advanced-gas-fee-popover/advanced-gas-fee-inputs/index';
@import 'advanced-gas-fee-popover/advanced-gas-fee-inputs/base-fee-input/index'; @import 'advanced-gas-fee-popover/advanced-gas-fee-inputs/base-fee-input/index';
@import 'advanced-gas-fee-popover/advanced-gas-fee-input-subtext/index'; @import 'advanced-gas-fee-popover/advanced-gas-fee-input-subtext/index';
@import 'transaction-decoding/index';

View File

@ -58,7 +58,6 @@ describe('Confirm Page Container Container Test', () => {
handleCloseEditGas: sinon.spy(), handleCloseEditGas: sinon.spy(),
// Gas Popover // Gas Popover
currentTransaction: {}, currentTransaction: {},
showAddToAddressBookModal: sinon.spy(),
contact: undefined, contact: undefined,
isOwnedAccount: false, isOwnedAccount: false,
}; };
@ -118,12 +117,6 @@ describe('Confirm Page Container Container Test', () => {
); );
}); });
it('should simulate click on Dialog', () => {
const DialogWrapper = wrapper.find(Dialog);
DialogWrapper.first().simulate('click');
expect(props.showAddToAddressBookModal.calledOnce).toStrictEqual(true);
});
it('should not show add to address dialog if contact is not undefined', () => { it('should not show add to address dialog if contact is not undefined', () => {
props.contact = { props.contact = {
address: '0x7a1A4Ad9cc746a70ee58568466f7996dD0aCE4E8', address: '0x7a1A4Ad9cc746a70ee58568466f7996dD0aCE4E8',

View File

@ -15,6 +15,7 @@ export default class ConfirmPageContainerContent extends Component {
static propTypes = { static propTypes = {
action: PropTypes.string, action: PropTypes.string,
dataComponent: PropTypes.node, dataComponent: PropTypes.node,
dataHexComponent: PropTypes.node,
detailsComponent: PropTypes.node, detailsComponent: PropTypes.node,
errorKey: PropTypes.string, errorKey: PropTypes.string,
errorMessage: PropTypes.string, errorMessage: PropTypes.string,
@ -54,7 +55,7 @@ export default class ConfirmPageContainerContent extends Component {
renderTabs() { renderTabs() {
const { t } = this.context; const { t } = this.context;
const { detailsComponent, dataComponent } = this.props; const { detailsComponent, dataComponent, dataHexComponent } = this.props;
return ( return (
<Tabs> <Tabs>
@ -67,6 +68,12 @@ export default class ConfirmPageContainerContent extends Component {
<Tab className="confirm-page-container-content__tab" name={t('data')}> <Tab className="confirm-page-container-content__tab" name={t('data')}>
{dataComponent} {dataComponent}
</Tab> </Tab>
<Tab
className="confirm-page-container-content__tab"
name={t('dataHex')}
>
{dataHexComponent}
</Tab>
</Tabs> </Tabs>
); );
} }

View File

@ -20,6 +20,10 @@
&__data { &__data {
padding: 16px; padding: 16px;
color: $oslo-gray; color: $oslo-gray;
& > .disclosure {
margin-top: 0;
}
} }
&__data-box { &__data-box {
@ -27,9 +31,7 @@
background-color: #f9fafa; background-color: #f9fafa;
padding: 12px; padding: 12px;
margin-bottom: 16px;
word-wrap: break-word; word-wrap: break-word;
max-height: 200px;
overflow-y: auto; overflow-y: auto;
&-label { &-label {

View File

@ -10,6 +10,8 @@ import Dialog from '../../ui/dialog';
import ErrorMessage from '../../ui/error-message'; import ErrorMessage from '../../ui/error-message';
import SenderToRecipient from '../../ui/sender-to-recipient'; import SenderToRecipient from '../../ui/sender-to-recipient';
import NicknamePopovers from '../modals/nickname-popovers';
import AdvancedGasFeePopover from '../advanced-gas-fee-popover'; import AdvancedGasFeePopover from '../advanced-gas-fee-popover';
import EditGasFeePopover from '../edit-gas-fee-popover/edit-gas-fee-popover'; import EditGasFeePopover from '../edit-gas-fee-popover/edit-gas-fee-popover';
import EditGasPopover from '../edit-gas-popover'; import EditGasPopover from '../edit-gas-popover';
@ -21,6 +23,10 @@ import {
} from '.'; } from '.';
export default class ConfirmPageContainer extends Component { export default class ConfirmPageContainer extends Component {
state = {
showNicknamePopovers: false,
};
static contextTypes = { static contextTypes = {
t: PropTypes.func, t: PropTypes.func,
}; };
@ -48,6 +54,7 @@ export default class ConfirmPageContainer extends Component {
errorKey: PropTypes.string, errorKey: PropTypes.string,
errorMessage: PropTypes.string, errorMessage: PropTypes.string,
dataComponent: PropTypes.node, dataComponent: PropTypes.node,
dataHexComponent: PropTypes.node,
detailsComponent: PropTypes.node, detailsComponent: PropTypes.node,
identiconAddress: PropTypes.string, identiconAddress: PropTypes.string,
nonce: PropTypes.string, nonce: PropTypes.string,
@ -75,7 +82,6 @@ export default class ConfirmPageContainer extends Component {
handleCloseEditGas: PropTypes.func, handleCloseEditGas: PropTypes.func,
// Gas Popover // Gas Popover
currentTransaction: PropTypes.object.isRequired, currentTransaction: PropTypes.object.isRequired,
showAddToAddressBookModal: PropTypes.func,
contact: PropTypes.object, contact: PropTypes.object,
isOwnedAccount: PropTypes.bool, isOwnedAccount: PropTypes.bool,
supportsEIP1559V2: PropTypes.bool, supportsEIP1559V2: PropTypes.bool,
@ -102,6 +108,7 @@ export default class ConfirmPageContainer extends Component {
hideSubtitle, hideSubtitle,
detailsComponent, detailsComponent,
dataComponent, dataComponent,
dataHexComponent,
onCancelAll, onCancelAll,
onCancel, onCancel,
onSubmit, onSubmit,
@ -126,7 +133,6 @@ export default class ConfirmPageContainer extends Component {
editingGas, editingGas,
handleCloseEditGas, handleCloseEditGas,
currentTransaction, currentTransaction,
showAddToAddressBookModal,
contact = {}, contact = {},
isOwnedAccount, isOwnedAccount,
supportsEIP1559V2, supportsEIP1559V2,
@ -177,13 +183,23 @@ export default class ConfirmPageContainer extends Component {
</ConfirmPageContainerHeader> </ConfirmPageContainerHeader>
<div> <div>
{showAddToAddressDialog && ( {showAddToAddressDialog && (
<Dialog <>
type="message" <Dialog
className="send__dialog" type="message"
onClick={() => showAddToAddressBookModal()} className="send__dialog"
> onClick={() => this.setState({ showNicknamePopovers: true })}
{this.context.t('newAccountDetectedDialogMessage')} >
</Dialog> {this.context.t('newAccountDetectedDialogMessage')}
</Dialog>
{this.state.showNicknamePopovers ? (
<NicknamePopovers
onClose={() =>
this.setState({ showNicknamePopovers: false })
}
address={toAddress}
/>
) : null}
</>
)} )}
</div> </div>
{contentComponent || ( {contentComponent || (
@ -195,6 +211,7 @@ export default class ConfirmPageContainer extends Component {
hideSubtitle={hideSubtitle} hideSubtitle={hideSubtitle}
detailsComponent={detailsComponent} detailsComponent={detailsComponent}
dataComponent={dataComponent} dataComponent={dataComponent}
dataHexComponent={dataHexComponent}
errorMessage={errorMessage} errorMessage={errorMessage}
errorKey={errorKey} errorKey={errorKey}
identiconAddress={identiconAddress} identiconAddress={identiconAddress}

View File

@ -1,6 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { getAccountsWithLabels, getAddressBookEntry } from '../../../selectors'; import { getAccountsWithLabels, getAddressBookEntry } from '../../../selectors';
import * as actions from '../../../store/actions';
import ConfirmPageContainer from './confirm-page-container.component'; import ConfirmPageContainer from './confirm-page-container.component';
function mapStateToProps(state, ownProps) { function mapStateToProps(state, ownProps) {
@ -17,30 +16,4 @@ function mapStateToProps(state, ownProps) {
}; };
} }
function mapDispatchToProps(dispatch) { export default connect(mapStateToProps)(ConfirmPageContainer);
return {
showAddToAddressBookModal: (recipient) =>
dispatch(
actions.showModal({
name: 'ADD_TO_ADDRESSBOOK',
recipient,
}),
),
};
}
function mergeProps(stateProps, dispatchProps, ownProps) {
const { to, ...restStateProps } = stateProps;
return {
...ownProps,
...restStateProps,
showAddToAddressBookModal: () =>
dispatchProps.showAddToAddressBookModal(to),
};
}
export default connect(
mapStateToProps,
mapDispatchToProps,
mergeProps,
)(ConfirmPageContainer);

View File

@ -0,0 +1 @@
export { default } from './nickname-popovers.component';

View File

@ -0,0 +1,72 @@
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import { getAccountLink } from '@metamask/etherscan-link';
import { addToAddressBook } from '../../../../store/actions';
import {
getRpcPrefsForCurrentProvider,
getCurrentChainId,
getAddressBook,
} from '../../../../selectors';
import NicknamePopover from '../../../ui/nickname-popover';
import UpdateNicknamePopover from '../../../ui/update-nickname-popover/update-nickname-popover';
const SHOW_NICKNAME_POPOVER = 'SHOW_NICKNAME_POPOVER';
const ADD_NICKNAME_POPOVER = 'ADD_NICKNAME_POPOVER';
const NicknamePopovers = ({ address, onClose }) => {
const dispatch = useDispatch();
const [popoverToDisplay, setPopoverToDisplay] = useState(
SHOW_NICKNAME_POPOVER,
);
const addressBook = useSelector(getAddressBook);
const chainId = useSelector(getCurrentChainId);
const addressBookEntryObject = addressBook.find(
(entry) => entry.address === address,
);
const recipientNickname = addressBookEntryObject?.name;
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider);
const explorerLink = getAccountLink(
address,
chainId,
{ blockExplorerUrl: rpcPrefs?.blockExplorerUrl ?? null },
null,
);
if (popoverToDisplay === ADD_NICKNAME_POPOVER) {
return (
<UpdateNicknamePopover
address={address}
nickname={recipientNickname || null}
memo={addressBookEntryObject?.memo}
onClose={() => setPopoverToDisplay(SHOW_NICKNAME_POPOVER)}
onAdd={(recipient, nickname, memo) =>
dispatch(addToAddressBook(recipient, nickname, memo))
}
/>
);
}
// SHOW_NICKNAME_POPOVER case
return (
<NicknamePopover
address={address}
nickname={recipientNickname || null}
onClose={onClose}
onAdd={() => setPopoverToDisplay(ADD_NICKNAME_POPOVER)}
explorerLink={explorerLink}
/>
);
};
NicknamePopovers.propTypes = {
address: PropTypes.string,
onClose: PropTypes.func,
};
export default NicknamePopovers;

View File

@ -2,8 +2,11 @@
.transaction-breakdown { .transaction-breakdown {
&__title { &__title {
border-bottom: 1px solid #d8d8d8;
padding-bottom: 4px; padding-bottom: 4px;
padding-top: 8px;
font-size: 14px;
color: $Black-100;
font-weight: bold;
text-transform: capitalize; text-transform: capitalize;
} }
@ -15,12 +18,17 @@
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
text-align: end; text-align: end;
white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
&--eth-total { &--eth-total {
font-weight: 500; font-weight: bold;
color: $Black-100;
}
&--amount {
font-weight: bold;
color: $Black-100;
} }
} }
} }

View File

@ -1,20 +1,22 @@
.transaction-breakdown-row { .transaction-breakdown-row {
@include H7; @include H7;
color: $scorpion; color: $Grey-500;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
padding: 8px 0; padding: 8px 0;
&:not(:last-child) { &--with-bottom-border {
border-bottom: 1px solid #d8d8d8; border-bottom: 1px solid #d8d8d8;
} }
&__title { &__title {
padding-right: 8px; padding-right: 8px;
min-width: 40%;
} }
&__value { &__value {
min-width: 0; min-width: 0;
word-break: break-word;
} }
} }

View File

@ -7,14 +7,19 @@ export default class TransactionBreakdownRow extends PureComponent {
title: PropTypes.string, title: PropTypes.string,
children: PropTypes.node, children: PropTypes.node,
className: PropTypes.string, className: PropTypes.string,
divider: PropTypes.bool,
}; };
render() { render() {
const { title, children, className } = this.props; const { title, children, className, divider = false } = this.props;
return ( return (
<div <div
className={classnames('transaction-breakdown-row', className)} className={classnames(
'transaction-breakdown-row',
divider ? 'transaction-breakdown-row--with-bottom-border' : '',
className,
)}
data-testid="transaction-breakdown-row" data-testid="transaction-breakdown-row"
> >
<div <div

View File

@ -65,7 +65,7 @@ export default class TransactionBreakdown extends PureComponent {
return ( return (
<div className={classnames('transaction-breakdown', className)}> <div className={classnames('transaction-breakdown', className)}>
<div className="transaction-breakdown__title">{t('transaction')}</div> <div className="transaction-breakdown__title">{t('transaction')}</div>
<TransactionBreakdownRow title={t('nonce')}> <TransactionBreakdownRow divider title={t('nonce')}>
{typeof nonce === 'undefined' ? null : ( {typeof nonce === 'undefined' ? null : (
<HexToDecimal <HexToDecimal
className="transaction-breakdown__value" className="transaction-breakdown__value"
@ -76,7 +76,7 @@ export default class TransactionBreakdown extends PureComponent {
<TransactionBreakdownRow <TransactionBreakdownRow
title={isTokenApprove ? t('spendLimitAmount') : t('amount')} title={isTokenApprove ? t('spendLimitAmount') : t('amount')}
> >
<span className="transaction-breakdown__value"> <span className="transaction-breakdown__value transaction-breakdown__value--amount">
{primaryCurrency} {primaryCurrency}
</span> </span>
</TransactionBreakdownRow> </TransactionBreakdownRow>
@ -178,7 +178,10 @@ export default class TransactionBreakdown extends PureComponent {
</TransactionBreakdownRow> </TransactionBreakdownRow>
)} )}
{isEIP1559Transaction && ( {isEIP1559Transaction && (
<TransactionBreakdownRow title={t('transactionHistoryMaxFeePerGas')}> <TransactionBreakdownRow
divider
title={t('transactionHistoryMaxFeePerGas')}
>
<UserPreferencedCurrencyDisplay <UserPreferencedCurrencyDisplay
className="transaction-breakdown__value" className="transaction-breakdown__value"
currency={nativeCurrency} currency={nativeCurrency}

View File

@ -0,0 +1,71 @@
import React, { useState } from 'react';
import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import copyToClipboard from 'copy-to-clipboard';
import { shortenAddress } from '../../../../../../helpers/utils/util';
import Identicon from '../../../../../ui/identicon';
import { useI18nContext } from '../../../../../../hooks/useI18nContext';
import { getAddressBook } from '../../../../../../selectors';
import NicknamePopovers from '../../../../modals/nickname-popovers';
const Address = ({
checksummedRecipientAddress,
onRecipientClick,
addressOnly,
recipientEns,
recipientName,
}) => {
const t = useI18nContext();
const [showNicknamePopovers, setShowNicknamePopovers] = useState(false);
const addressBook = useSelector(getAddressBook);
const addressBookEntryObject = addressBook.find(
(entry) => entry.address === checksummedRecipientAddress,
);
const recipientNickname = addressBookEntryObject?.name;
const recipientToRender = addressOnly
? recipientNickname ||
recipientEns ||
shortenAddress(checksummedRecipientAddress)
: recipientNickname || recipientEns || recipientName || t('newContract');
return (
<div
className="tx-insight tx-insight-component tx-insight-component-address"
onClick={() => {
copyToClipboard(checksummedRecipientAddress);
if (onRecipientClick) {
onRecipientClick();
}
}}
>
<div className="tx-insight-component-address__sender-icon">
<Identicon address={checksummedRecipientAddress} diameter={18} />
</div>
<div
className="address__name"
onClick={() => setShowNicknamePopovers(true)}
>
{recipientToRender}
</div>
{showNicknamePopovers ? (
<NicknamePopovers
onClose={() => setShowNicknamePopovers(false)}
address={checksummedRecipientAddress}
/>
) : null}
</div>
);
};
Address.propTypes = {
checksummedRecipientAddress: PropTypes.string,
recipientName: PropTypes.string,
recipientEns: PropTypes.string,
addressOnly: PropTypes.bool,
onRecipientClick: PropTypes.func,
};
export default Address;

View File

@ -0,0 +1 @@
export { default } from './address.component';

View File

@ -0,0 +1,12 @@
.tx-insight-content {
.tx-insight-component-address {
display: flex;
align-items: center;
cursor: pointer;
overflow: visible;
&__sender-icon {
padding-right: 5px;
}
}
}

View File

@ -0,0 +1,38 @@
import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import Tooltip from '../../../../../ui/tooltip/tooltip';
import CopyIcon from '../../../../../ui/icon/copy-icon.component';
import { I18nContext } from '../../../../../../contexts/i18n';
import { useCopyToClipboard } from '../../../../../../hooks/useCopyToClipboard';
const CopyRawData = ({ data }) => {
const t = useContext(I18nContext);
const [copied, handleCopy] = useCopyToClipboard();
return (
<div className="copy-raw-data">
<Tooltip position="right" title={copied ? t('copiedExclamation') : ''}>
<button
onClick={() => {
handleCopy(data);
}}
className="copy-raw-data__button"
>
<div className="copy-raw-data__icon">
<CopyIcon size={12} color="#BBC0C5" />
</div>
<div className="copy-raw-data__label">
{t('copyRawTransactionData')}
</div>
</button>
</Tooltip>
</div>
);
};
CopyRawData.propTypes = {
data: PropTypes.string.isRequired,
};
export default CopyRawData;

View File

@ -0,0 +1 @@
export { default } from './copy-raw-data.component';

View File

@ -0,0 +1,30 @@
.copy-raw-data {
display: flex;
align-items: center;
&__button {
border-radius: 20px;
display: flex;
align-items: center;
justify-content: center;
padding: 8px;
margin-top: 5px;
background-color: transparent;
&:hover {
background-color: $Grey-000;
}
&:active {
background-color: #ededed;
}
}
&__icon {
padding-inline-end: 6px;
}
&__label {
color: #6a737d;
}
}

View File

@ -0,0 +1,5 @@
const TX_INSIGHTS_BASE_URI =
'https://tx-insights-api.metaswap-dev.codefi.network';
export const FETCH_PROJECT_INFO_URI = `${TX_INSIGHTS_BASE_URI}/fetch-project`;
export const FETCH_SUPPORTED_NETWORKS_URI = `${TX_INSIGHTS_BASE_URI}/networks`;

View File

@ -0,0 +1 @@
export { default } from './transaction-decoding.component';

View File

@ -0,0 +1,169 @@
//styling for ui components
@import './components/ui/copy-raw-data/index';
//styling for decoding components
@import './components/decoding/address/index';
.tx-insight {
overflow-x: hidden;
&-loading {
display: flex;
justify-content: center;
align-items: center;
min-height: 100px;
.spinner {
width: 30px;
}
}
& > details {
margin: 20px 0;
}
& > details > summary {
&.tx-insight-title {
font-size: 14px;
position: relative;
margin: 12px 0 4px;
padding-inline-start: 22px;
cursor: pointer;
& + .tx-insight-content {
padding-inline-start: 14px;
padding-top: 5px;
}
}
}
.tx-insight-content {
&__tree-component {
line-height: 175%;
& > ol {
padding-left: 0;
}
.eth-tx-params {
padding: 8px;
width: 343px;
background: white;
text-align: left;
display: flex;
flex-direction: column;
align-items: left;
font-family: Euclid Circular B, sans-serif;
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 172%;
}
ol ol {
padding-left: 22px;
margin-left: 4px;
}
details > summary {
position: relative;
cursor: pointer;
padding-bottom: 5px;
}
.eth-tx-params .solidity-func-name {
width: fit-content;
padding: 4px;
text-transform: uppercase;
border: 1px solid rgb(149, 149, 149);
color: rgb(149, 149, 149);
border-radius: 4px;
}
.eth-tx-params .sol-value {
display: flex;
flex-flow: row wrap;
}
.eth-tx-params .sol-value > {
overflow: ellipses;
}
.eth-tx-params ol {
list-style: none;
padding: 0;
max-width: inherit;
}
.eth-tx-params > ol {
margin-left: 16px;
}
/*
Use this parameter to change the indentation!! */
.eth-tx-params ol ol:not(:first-child) {
padding-left: 8px;
}
pre.solidity-raw {
text-align: left;
}
.solidity-address {
display: flex;
flex-direction: row;
}
.solidity-address :first-child {
width: 16px;
height: 16px;
margin: 0 8px;
}
.solidity-item .param-name {
padding-right: 4px;
}
.solidity-value {
color: #6a737d;
overflow-x: hidden;
padding-bottom: 5px;
& > div {
display: flex;
flex-wrap: wrap;
word-break: break-all;
}
}
.solidity-error {
display: flex;
align-items: center;
& > .error-message__icon {
width: 14px;
margin-right: 5px;
}
}
.eth-tx-params details > summary {
color: black;
font-family: sans-serif;
}
.eth-tx-params footer {
text-align: center;
color: #8d959e;
}
.eth-tx-params footer a {
text-align: center;
color: #8d959e;
}
}
}
}

View File

@ -0,0 +1,219 @@
import React, { useContext, useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import inspect from 'browser-util-inspect';
import { forAddress } from '@truffle/decoder';
import { useSelector } from 'react-redux';
import * as Codec from '@truffle/codec';
import Spinner from '../../ui/spinner';
import ErrorMessage from '../../ui/error-message';
import fetchWithCache from '../../../helpers/utils/fetch-with-cache';
import { getSelectedAccount, getCurrentChainId } from '../../../selectors';
import { hexToDecimal } from '../../../helpers/utils/conversions.util';
import { I18nContext } from '../../../contexts/i18n';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import { transformTxDecoding } from './transaction-decoding.util';
import {
FETCH_PROJECT_INFO_URI,
FETCH_SUPPORTED_NETWORKS_URI,
} from './constants';
import Address from './components/decoding/address';
import CopyRawData from './components/ui/copy-raw-data';
export default function TransactionDecoding({ to = '', inputData: data = '' }) {
const t = useContext(I18nContext);
const [tx, setTx] = useState([]);
const { address: from } = useSelector(getSelectedAccount);
const network = hexToDecimal(useSelector(getCurrentChainId));
const [loading, setLoading] = useState(false);
const [hasError, setError] = useState(false);
const [errorMessage, setErrorMessage] = useState('');
useEffect(() => {
(async () => {
setLoading(true);
try {
const networks = await fetchWithCache(FETCH_SUPPORTED_NETWORKS_URI, {
method: 'GET',
});
if (
!networks.some(
(n) => n.active && Number(n.chainId) === Number(network),
)
) {
throw new Error(
t('transactionDecodingUnsupportedNetworkError', [network]),
);
}
const requestUrl = `${FETCH_PROJECT_INFO_URI}?${new URLSearchParams({
to,
'network-id': network,
})}`;
const response = await fetchWithCache(requestUrl, { method: 'GET' });
const { info: projectInfo } = response;
// creating instance of the truffle decoder
const decoder = await forAddress(to, {
provider: global.ethereumProvider,
projectInfo,
});
// decode tx input data
const decoding = await decoder.decodeTransaction({
from,
to,
input: data,
blockNumber: null,
});
// transform tx decoding arguments into tree data
const params = transformTxDecoding(decoding?.arguments);
setTx(params);
setLoading(false);
} catch (error) {
setLoading(false);
setError(true);
setErrorMessage(error?.message);
}
})();
}, [t, from, to, network, data]);
// ***********************************************************
// component rendering methods
// ***********************************************************
const renderLeaf = ({ name, kind, typeClass, value }) => {
switch (kind) {
case 'error':
return (
<span className="sol-item solidity-error">
<span>Malformed data</span>
</span>
);
default:
switch (typeClass) {
case 'int':
return (
<span className="sol-item solidity-int">
{[value.asBN || value.asString].toString()}
</span>
);
case 'uint':
return (
<span className="sol-item solidity-uint">
{[value.asBN || value.asString].toString()}
</span>
);
case 'bytes':
return (
<span className="sol-item solidity-bytes">{value.asHex}</span>
);
case 'array':
return (
<details>
<summary className="typography--color-black">{name}: </summary>
<ol>
{value.map((itemValue, index) => {
return (
<li key={`${itemValue.type?.typeClass}-${index}`}>
{renderLeaf({
typeClass: itemValue.type?.typeClass,
value: itemValue.value,
kind: itemValue.kind,
})}
</li>
);
})}
</ol>
</details>
);
case 'address': {
const address = value?.asAddress;
return (
<Address
addressOnly
checksummedRecipientAddress={toChecksumHexAddress(address)}
/>
);
}
default:
return (
<pre className="sol-item solidity-raw">
{inspect(new Codec.Format.Utils.Inspect.ResultInspector(value))}
</pre>
);
}
}
};
const renderTree = (
{ name, kind, typeClass, type, value, children },
index,
) => {
return children ? (
<li key={`${typeClass}-${index}`}>
<details open={index === 0 ? 'open' : ''}>
<summary>{name}: </summary>
<ol>{children.map(renderTree)}</ol>
</details>
</li>
) : (
<li className="solidity-value">
<div className="solidity-named-item solidity-item">
{typeClass !== 'array' && !Array.isArray(value) ? (
<span className="param-name typography--color-black">{name}: </span>
) : null}
<span className="sol-item solidity-uint">
{renderLeaf({ name, typeClass, type, value, kind })}
</span>
</div>
</li>
);
};
const renderTransactionDecoding = () => {
if (loading) {
return (
<div className="tx-insight-loading">
<Spinner color="#F7C06C" />
</div>
);
}
if (hasError) {
return (
<div className="tx-insight-error">
<ErrorMessage errorMessage={errorMessage} />
</div>
);
}
return (
<div className="tx-insight-content">
<div className="tx-insight-content__tree-component">
<ol>{tx.map(renderTree)}</ol>
</div>
<div className="tx-insight-content__copy-raw-tx">
<CopyRawData data={data} />
</div>
</div>
);
};
return <div className="tx-insight">{renderTransactionDecoding()}</div>;
}
TransactionDecoding.propTypes = {
to: PropTypes.string.isRequired,
inputData: PropTypes.string.isRequired,
};

View File

@ -0,0 +1,30 @@
// *********************************************
// data transformation utils
// *********************************************
export const transformTxDecoding = (params) => {
return params.map((node) => {
const nodeName = node.name;
const nodeValue = node.value;
const nodeKind = nodeValue.kind;
const nodeTypeClass = nodeValue.type.typeClass;
const treeItem = {
name: nodeName,
kind: nodeKind,
typeClass: nodeTypeClass,
type: nodeValue.type,
};
if (nodeTypeClass === 'struct') {
return {
...treeItem,
children: transformTxDecoding(nodeValue.value),
};
}
return {
...treeItem,
value: nodeValue.value ? nodeValue.value : nodeValue,
};
});
};

View File

@ -1,11 +1,82 @@
.transaction-list-item-details { .transaction-list-item-details {
div.disclosure + div.disclosure {
margin-top: 0;
}
.sender-to-recipient--flat .sender-to-recipient__party.sender-to-recipient__party--sender {
padding: 0;
justify-content: flex-start;
}
.sender-to-recipient--flat .sender-to-recipient__party.sender-to-recipient__party--recipient {
padding: 0;
justify-content: flex-end;
}
&__sender-to-recipient-header {
display: flex;
font-size: 14px;
color: $Black-100;
font-weight: bold;
padding-bottom: 7px;
& > div:first-child {
flex: 1;
}
}
&__tx-status {
display: flex;
flex-direction: column;
align-items: flex-start;
height: 44px;
justify-content: space-between;
& > div:first-child {
font-size: 14px;
color: $Black-100;
font-weight: bold;
}
& > div:last-child {
font-weight: bold;
}
}
&__tx-hash {
display: flex;
flex-direction: column;
align-items: flex-end;
.btn-link {
font-size: 12px;
line-height: 100%;
padding: 0;
}
& > div:first-child {
padding-bottom: 16px;
}
}
&__operations {
margin: 0 0 16px 16px;
display: flex;
justify-content: end;
}
&__header { &__header {
font-size: 12px;
margin: 8px 16px; margin: 8px 16px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
} }
&__body {
padding: 8px 16px;
}
&__header-buttons { &__header-buttons {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -31,12 +102,25 @@
&__sender-to-recipient-container { &__sender-to-recipient-container {
margin-bottom: 8px; margin-bottom: 8px;
.sender-to-recipient {
.sender-to-recipient__party {
border: none;
&--sender {
padding-left: 0;
}
&--recipient {
padding-right: 0;
}
}
}
} }
&__cards-container { &__cards-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 8px 16px;
} }
&__transaction-breakdown { &__transaction-breakdown {
@ -49,5 +133,13 @@
&__transaction-activity-log { &__transaction-activity-log {
flex: 2; flex: 2;
min-width: 0; min-width: 0;
.transaction-activity-log__activities-container {
padding-top: 0;
}
.transaction-activity-log__title {
display: none;
}
} }
} }

View File

@ -4,16 +4,17 @@ import copyToClipboard from 'copy-to-clipboard';
import { getBlockExplorerLink } from '@metamask/etherscan-link'; import { getBlockExplorerLink } from '@metamask/etherscan-link';
import SenderToRecipient from '../../ui/sender-to-recipient'; import SenderToRecipient from '../../ui/sender-to-recipient';
import { DEFAULT_VARIANT } from '../../ui/sender-to-recipient/sender-to-recipient.constants'; import { DEFAULT_VARIANT } from '../../ui/sender-to-recipient/sender-to-recipient.constants';
import Disclosure from '../../ui/disclosure';
import TransactionActivityLog from '../transaction-activity-log'; import TransactionActivityLog from '../transaction-activity-log';
import TransactionBreakdown from '../transaction-breakdown'; import TransactionBreakdown from '../transaction-breakdown';
import Button from '../../ui/button'; import Button from '../../ui/button';
import Tooltip from '../../ui/tooltip'; import Tooltip from '../../ui/tooltip';
import Copy from '../../ui/icon/copy-icon.component';
import CancelButton from '../cancel-button'; import CancelButton from '../cancel-button';
import Popover from '../../ui/popover'; import Popover from '../../ui/popover';
import { SECOND } from '../../../../shared/constants/time'; import { SECOND } from '../../../../shared/constants/time';
import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction'; import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction';
import { getURLHostName } from '../../../helpers/utils/util'; import { getURLHostName } from '../../../helpers/utils/util';
import TransactionDecoding from '../transaction-decoding';
export default class TransactionListItemDetails extends PureComponent { export default class TransactionListItemDetails extends PureComponent {
static contextTypes = { static contextTypes = {
@ -44,6 +45,7 @@ export default class TransactionListItemDetails extends PureComponent {
tryReverseResolveAddress: PropTypes.func.isRequired, tryReverseResolveAddress: PropTypes.func.isRequired,
senderNickname: PropTypes.string.isRequired, senderNickname: PropTypes.string.isRequired,
recipientNickname: PropTypes.string, recipientNickname: PropTypes.string,
transactionStatus: PropTypes.func,
}; };
state = { state = {
@ -124,7 +126,6 @@ export default class TransactionListItemDetails extends PureComponent {
showRetry, showRetry,
recipientEns, recipientEns,
recipientAddress, recipientAddress,
rpcPrefs: { blockExplorerUrl } = {},
senderAddress, senderAddress,
isEarliestNonce, isEarliestNonce,
senderNickname, senderNickname,
@ -132,6 +133,7 @@ export default class TransactionListItemDetails extends PureComponent {
onClose, onClose,
recipientNickname, recipientNickname,
showCancel, showCancel,
transactionStatus: TransactionStatus,
} = this.props; } = this.props;
const { const {
primaryTransaction: transaction, primaryTransaction: transaction,
@ -142,8 +144,7 @@ export default class TransactionListItemDetails extends PureComponent {
return ( return (
<Popover title={title} onClose={onClose}> <Popover title={title} onClose={onClose}>
<div className="transaction-list-item-details"> <div className="transaction-list-item-details">
<div className="transaction-list-item-details__header"> <div className="transaction-list-item-details__operations">
<div>{t('details')}</div>
<div className="transaction-list-item-details__header-buttons"> <div className="transaction-list-item-details__header-buttons">
{showSpeedUp && ( {showSpeedUp && (
<Button <Button
@ -161,43 +162,6 @@ export default class TransactionListItemDetails extends PureComponent {
detailsModal detailsModal
/> />
)} )}
<Tooltip
wrapperClassName="transaction-list-item-details__header-button"
containerClassName="transaction-list-item-details__header-button-tooltip-container"
title={
justCopied ? t('copiedTransactionId') : t('copyTransactionId')
}
>
<Button
type="raised"
onClick={this.handleCopyTxId}
disabled={!hash}
>
<Copy size={10} color="#3098DC" />
</Button>
</Tooltip>
<Tooltip
wrapperClassName="transaction-list-item-details__header-button"
containerClassName="transaction-list-item-details__header-button-tooltip-container"
title={
blockExplorerUrl
? t('viewOnCustomBlockExplorer', [
t('blockExplorerTransactionAction'),
blockExplorerUrl,
])
: t('viewOnEtherscan', [
t('blockExplorerTransactionAction'),
])
}
>
<Button
type="raised"
onClick={this.handleBlockExplorerClick}
disabled={!hash}
>
<img src="./images/arrow-popout.svg" alt="" />
</Button>
</Tooltip>
{showRetry && ( {showRetry && (
<Tooltip title={t('retryTransaction')}> <Tooltip title={t('retryTransaction')}>
<Button <Button
@ -211,7 +175,45 @@ export default class TransactionListItemDetails extends PureComponent {
)} )}
</div> </div>
</div> </div>
<div className="transaction-list-item-details__header">
<div className="transaction-list-item-details__tx-status">
<div>Status</div>
<div>
<TransactionStatus />
</div>
</div>
<div className="transaction-list-item-details__tx-hash">
<div>
<Button
type="link"
onClick={this.handleBlockExplorerClick}
disabled={!hash}
>
{t('viewOnBlockExplorer')}
</Button>
</div>
<div>
<Tooltip
wrapperClassName="transaction-list-item-details__header-button"
containerClassName="transaction-list-item-details__header-button-tooltip-container"
title={justCopied ? t('copiedExclamation') : null}
>
<Button
type="link"
onClick={this.handleCopyTxId}
disabled={!hash}
>
{t('copyTransactionId')}
</Button>
</Tooltip>
</div>
</div>
</div>
<div className="transaction-list-item-details__body"> <div className="transaction-list-item-details__body">
<div className="transaction-list-item-details__sender-to-recipient-header">
<div>{t('from')}</div>
<div>{t('to')}</div>
</div>
<div className="transaction-list-item-details__sender-to-recipient-container"> <div className="transaction-list-item-details__sender-to-recipient-container">
<SenderToRecipient <SenderToRecipient
warnUserOnAccountMismatch={false} warnUserOnAccountMismatch={false}
@ -250,13 +252,26 @@ export default class TransactionListItemDetails extends PureComponent {
primaryCurrency={primaryCurrency} primaryCurrency={primaryCurrency}
className="transaction-list-item-details__transaction-breakdown" className="transaction-list-item-details__transaction-breakdown"
/> />
<TransactionActivityLog <Disclosure title="Activity log" size="small">
transactionGroup={transactionGroup} <TransactionActivityLog
className="transaction-list-item-details__transaction-activity-log" transactionGroup={transactionGroup}
onCancel={this.handleCancel} className="transaction-list-item-details__transaction-activity-log"
onRetry={this.handleRetry} onCancel={this.handleCancel}
isEarliestNonce={isEarliestNonce} onRetry={this.handleRetry}
/> isEarliestNonce={isEarliestNonce}
/>
</Disclosure>
{transactionGroup.initialTransaction?.txParams?.data ? (
<Disclosure title="Transaction data" size="small">
<TransactionDecoding
title={t('transactionData')}
to={transactionGroup.initialTransaction.txParams?.to}
inputData={
transactionGroup.initialTransaction.txParams?.data
}
/>
</Disclosure>
) : null}
</div> </div>
</div> </div>
</div> </div>

View File

@ -212,6 +212,16 @@ export default function TransactionListItem({
isEarliestNonce={isEarliestNonce} isEarliestNonce={isEarliestNonce}
onCancel={cancelTransaction} onCancel={cancelTransaction}
showCancel={isPending && !hasCancelled} showCancel={isPending && !hasCancelled}
transactionStatus={() => (
<TransactionStatus
isPending={isPending}
isEarliestNonce={isEarliestNonce}
error={err}
date={date}
status={displayedStatusKey}
statusOnly
/>
)}
/> />
)} )}
{showRetryEditGasPopover && ( {showRetryEditGasPopover && (

View File

@ -1,6 +1,10 @@
.transaction-status { .transaction-status {
display: inline; display: inline;
&--confirmed {
color: $success-3;
}
&--unapproved { &--unapproved {
color: $Orange-500; color: $Orange-500;
} }

View File

@ -43,6 +43,7 @@ export default function TransactionStatus({
error, error,
isEarliestNonce, isEarliestNonce,
className, className,
statusOnly,
}) { }) {
const t = useI18nContext(); const t = useI18nContext();
const tooltipText = error?.rpc?.message || error?.message; const tooltipText = error?.rpc?.message || error?.message;
@ -54,7 +55,9 @@ export default function TransactionStatus({
} }
const statusText = const statusText =
statusKey === TRANSACTION_STATUSES.CONFIRMED ? date : t(statusKey); statusKey === TRANSACTION_STATUSES.CONFIRMED && !statusOnly
? date
: t(statusKey);
return ( return (
<Tooltip <Tooltip
@ -62,6 +65,7 @@ export default function TransactionStatus({
title={tooltipText} title={tooltipText}
wrapperClassName={classnames( wrapperClassName={classnames(
'transaction-status', 'transaction-status',
`transaction-status--${statusKey}`,
className, className,
statusToClassNameHash[statusKey], statusToClassNameHash[statusKey],
)} )}
@ -77,4 +81,5 @@ TransactionStatus.propTypes = {
date: PropTypes.string, date: PropTypes.string,
error: PropTypes.object, error: PropTypes.object,
isEarliestNonce: PropTypes.bool, isEarliestNonce: PropTypes.bool,
statusOnly: PropTypes.bool,
}; };

View File

@ -0,0 +1,51 @@
import React, { useState, useRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
const Disclosure = ({ children, title, size }) => {
const disclosureFooterEl = useRef(null);
const [open, setOpen] = useState(false);
const scrollToBottom = () => {
disclosureFooterEl &&
disclosureFooterEl.current &&
disclosureFooterEl.current.scrollIntoView({ behavior: 'smooth' });
};
useEffect(() => {
if (open) {
scrollToBottom();
}
}, [open]);
return (
<div className="disclosure" onClick={() => setOpen((state) => !state)}>
{title ? (
<details>
<summary className="disclosure__title disclosure__summary typography--weight-bold typography--color-black">
{title}:{' '}
</summary>
<div className={classnames('disclosure__content', size)}>
{children}
</div>
<div ref={disclosureFooterEl} className="disclosure__footer"></div>
</details>
) : (
children
)}
</div>
);
};
Disclosure.propTypes = {
children: PropTypes.node.isRequired,
title: PropTypes.string,
size: PropTypes.string,
};
Disclosure.defaultProps = {
size: 'normal',
title: null,
};
export default Disclosure;

View File

@ -0,0 +1,46 @@
.disclosure {
margin: 12px 0;
cursor: pointer;
font-size: 14px;
& > details[open] > summary {
&::before {
background-image: url("images/icons/collapse.svg");
}
}
&__summary {
position: relative;
padding-left: 24px;
padding-bottom: 10px;
&::-webkit-details-marker,
&::marker {
display: none;
content: "";
}
&::before {
position: absolute;
content: " ";
flex: 0 0 auto;
height: 16px;
width: 16px;
background-image: url("images/icons/expand.svg");
background-size: contain;
background-repeat: no-repeat;
cursor: pointer;
left: 0;
top: 2px;
}
}
&__content {
margin-left: 12px;
font-size: 14px;
&.small {
font-size: 12px;
}
}
}

View File

@ -0,0 +1 @@
export { default } from './disclosure';

View File

@ -1,10 +1,11 @@
.nickname-popover { .nickname-popover {
&__popover-wrap { &__popover-wrap {
height: 232px; height: 232px;
border-radius: 8px; border-radius: 4px;
background: $ui-white; background: $ui-white;
display: flex; display: flex;
justify-content: center; justify-content: center;
width: auto;
.popover-header { .popover-header {
padding: 16px 16px 0 0; padding: 16px 16px 0 0;
@ -57,6 +58,12 @@
margin-top: 12px; margin-top: 12px;
} }
&__etherscan-link {
@include H7;
padding: 0;
}
&__footer-button { &__footer-button {
margin-top: 16px; margin-top: 16px;
width: 152px; width: 152px;

View File

@ -1,6 +1,7 @@
import React, { useCallback, useContext } from 'react'; import React, { useCallback, useContext } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { I18nContext } from '../../../contexts/i18n'; import { I18nContext } from '../../../contexts/i18n';
import Tooltip from '../tooltip';
import Popover from '../popover'; import Popover from '../popover';
import Button from '../button'; import Button from '../button';
import Identicon from '../identicon/identicon.component'; import Identicon from '../identicon/identicon.component';
@ -8,13 +9,18 @@ import { shortenAddress } from '../../../helpers/utils/util';
import CopyIcon from '../icon/copy-icon.component'; import CopyIcon from '../icon/copy-icon.component';
import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard'; import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard';
const NicknamePopover = ({ address, onClose = null, onAdd = null }) => { const NicknamePopover = ({
address,
nickname,
onClose = null,
onAdd = null,
explorerLink,
}) => {
const t = useContext(I18nContext); const t = useContext(I18nContext);
const onAddClick = useCallback(() => { const onAddClick = useCallback(() => {
onAdd(address); onAdd();
onClose(); }, [onAdd]);
}, [address, onClose, onAdd]);
const [copied, handleCopy] = useCopyToClipboard(); const [copied, handleCopy] = useCopyToClipboard();
@ -27,31 +33,51 @@ const NicknamePopover = ({ address, onClose = null, onAdd = null }) => {
className="nickname-popover__identicon" className="nickname-popover__identicon"
/> />
<div className="nickname-popover__address"> <div className="nickname-popover__address">
{shortenAddress(address)} {nickname || shortenAddress(address)}
</div> </div>
<div className="nickname-popover__public-address"> <div className="nickname-popover__public-address">
<div className="nickname-popover__public-address__constant"> <div className="nickname-popover__public-address__constant">
{address} {address}
</div> </div>
<button
type="link" <Tooltip
onClick={() => { position="bottom"
handleCopy(address);
}}
title={copied ? t('copiedExclamation') : t('copyToClipboard')} title={copied ? t('copiedExclamation') : t('copyToClipboard')}
> >
<CopyIcon size={11} color="#989a9b" /> <button
</button> type="link"
onClick={() => {
handleCopy(address);
}}
title=""
>
<CopyIcon size={11} color="#989a9b" />
</button>
</Tooltip>
</div> </div>
<div className="nickname-popover__view-on-block-explorer"> <div className="nickname-popover__view-on-block-explorer">
{t('viewOnBlockExplorer')} <Button
type="link"
className="nickname-popover__etherscan-link"
onClick={() => {
global.platform.openTab({
url: explorerLink,
});
}}
target="_blank"
rel="noopener noreferrer"
title={t('etherscanView')}
>
{t('viewOnBlockExplorer')}
</Button>
</div> </div>
<Button <Button
type="primary" type="primary"
className="nickname-popover__footer-button" className="nickname-popover__footer-button"
onClick={onAddClick} onClick={onAddClick}
> >
{t('addANickname')} {nickname ? t('editANickname') : t('addANickname')}
</Button> </Button>
</Popover> </Popover>
</div> </div>
@ -60,8 +86,10 @@ const NicknamePopover = ({ address, onClose = null, onAdd = null }) => {
NicknamePopover.propTypes = { NicknamePopover.propTypes = {
address: PropTypes.string, address: PropTypes.string,
nickname: PropTypes.string,
onClose: PropTypes.func, onClose: PropTypes.func,
onAdd: PropTypes.func, onAdd: PropTypes.func,
explorerLink: PropTypes.string,
}; };
export default NicknamePopover; export default NicknamePopover;

View File

@ -8,6 +8,7 @@ import { shortenAddress } from '../../../helpers/utils/util';
import AccountMismatchWarning from '../account-mismatch-warning/account-mismatch-warning.component'; import AccountMismatchWarning from '../account-mismatch-warning/account-mismatch-warning.component';
import { useI18nContext } from '../../../hooks/useI18nContext'; import { useI18nContext } from '../../../hooks/useI18nContext';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import NicknamePopovers from '../../app/modals/nickname-popovers';
import { import {
DEFAULT_VARIANT, DEFAULT_VARIANT,
CARDS_VARIANT, CARDS_VARIANT,
@ -94,7 +95,7 @@ SenderAddress.propTypes = {
warnUserOnAccountMismatch: PropTypes.bool, warnUserOnAccountMismatch: PropTypes.bool,
}; };
function RecipientWithAddress({ export function RecipientWithAddress({
checksummedRecipientAddress, checksummedRecipientAddress,
onRecipientClick, onRecipientClick,
addressOnly, addressOnly,
@ -103,44 +104,22 @@ function RecipientWithAddress({
recipientName, recipientName,
}) { }) {
const t = useI18nContext(); const t = useI18nContext();
const [addressCopied, setAddressCopied] = useState(false); const [showNicknamePopovers, setShowNicknamePopovers] = useState(false);
let tooltipHtml = <p>{t('copiedExclamation')}</p>;
if (!addressCopied) {
if (addressOnly && !recipientNickname && !recipientEns) {
tooltipHtml = <p>{t('copyAddress')}</p>;
} else {
tooltipHtml = (
<p>
{shortenAddress(checksummedRecipientAddress)}
<br />
{t('copyAddress')}
</p>
);
}
}
return ( return (
<div <>
className="sender-to-recipient__party sender-to-recipient__party--recipient sender-to-recipient__party--recipient-with-address" <div
onClick={() => { className="sender-to-recipient__party sender-to-recipient__party--recipient sender-to-recipient__party--recipient-with-address"
setAddressCopied(true); onClick={() => {
copyToClipboard(checksummedRecipientAddress); setShowNicknamePopovers(true);
if (onRecipientClick) { if (onRecipientClick) {
onRecipientClick(); onRecipientClick();
} }
}} }}
>
<div className="sender-to-recipient__sender-icon">
<Identicon address={checksummedRecipientAddress} diameter={24} />
</div>
<Tooltip
position="bottom"
html={tooltipHtml}
offset={-10}
wrapperClassName="sender-to-recipient__tooltip-wrapper"
containerClassName="sender-to-recipient__tooltip-container"
onHidden={() => setAddressCopied(false)}
> >
<div className="sender-to-recipient__sender-icon">
<Identicon address={checksummedRecipientAddress} diameter={24} />
</div>
<div className="sender-to-recipient__name"> <div className="sender-to-recipient__name">
{addressOnly {addressOnly
? recipientNickname || ? recipientNickname ||
@ -151,8 +130,14 @@ function RecipientWithAddress({
recipientName || recipientName ||
t('newContract')} t('newContract')}
</div> </div>
</Tooltip> </div>
</div> {showNicknamePopovers ? (
<NicknamePopovers
onClose={() => setShowNicknamePopovers(false)}
address={checksummedRecipientAddress}
/>
) : null}
</>
); );
} }

View File

@ -55,3 +55,4 @@
@import 'unit-input/index'; @import 'unit-input/index';
@import 'url-icon/index'; @import 'url-icon/index';
@import 'update-nickname-popover/index'; @import 'update-nickname-popover/index';
@import 'disclosure/disclosure';

View File

@ -3,12 +3,19 @@
&__wrapper { &__wrapper {
height: 620px; height: 620px;
width: 360px; width: 360px;
border-radius: 0; border-radius: 10px;
max-height: 100vh;
width: auto;
.popover-header { .popover-header {
border-bottom: 1px solid #d2d8dd; border-bottom: 1px solid #d2d8dd;
margin-bottom: 16px; margin-bottom: 16px;
border-radius: 0; border-radius: 10px;
}
@media screen and (max-width: $break-small) {
width: 96%;
height: 96%;
} }
} }
@ -37,6 +44,7 @@
font-size: 13px; font-size: 13px;
color: #bbc0c5; color: #bbc0c5;
margin-bottom: 16px; margin-bottom: 16px;
overflow-wrap: break-word;
} }
&__label, &__label,

View File

@ -42,14 +42,9 @@ export default function UpdateNicknamePopover({
onClose(); onClose();
}; };
let title = t('addANickname');
if (nickname) {
title = t('editAddressNickname');
}
return ( return (
<Popover <Popover
title={title} title={nickname ? t('editAddressNickname') : t('addANickname')}
onClose={closePopover} onClose={closePopover}
className="update-nickname__wrapper" className="update-nickname__wrapper"
footer={ footer={
@ -61,7 +56,12 @@ export default function UpdateNicknamePopover({
> >
{t('cancel')} {t('cancel')}
</Button> </Button>
<Button type="primary" onClick={onSubmit} disabled={!nickname}> <Button
className="update-nickname__save"
type="primary"
onClick={onSubmit}
disabled={!nicknameInput}
>
{t('save')} {t('save')}
</Button> </Button>
</> </>

View File

@ -1,6 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ConfirmPageContainer from '../../components/app/confirm-page-container'; import ConfirmPageContainer from '../../components/app/confirm-page-container';
import TransactionDecoding from '../../components/app/transaction-decoding';
import { isBalanceSufficient } from '../send/send.utils'; import { isBalanceSufficient } from '../send/send.utils';
import { import {
addHexes, addHexes,
@ -18,9 +19,12 @@ import {
GAS_PRICE_FETCH_FAILURE_ERROR_KEY, GAS_PRICE_FETCH_FAILURE_ERROR_KEY,
} from '../../helpers/constants/error-keys'; } from '../../helpers/constants/error-keys';
import UserPreferencedCurrencyDisplay from '../../components/app/user-preferenced-currency-display'; import UserPreferencedCurrencyDisplay from '../../components/app/user-preferenced-currency-display';
import CopyRawData from '../../components/app/transaction-decoding/components/ui/copy-raw-data';
import { PRIMARY, SECONDARY } from '../../helpers/constants/common'; import { PRIMARY, SECONDARY } from '../../helpers/constants/common';
import TextField from '../../components/ui/text-field'; import TextField from '../../components/ui/text-field';
import ActionableMessage from '../../components/ui/actionable-message'; import ActionableMessage from '../../components/ui/actionable-message';
import Disclosure from '../../components/ui/disclosure';
import { import {
TRANSACTION_TYPES, TRANSACTION_TYPES,
TRANSACTION_STATUSES, TRANSACTION_STATUSES,
@ -110,6 +114,7 @@ export default class ConfirmTransactionBase extends Component {
actionKey: PropTypes.string, actionKey: PropTypes.string,
contentComponent: PropTypes.node, contentComponent: PropTypes.node,
dataComponent: PropTypes.node, dataComponent: PropTypes.node,
dataHexComponent: PropTypes.node,
hideData: PropTypes.bool, hideData: PropTypes.bool,
hideSubtitle: PropTypes.bool, hideSubtitle: PropTypes.bool,
identiconAddress: PropTypes.string, identiconAddress: PropTypes.string,
@ -633,12 +638,7 @@ export default class ConfirmTransactionBase extends Component {
renderData(functionType) { renderData(functionType) {
const { t } = this.context; const { t } = this.context;
const { const { txData: { txParams } = {}, hideData, dataComponent } = this.props;
txData: { txParams: { data } = {} } = {},
methodData: { params } = {},
hideData,
dataComponent,
} = this.props;
if (hideData) { if (hideData) {
return null; return null;
@ -653,6 +653,40 @@ export default class ConfirmTransactionBase extends Component {
{functionType} {functionType}
</span> </span>
</div> </div>
<Disclosure>
<TransactionDecoding to={txParams?.to} inputData={txParams?.data} />
</Disclosure>
</div>
)
);
}
renderDataHex(functionType) {
const { t } = this.context;
const {
txData: { txParams } = {},
methodData: { params } = {},
hideData,
dataHexComponent,
} = this.props;
if (hideData) {
return null;
}
const functionParams = params
? `(${params.map(({ type }) => type).join(', ')}`
: '';
return (
dataHexComponent || (
<div className="confirm-page-container-content__data">
<div className="confirm-page-container-content__data-box-label">
{`${t('functionType')}:`}
<span className="confirm-page-container-content__function-type">
{`${functionType} ${functionParams}`}
</span>
</div>
{params && ( {params && (
<div className="confirm-page-container-content__data-box"> <div className="confirm-page-container-content__data-box">
<div className="confirm-page-container-content__data-field-label"> <div className="confirm-page-container-content__data-field-label">
@ -664,9 +698,12 @@ export default class ConfirmTransactionBase extends Component {
</div> </div>
)} )}
<div className="confirm-page-container-content__data-box-label"> <div className="confirm-page-container-content__data-box-label">
{`${t('hexData')}: ${toBuffer(data).length} bytes`} {`${t('hexData')}: ${toBuffer(txParams?.data).length} bytes`}
</div> </div>
<div className="confirm-page-container-content__data-box">{data}</div> <div className="confirm-page-container-content__data-box">
{txParams?.data}
</div>
<CopyRawData data={txParams?.data} />
</div> </div>
) )
); );
@ -1019,6 +1056,7 @@ export default class ConfirmTransactionBase extends Component {
hideSubtitle={hideSubtitle} hideSubtitle={hideSubtitle}
detailsComponent={this.renderDetails()} detailsComponent={this.renderDetails()}
dataComponent={this.renderData(functionType)} dataComponent={this.renderData(functionType)}
dataHexComponent={this.renderDataHex(functionType)}
contentComponent={contentComponent} contentComponent={contentComponent}
nonce={customNonceValue || nonce} nonce={customNonceValue || nonce}
unapprovedTxCount={unapprovedTxCount} unapprovedTxCount={unapprovedTxCount}

View File

@ -120,7 +120,10 @@ const mapStateToProps = (state, ownProps) => {
shortenAddress(toChecksumHexAddress(toAddress)); shortenAddress(toChecksumHexAddress(toAddress));
const checksummedAddress = toChecksumHexAddress(toAddress); const checksummedAddress = toChecksumHexAddress(toAddress);
const addressBookObject = addressBook[checksummedAddress]; const addressBookObject =
addressBook &&
addressBook[chainId] &&
addressBook[chainId][checksummedAddress];
const toEns = ensResolutionsByAddress[checksummedAddress] || ''; const toEns = ensResolutionsByAddress[checksummedAddress] || '';
const toNickname = addressBookObject ? addressBookObject.name : ''; const toNickname = addressBookObject ? addressBookObject.name : '';
const transactionStatus = transaction ? transaction.status : ''; const transactionStatus = transaction ? transaction.status : '';
@ -231,6 +234,7 @@ const mapStateToProps = (state, ownProps) => {
nativeCurrency, nativeCurrency,
hardwareWalletRequiresConnection, hardwareWalletRequiresConnection,
isMultiLayerFeeNetwork, isMultiLayerFeeNetwork,
chainId,
}; };
}; };

View File

@ -2,6 +2,7 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import PageContainerContent from '../../../components/ui/page-container/page-container-content.component'; import PageContainerContent from '../../../components/ui/page-container/page-container-content.component';
import Dialog from '../../../components/ui/dialog'; import Dialog from '../../../components/ui/dialog';
import NicknamePopovers from '../../../components/app/modals/nickname-popovers';
import { import {
ETH_GAS_PRICE_FETCH_WARNING_KEY, ETH_GAS_PRICE_FETCH_WARNING_KEY,
GAS_PRICE_FETCH_FAILURE_ERROR_KEY, GAS_PRICE_FETCH_FAILURE_ERROR_KEY,
@ -16,13 +17,16 @@ import SendAssetRow from './send-asset-row';
import SendGasRow from './send-gas-row'; import SendGasRow from './send-gas-row';
export default class SendContent extends Component { export default class SendContent extends Component {
state = {
showNicknamePopovers: false,
};
static contextTypes = { static contextTypes = {
t: PropTypes.func, t: PropTypes.func,
}; };
static propTypes = { static propTypes = {
isAssetSendable: PropTypes.bool, isAssetSendable: PropTypes.bool,
showAddToAddressBookModal: PropTypes.func,
showHexData: PropTypes.bool, showHexData: PropTypes.bool,
contact: PropTypes.object, contact: PropTypes.object,
isOwnedAccount: PropTypes.bool, isOwnedAccount: PropTypes.bool,
@ -34,6 +38,7 @@ export default class SendContent extends Component {
networkOrAccountNotSupports1559: PropTypes.bool, networkOrAccountNotSupports1559: PropTypes.bool,
getIsBalanceInsufficient: PropTypes.bool, getIsBalanceInsufficient: PropTypes.bool,
asset: PropTypes.object, asset: PropTypes.object,
to: PropTypes.string,
}; };
render() { render() {
@ -81,24 +86,29 @@ export default class SendContent extends Component {
maybeRenderAddContact() { maybeRenderAddContact() {
const { t } = this.context; const { t } = this.context;
const { const { isOwnedAccount, contact = {}, to } = this.props;
isOwnedAccount, const { showNicknamePopovers } = this.state;
showAddToAddressBookModal,
contact = {},
} = this.props;
if (isOwnedAccount || contact.name) { if (isOwnedAccount || contact.name) {
return null; return null;
} }
return ( return (
<Dialog <>
type="message" <Dialog
className="send__dialog" type="message"
onClick={showAddToAddressBookModal} className="send__dialog"
> onClick={() => this.setState({ showNicknamePopovers: true })}
{t('newAccountDetectedDialogMessage')} >
</Dialog> {t('newAccountDetectedDialogMessage')}
</Dialog>
{showNicknamePopovers ? (
<NicknamePopovers
onClose={() => this.setState({ showNicknamePopovers: false })}
address={to}
/>
) : null}
</>
); );
} }

View File

@ -13,7 +13,6 @@ import {
getSendAsset, getSendAsset,
} from '../../../ducks/send'; } from '../../../ducks/send';
import * as actions from '../../../store/actions';
import SendContent from './send-content.component'; import SendContent from './send-content.component';
function mapStateToProps(state) { function mapStateToProps(state) {
@ -38,30 +37,4 @@ function mapStateToProps(state) {
}; };
} }
function mapDispatchToProps(dispatch) { export default connect(mapStateToProps)(SendContent);
return {
showAddToAddressBookModal: (recipient) =>
dispatch(
actions.showModal({
name: 'ADD_TO_ADDRESSBOOK',
recipient,
}),
),
};
}
function mergeProps(stateProps, dispatchProps, ownProps) {
const { to, ...restStateProps } = stateProps;
return {
...ownProps,
...restStateProps,
showAddToAddressBookModal: () =>
dispatchProps.showAddToAddressBookModal(to),
};
}
export default connect(
mapStateToProps,
mapDispatchToProps,
mergeProps,
)(SendContent);

309
yarn.lock
View File

@ -3955,6 +3955,79 @@
optionalDependencies: optionalDependencies:
secp256k1 "^3.5.2" secp256k1 "^3.5.2"
"@truffle/abi-utils@^0.2.4":
version "0.2.4"
resolved "https://registry.yarnpkg.com/@truffle/abi-utils/-/abi-utils-0.2.4.tgz#9fc8bfc95bbe29a33cca3ab9028865b078e2f051"
integrity sha512-ICr5Sger6r5uj2G5GN9Zp9OQDCaCqe2ZyAEyvavDoFB+jX0zZFUCfDnv5jllGRhgzdYJ3mec2390mjUyz9jSZA==
dependencies:
change-case "3.0.2"
faker "^5.3.1"
fast-check "^2.12.1"
"@truffle/code-utils@^1.2.30":
version "1.2.30"
resolved "https://registry.yarnpkg.com/@truffle/code-utils/-/code-utils-1.2.30.tgz#aa0a2a11eea40e3c76824729467f27d6cb76819b"
integrity sha512-/GFtGkmSZlLpIbIjBTunvhQQ4K2xaHK63QCEKydt3xRMPhpaeVAIaBNH53Z1ulOMDi6BZcSgwQHkquHf/omvMQ==
dependencies:
cbor "^5.1.0"
"@truffle/codec@^0.11.18", "@truffle/codec@^0.11.19":
version "0.11.19"
resolved "https://registry.yarnpkg.com/@truffle/codec/-/codec-0.11.19.tgz#c3da4b823d1f730a1114f94406fccfa5459b6bdd"
integrity sha512-ZxsfRWBE4wcQ01NCpMWH6VRJ/q3mGTl3ku8ln+WJ2P6McIMsS37imO3d8N9NWiQ49klc9kJfT3mKnOVMLTJhIg==
dependencies:
"@truffle/abi-utils" "^0.2.4"
"@truffle/compile-common" "^0.7.22"
big.js "^5.2.2"
bn.js "^5.1.3"
cbor "^5.1.0"
debug "^4.3.1"
lodash.clonedeep "^4.5.0"
lodash.escaperegexp "^4.1.2"
lodash.partition "^4.6.0"
lodash.sum "^4.0.2"
semver "^7.3.4"
utf8 "^3.0.0"
web3-utils "1.5.3"
"@truffle/compile-common@^0.7.22":
version "0.7.22"
resolved "https://registry.yarnpkg.com/@truffle/compile-common/-/compile-common-0.7.22.tgz#c376eea36f59dc770ece3bc8cbb7132f49352846"
integrity sha512-afFKh0Wphn8JrCSjOORKjO8/E1X0EtQv6GpFJpQCAWo3/i4VGcSVKR1rjkknnExtjEGe9PJH/Ym/opGH3pQyDw==
dependencies:
"@truffle/error" "^0.0.14"
colors "^1.4.0"
"@truffle/decoder@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@truffle/decoder/-/decoder-5.1.0.tgz#79cb9f6131ed81f69ec67a241fd5bbfd079d1501"
integrity sha512-bfNIqSlJviZjpHSiQ76IQvrJewKAzqnpIlC6V73tnhmJn2v21OQ945dXeQdVn/1V9gTkqSUgcXfNjB0wBKaevg==
dependencies:
"@truffle/abi-utils" "^0.2.4"
"@truffle/codec" "^0.11.19"
"@truffle/compile-common" "^0.7.22"
"@truffle/source-map-utils" "^1.3.63"
bn.js "^5.1.3"
debug "^4.3.1"
web3-utils "1.5.3"
"@truffle/error@^0.0.14":
version "0.0.14"
resolved "https://registry.yarnpkg.com/@truffle/error/-/error-0.0.14.tgz#59683b5407bede7bddf16d80dc5592f9c5e5fa05"
integrity sha512-utJx+SZYoMqk8wldQG4gCVKhV8GwMJbWY7sLXFT/D8wWZTnE2peX7URFJh/cxkjTRCO328z1s2qewkhyVsu2HA==
"@truffle/source-map-utils@^1.3.63":
version "1.3.63"
resolved "https://registry.yarnpkg.com/@truffle/source-map-utils/-/source-map-utils-1.3.63.tgz#6fa26d6b7a0874e99d6d78a5cacc13903dbcffd4"
integrity sha512-JmRnhONsjAdB5sTDl2xy7DUoIxg2KUGpXsPcu1EggBcojY1fZoD3wsdWWLysRDW5Od+npn/BWSdjzGdQknyVPA==
dependencies:
"@truffle/code-utils" "^1.2.30"
"@truffle/codec" "^0.11.19"
debug "^4.3.1"
json-pointer "^0.6.0"
node-interval-tree "^1.3.3"
web3-utils "1.5.3"
"@types/aria-query@^4.2.0": "@types/aria-query@^4.2.0":
version "4.2.0" version "4.2.0"
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0"
@ -6926,7 +6999,7 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828"
integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==
bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.2.0: bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.1.3, bn.js@^5.2.0:
version "5.2.0" version "5.2.0"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002"
integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==
@ -7141,6 +7214,11 @@ browser-stdout@1.3.1:
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
browser-util-inspect@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/browser-util-inspect/-/browser-util-inspect-0.2.0.tgz#cdda8ce1a4a07a4386035168a228c8777bff459c"
integrity sha1-zdqM4aSgekOGA1FooijId3v/RZw=
browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6, browserify-aes@^1.1.1, browserify-aes@^1.2.0: browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6, browserify-aes@^1.1.1, browserify-aes@^1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
@ -7694,6 +7772,14 @@ callsites@^3.0.0:
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
camel-case@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73"
integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=
dependencies:
no-case "^2.2.0"
upper-case "^1.1.1"
camel-case@^4.1.1: camel-case@^4.1.1:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.1.tgz#1fc41c854f00e2f7d0139dfeba1542d6896fe547" resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.1.tgz#1fc41c854f00e2f7d0139dfeba1542d6896fe547"
@ -7785,6 +7871,14 @@ cbor-web@^7.0.6:
resolved "https://registry.yarnpkg.com/cbor-web/-/cbor-web-7.0.6.tgz#6e23a0c58db4c38e485e395de511b9e2f628961c" resolved "https://registry.yarnpkg.com/cbor-web/-/cbor-web-7.0.6.tgz#6e23a0c58db4c38e485e395de511b9e2f628961c"
integrity sha512-A6ZH12jcDJG9PS7StugO78G+ok23SAjxMugGInPBy4IItiH6hYzybi6HQkGjWw9jBEGQpIBkleB2mizxYZIpLw== integrity sha512-A6ZH12jcDJG9PS7StugO78G+ok23SAjxMugGInPBy4IItiH6hYzybi6HQkGjWw9jBEGQpIBkleB2mizxYZIpLw==
cbor@^5.1.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/cbor/-/cbor-5.2.0.tgz#4cca67783ccd6de7b50ab4ed62636712f287a67c"
integrity sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A==
dependencies:
bignumber.js "^9.0.1"
nofilter "^1.0.4"
ccount@^1.0.0: ccount@^1.0.0:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.4.tgz#9cf2de494ca84060a2a8d2854edd6dfb0445f386" resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.4.tgz#9cf2de494ca84060a2a8d2854edd6dfb0445f386"
@ -7871,6 +7965,30 @@ chalk@~0.4.0:
has-color "~0.1.0" has-color "~0.1.0"
strip-ansi "~0.1.0" strip-ansi "~0.1.0"
change-case@3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/change-case/-/change-case-3.0.2.tgz#fd48746cce02f03f0a672577d1d3a8dc2eceb037"
integrity sha512-Mww+SLF6MZ0U6kdg11algyKd5BARbyM4TbFBepwowYSR5ClfQGCGtxNXgykpN0uF/bstWeaGDT4JWaDh8zWAHA==
dependencies:
camel-case "^3.0.0"
constant-case "^2.0.0"
dot-case "^2.1.0"
header-case "^1.0.0"
is-lower-case "^1.1.0"
is-upper-case "^1.1.0"
lower-case "^1.1.1"
lower-case-first "^1.0.0"
no-case "^2.3.2"
param-case "^2.1.0"
pascal-case "^2.0.0"
path-case "^2.1.0"
sentence-case "^2.1.0"
snake-case "^2.1.0"
swap-case "^1.1.0"
title-case "^2.1.0"
upper-case "^1.1.1"
upper-case-first "^1.1.0"
char-regex@^1.0.2: char-regex@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
@ -8373,7 +8491,7 @@ colors@0.5.x:
resolved "https://registry.yarnpkg.com/colors/-/colors-0.5.1.tgz#7d0023eaeb154e8ee9fce75dcb923d0ed1667774" resolved "https://registry.yarnpkg.com/colors/-/colors-0.5.1.tgz#7d0023eaeb154e8ee9fce75dcb923d0ed1667774"
integrity sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q= integrity sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=
colors@^1.1.2: colors@^1.1.2, colors@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
@ -8583,6 +8701,14 @@ consolidate@^0.16.0:
dependencies: dependencies:
bluebird "^3.7.2" bluebird "^3.7.2"
constant-case@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-2.0.0.tgz#4175764d389d3fa9c8ecd29186ed6005243b6a46"
integrity sha1-QXV2TTidP6nI7NKRhu1gBSQ7akY=
dependencies:
snake-case "^2.1.0"
upper-case "^1.1.1"
constants-browserify@^1.0.0, constants-browserify@~1.0.0: constants-browserify@^1.0.0, constants-browserify@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
@ -10039,6 +10165,13 @@ domutils@^1.5.1:
dom-serializer "0" dom-serializer "0"
domelementtype "1" domelementtype "1"
dot-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-2.1.1.tgz#34dcf37f50a8e93c2b3bca8bb7fb9155c7da3bee"
integrity sha1-NNzzf1Co6TwrO8qLt/uRVcfaO+4=
dependencies:
no-case "^2.2.0"
dot-case@^3.0.3: dot-case@^3.0.3:
version "3.0.3" version "3.0.3"
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa" resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa"
@ -12223,6 +12356,11 @@ fake-merkle-patricia-tree@^1.0.1:
dependencies: dependencies:
checkpoint-store "^1.1.0" checkpoint-store "^1.1.0"
faker@^5.3.1:
version "5.5.3"
resolved "https://registry.yarnpkg.com/faker/-/faker-5.5.3.tgz#c57974ee484431b25205c2c8dc09fda861e51e0e"
integrity sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==
fancy-log@1.3.2: fancy-log@1.3.2:
version "1.3.2" version "1.3.2"
resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1"
@ -12242,6 +12380,13 @@ fancy-log@^1.3.2, fancy-log@^1.3.3:
parse-node-version "^1.0.0" parse-node-version "^1.0.0"
time-stamp "^1.0.0" time-stamp "^1.0.0"
fast-check@^2.12.1:
version "2.19.0"
resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-2.19.0.tgz#e87666450e417cd163a564bd546ee763d27c0f19"
integrity sha512-qY4Rc0Nljl2aJx2qgbK3o6wPBjL9QvhKdD/VqJgaKd5ewn8l4ViqgDpUHJq/JkHTBnFKomYYvkFkOYGDVTT8bw==
dependencies:
pure-rand "^5.0.0"
fast-deep-equal@^2.0.1: fast-deep-equal@^2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
@ -12797,7 +12942,7 @@ for-own@^1.0.0:
dependencies: dependencies:
for-in "^1.0.1" for-in "^1.0.1"
foreach@^2.0.5: foreach@^2.0.4, foreach@^2.0.5:
version "2.0.5" version "2.0.5"
resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k=
@ -14236,6 +14381,14 @@ he@1.2.0, he@^1.2.0:
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
header-case@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/header-case/-/header-case-1.0.1.tgz#9535973197c144b09613cd65d317ef19963bd02d"
integrity sha1-lTWXMZfBRLCWE81l0xfvGZY70C0=
dependencies:
no-case "^2.2.0"
upper-case "^1.1.3"
heap@0.2.6, heap@~0.2.6: heap@0.2.6, heap@~0.2.6:
version "0.2.6" version "0.2.6"
resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac"
@ -15744,6 +15897,13 @@ is-ipfs@~0.6.1:
multibase "~0.6.0" multibase "~0.6.0"
multihashes "~0.4.13" multihashes "~0.4.13"
is-lower-case@^1.1.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-1.1.3.tgz#7e147be4768dc466db3bfb21cc60b31e6ad69393"
integrity sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=
dependencies:
lower-case "^1.1.0"
is-mergeable-object@1.1.1: is-mergeable-object@1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/is-mergeable-object/-/is-mergeable-object-1.1.1.tgz#faaa3ed1cfce87d6f7d2f5885e92cc30af3e2ebf" resolved "https://registry.yarnpkg.com/is-mergeable-object/-/is-mergeable-object-1.1.1.tgz#faaa3ed1cfce87d6f7d2f5885e92cc30af3e2ebf"
@ -16037,6 +16197,13 @@ is-unc-path@^1.0.0:
dependencies: dependencies:
unc-path-regex "^0.1.2" unc-path-regex "^0.1.2"
is-upper-case@^1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-1.1.2.tgz#8d0b1fa7e7933a1e58483600ec7d9661cbaf756f"
integrity sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=
dependencies:
upper-case "^1.1.0"
is-url@^1.2.2, is-url@^1.2.4: is-url@^1.2.2, is-url@^1.2.4:
version "1.2.4" version "1.2.4"
resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52"
@ -16825,6 +16992,13 @@ json-parse-even-better-errors@^2.3.0:
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
json-pointer@^0.6.0:
version "0.6.1"
resolved "https://registry.yarnpkg.com/json-pointer/-/json-pointer-0.6.1.tgz#3c6caa6ac139e2599f5a1659d39852154015054d"
integrity sha512-3OvjqKdCBvH41DLpV4iSt6v2XhZXV1bPB4OROuknvUXI7ZQNofieCPkmE26stEJ9zdQuvIxDHCuYhfgxFAAs+Q==
dependencies:
foreach "^2.0.4"
json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0:
version "3.8.0" version "3.8.0"
resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9"
@ -18331,6 +18505,11 @@ lodash.escape@^4.0.1:
resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98" resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98"
integrity sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg= integrity sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=
lodash.escaperegexp@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347"
integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=
lodash.filter@^4.6.0: lodash.filter@^4.6.0:
version "4.6.0" version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace"
@ -18396,11 +18575,21 @@ lodash.memoize@~3.0.3:
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f"
integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8= integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=
lodash.partition@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.partition/-/lodash.partition-4.6.0.tgz#a38e46b73469e0420b0da1212e66d414be364ba4"
integrity sha1-o45GtzRp4EILDaEhLmbUFL42S6Q=
lodash.sortby@^4.7.0: lodash.sortby@^4.7.0:
version "4.7.0" version "4.7.0"
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
lodash.sum@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/lodash.sum/-/lodash.sum-4.0.2.tgz#ad90e397965d803d4f1ff7aa5b2d0197f3b4637b"
integrity sha1-rZDjl5ZdgD1PH/eqWy0Bl/O0Y3s=
lodash.throttle@^4.1.1: lodash.throttle@^4.1.1:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
@ -18494,6 +18683,18 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3
dependencies: dependencies:
js-tokens "^3.0.0 || ^4.0.0" js-tokens "^3.0.0 || ^4.0.0"
lower-case-first@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-1.0.2.tgz#e5da7c26f29a7073be02d52bac9980e5922adfa1"
integrity sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E=
dependencies:
lower-case "^1.1.2"
lower-case@^1.1.0, lower-case@^1.1.1, lower-case@^1.1.2:
version "1.1.4"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
lower-case@^2.0.1: lower-case@^2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7"
@ -19809,6 +20010,13 @@ nise@^4.0.1:
just-extend "^4.0.2" just-extend "^4.0.2"
path-to-regexp "^1.7.0" path-to-regexp "^1.7.0"
no-case@^2.2.0, no-case@^2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==
dependencies:
lower-case "^1.1.1"
no-case@^3.0.3: no-case@^3.0.3:
version "3.0.3" version "3.0.3"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.3.tgz#c21b434c1ffe48b39087e86cfb4d2582e9df18f8" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.3.tgz#c21b434c1ffe48b39087e86cfb4d2582e9df18f8"
@ -19952,6 +20160,13 @@ node-int64@^0.4.0:
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=
node-interval-tree@^1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/node-interval-tree/-/node-interval-tree-1.3.3.tgz#15ffb904cde08270214acace8dc7653e89ae32b7"
integrity sha512-K9vk96HdTK5fEipJwxSvIIqwTqr4e3HRJeJrNxBSeVMNSC/JWARRaX7etOLOuTmrRMeOI/K5TCJu3aWIwZiNTw==
dependencies:
shallowequal "^1.0.2"
node-libs-browser@^2.2.1: node-libs-browser@^2.2.1:
version "2.2.1" version "2.2.1"
resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425"
@ -20067,6 +20282,11 @@ nodeify@^1.0.1:
is-promise "~1.0.0" is-promise "~1.0.0"
promise "~1.3.0" promise "~1.3.0"
nofilter@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-1.0.4.tgz#78d6f4b6a613e7ced8b015cec534625f7667006e"
integrity sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA==
nomnom@1.8.1: nomnom@1.8.1:
version "1.8.1" version "1.8.1"
resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.8.1.tgz#2151f722472ba79e50a76fc125bb8c8f2e4dc2a7" resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.8.1.tgz#2151f722472ba79e50a76fc125bb8c8f2e4dc2a7"
@ -21061,6 +21281,13 @@ parallel-transform@^1.1.0:
inherits "^2.0.3" inherits "^2.0.3"
readable-stream "^2.1.5" readable-stream "^2.1.5"
param-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247"
integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc=
dependencies:
no-case "^2.2.0"
param-case@^3.0.3: param-case@^3.0.3:
version "3.0.3" version "3.0.3"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.3.tgz#4be41f8399eff621c56eebb829a5e451d9801238" resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.3.tgz#4be41f8399eff621c56eebb829a5e451d9801238"
@ -21223,6 +21450,14 @@ parseurl@^1.3.2, parseurl@~1.3.2, parseurl@~1.3.3:
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
pascal-case@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-2.0.1.tgz#2d578d3455f660da65eca18ef95b4e0de912761e"
integrity sha1-LVeNNFX2YNpl7KGO+VtODekSdh4=
dependencies:
camel-case "^3.0.0"
upper-case-first "^1.1.0"
pascal-case@^3.1.1: pascal-case@^3.1.1:
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.1.tgz#5ac1975133ed619281e88920973d2cd1f279de5f" resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.1.tgz#5ac1975133ed619281e88920973d2cd1f279de5f"
@ -21283,6 +21518,13 @@ path-browserify@^1.0.0:
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd"
integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==
path-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/path-case/-/path-case-2.1.1.tgz#94b8037c372d3fe2906e465bb45e25d226e8eea5"
integrity sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU=
dependencies:
no-case "^2.2.0"
path-dirname@^1.0.0: path-dirname@^1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
@ -22668,6 +22910,11 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
pure-rand@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-5.0.0.tgz#87f5bdabeadbd8904e316913a5c0b8caac517b37"
integrity sha512-lD2/y78q+7HqBx2SaT6OT4UcwtvXNRfEpzYEzl0EQ+9gZq2Qi3fa0HDnYPeqQwhlHJFBUhT7AO3mLU3+8bynHA==
pushdata-bitcoin@^1.0.1: pushdata-bitcoin@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/pushdata-bitcoin/-/pushdata-bitcoin-1.0.1.tgz#15931d3cd967ade52206f523aa7331aef7d43af7" resolved "https://registry.yarnpkg.com/pushdata-bitcoin/-/pushdata-bitcoin-1.0.1.tgz#15931d3cd967ade52206f523aa7331aef7d43af7"
@ -24705,6 +24952,14 @@ send@0.17.1:
range-parser "~1.2.1" range-parser "~1.2.1"
statuses "~1.5.0" statuses "~1.5.0"
sentence-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-2.1.1.tgz#1f6e2dda39c168bf92d13f86d4a918933f667ed4"
integrity sha1-H24t2jnBaL+S0T+G1KkYkz9mftQ=
dependencies:
no-case "^2.2.0"
upper-case-first "^1.1.2"
serialize-error@^7.0.1: serialize-error@^7.0.1:
version "7.0.1" version "7.0.1"
resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18" resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18"
@ -25060,6 +25315,13 @@ smart-buffer@^4.0.2, smart-buffer@^4.1.0:
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
snake-case@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-2.1.0.tgz#41bdb1b73f30ec66a04d4e2cad1b76387d4d6d9f"
integrity sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=
dependencies:
no-case "^2.2.0"
snapdragon-node@^2.0.1: snapdragon-node@^2.0.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
@ -26141,6 +26403,14 @@ svg-tags@^1.0.0:
resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=
swap-case@^1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-1.1.2.tgz#c39203a4587385fad3c850a0bd1bcafa081974e3"
integrity sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM=
dependencies:
lower-case "^1.1.1"
upper-case "^1.1.1"
swappable-obj-proxy@^1.1.0: swappable-obj-proxy@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/swappable-obj-proxy/-/swappable-obj-proxy-1.1.0.tgz#fe23c60a0df22499e85d94b71297d9c39ff05fa4" resolved "https://registry.yarnpkg.com/swappable-obj-proxy/-/swappable-obj-proxy-1.1.0.tgz#fe23c60a0df22499e85d94b71297d9c39ff05fa4"
@ -26593,6 +26863,14 @@ tiny-worker@^2.3.0:
dependencies: dependencies:
esm "^3.2.25" esm "^3.2.25"
title-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.1.tgz#3e127216da58d2bc5becf137ab91dae3a7cd8faa"
integrity sha1-PhJyFtpY0rxb7PE3q5Ha46fNj6o=
dependencies:
no-case "^2.2.0"
upper-case "^1.0.3"
tmp@0.0.30: tmp@0.0.30:
version "0.0.30" version "0.0.30"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed"
@ -27367,6 +27645,18 @@ uport-base64url@3.0.2-alpha.0:
dependencies: dependencies:
buffer "^5.2.1" buffer "^5.2.1"
upper-case-first@^1.1.0, upper-case-first@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-1.1.2.tgz#5d79bedcff14419518fd2edb0a0507c9b6859115"
integrity sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=
dependencies:
upper-case "^1.1.1"
upper-case@^1.0.3, upper-case@^1.1.0, upper-case@^1.1.1, upper-case@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=
uri-js@^4.2.2: uri-js@^4.2.2:
version "4.2.2" version "4.2.2"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
@ -28176,6 +28466,19 @@ web3-utils@1.2.11:
underscore "1.9.1" underscore "1.9.1"
utf8 "3.0.0" utf8 "3.0.0"
web3-utils@1.5.3:
version "1.5.3"
resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.5.3.tgz#e914c9320cd663b2a09a5cb920ede574043eb437"
integrity sha512-56nRgA+Ad9SEyCv39g36rTcr5fpsd4L9LgV3FK0aB66nAMazLAA6Qz4lH5XrUKPDyBIPGJIR+kJsyRtwcu2q1Q==
dependencies:
bn.js "^4.11.9"
eth-lib "0.2.8"
ethereum-bloom-filters "^1.0.6"
ethjs-unit "0.1.6"
number-to-bn "1.7.0"
randombytes "^2.1.0"
utf8 "3.0.0"
web3@1.2.11: web3@1.2.11:
version "1.2.11" version "1.2.11"
resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975"