aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkumavis <kumavis@users.noreply.github.com>2018-11-02 09:29:45 +0800
committerGitHub <noreply@github.com>2018-11-02 09:29:45 +0800
commit337a4e1b4ea7a560d773bc262b2adffd1617a39b (patch)
treef3c2f9b33642ef9be901645645734129686e6c6e
parentc2f97717c0fbf9a64cf527891f7a1f35049fb023 (diff)
parentde231c7a6191ca869308b6d27ca9cd4b020e59aa (diff)
downloadtangerine-wallet-browser-337a4e1b4ea7a560d773bc262b2adffd1617a39b.tar
tangerine-wallet-browser-337a4e1b4ea7a560d773bc262b2adffd1617a39b.tar.gz
tangerine-wallet-browser-337a4e1b4ea7a560d773bc262b2adffd1617a39b.tar.bz2
tangerine-wallet-browser-337a4e1b4ea7a560d773bc262b2adffd1617a39b.tar.lz
tangerine-wallet-browser-337a4e1b4ea7a560d773bc262b2adffd1617a39b.tar.xz
tangerine-wallet-browser-337a4e1b4ea7a560d773bc262b2adffd1617a39b.tar.zst
tangerine-wallet-browser-337a4e1b4ea7a560d773bc262b2adffd1617a39b.zip
Merge pull request #5649 from MetaMask/develop
Version 4.17.0
-rw-r--r--.circleci/config.yml2
-rw-r--r--CHANGELOG.md12
-rw-r--r--app/_locales/en/messages.json28
-rw-r--r--app/_locales/ht/messages.json2545
-rw-r--r--app/_locales/index.json42
-rw-r--r--app/_locales/nl/messages.json2
-rw-r--r--app/_locales/sl/messages.json763
-rw-r--r--app/loading.html12
-rw-r--r--app/manifest.json2
-rw-r--r--app/scripts/background.js22
-rw-r--r--app/scripts/controllers/blacklist.js25
-rw-r--r--app/scripts/controllers/currency.js80
-rw-r--r--app/scripts/controllers/network/createMetamaskMiddleware.js2
-rw-r--r--app/scripts/controllers/network/network.js76
-rw-r--r--app/scripts/controllers/preferences.js70
-rw-r--r--app/scripts/controllers/transactions/tx-gas-utils.js35
-rw-r--r--app/scripts/lib/ens-ipfs/contracts/registrar.js (renamed from app/scripts/lib/contracts/registrar.js)0
-rw-r--r--app/scripts/lib/ens-ipfs/contracts/resolver.js (renamed from app/scripts/lib/contracts/resolver.js)0
-rw-r--r--app/scripts/lib/ens-ipfs/resolver.js54
-rw-r--r--app/scripts/lib/ens-ipfs/setup.js63
-rw-r--r--app/scripts/lib/ipfsContent.js46
-rw-r--r--app/scripts/lib/reportFailedTxToSentry.js6
-rw-r--r--app/scripts/lib/resolver.js71
-rw-r--r--app/scripts/lib/setupFetchDebugging.js10
-rw-r--r--app/scripts/lib/setupSentry.js (renamed from app/scripts/lib/setupRaven.js)75
-rw-r--r--app/scripts/metamask-controller.js51
-rw-r--r--app/scripts/ui.js14
-rw-r--r--development/states/add-token.json2
-rw-r--r--development/states/confirm-sig-requests.json2
-rw-r--r--development/states/currency-localization.json2
-rw-r--r--development/states/first-time.json2
-rw-r--r--development/states/send-new-ui.json2
-rw-r--r--development/states/tx-list-items.json2
-rw-r--r--gulpfile.js4
-rw-r--r--old-ui/app/app.js2
-rw-r--r--old-ui/app/components/app-bar.js15
-rw-r--r--old-ui/app/components/balance.js11
-rw-r--r--old-ui/app/components/eth-balance.js12
-rw-r--r--old-ui/app/components/pending-tx.js16
-rw-r--r--old-ui/app/config.js76
-rw-r--r--old-ui/app/util.js8
-rw-r--r--package-lock.json504
-rw-r--r--package.json10
-rw-r--r--test/data/mock-state.json4
-rw-r--r--test/e2e/beta/from-import-beta-ui.spec.js2
-rw-r--r--test/e2e/beta/metamask-beta-ui.spec.js28
-rwxr-xr-xtest/e2e/beta/run-drizzle.sh2
-rw-r--r--test/integration/lib/currency-localization.js2
-rw-r--r--test/integration/lib/send-new-ui.js6
-rw-r--r--test/unit/app/controllers/network-contoller-test.js2
-rw-r--r--test/unit/app/controllers/preferences-controller-test.js24
-rw-r--r--test/unit/ui/app/actions.spec.js2
-rw-r--r--ui/app/actions.js12
-rw-r--r--ui/app/app.js8
-rw-r--r--ui/app/components/account-dropdowns.js3
-rw-r--r--ui/app/components/account-menu/index.js2
-rw-r--r--ui/app/components/account-panel.js2
-rw-r--r--ui/app/components/app-header/app-header.component.js2
-rw-r--r--ui/app/components/balance-component.js16
-rw-r--r--ui/app/components/currency-display/currency-display.component.js17
-rw-r--r--ui/app/components/currency-display/currency-display.container.js12
-rw-r--r--ui/app/components/currency-display/index.scss4
-rw-r--r--ui/app/components/currency-display/tests/currency-display.container.test.js31
-rw-r--r--ui/app/components/currency-input/currency-input.component.js5
-rw-r--r--ui/app/components/currency-input/currency-input.container.js7
-rw-r--r--ui/app/components/currency-input/tests/currency-input.component.test.js24
-rw-r--r--ui/app/components/currency-input/tests/currency-input.container.test.js5
-rw-r--r--ui/app/components/dropdowns/components/account-dropdowns.js8
-rw-r--r--ui/app/components/dropdowns/network-dropdown.js35
-rw-r--r--ui/app/components/dropdowns/tests/network-dropdown.test.js4
-rw-r--r--ui/app/components/eth-balance.js12
-rw-r--r--ui/app/components/identicon.js124
-rw-r--r--ui/app/components/identicon/identicon.component.js99
-rw-r--r--ui/app/components/identicon/identicon.container.js12
-rw-r--r--ui/app/components/identicon/index.js1
-rw-r--r--ui/app/components/identicon/index.scss7
-rw-r--r--ui/app/components/identicon/tests/identicon.component.test.js (renamed from test/unit/ui/app/components/identicon.spec.js)33
-rw-r--r--ui/app/components/index.scss2
-rw-r--r--ui/app/components/jazzicon/index.js1
-rw-r--r--ui/app/components/jazzicon/jazzicon.component.js69
-rw-r--r--ui/app/components/modals/account-modal-container.js2
-rw-r--r--ui/app/components/modals/hide-token-confirmation-modal.js2
-rw-r--r--ui/app/components/modals/modal.js14
-rw-r--r--ui/app/components/modals/transaction-details/index.js1
-rw-r--r--ui/app/components/modals/transaction-details/transaction-details.component.js54
-rw-r--r--ui/app/components/modals/transaction-details/transaction-details.container.js4
-rw-r--r--ui/app/components/network-display/network-display.component.js4
-rw-r--r--ui/app/components/network.js5
-rw-r--r--ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js2
-rw-r--r--ui/app/components/pages/settings/settings-tab/index.scss12
-rw-r--r--ui/app/components/pages/settings/settings-tab/settings-tab.component.js122
-rw-r--r--ui/app/components/pages/settings/settings-tab/settings-tab.container.js14
-rw-r--r--ui/app/components/send/account-list-item/account-list-item.container.js2
-rw-r--r--ui/app/components/send/account-list-item/tests/account-list-item-component.test.js1
-rw-r--r--ui/app/components/send/account-list-item/tests/account-list-item-container.test.js2
-rw-r--r--ui/app/components/send/send-content/send-amount-row/tests/send-amount-row-component.test.js1
-rw-r--r--ui/app/components/send/send.selectors.js5
-rw-r--r--ui/app/components/send/send.utils.js4
-rw-r--r--ui/app/components/send/tests/send-selectors-test-data.js1
-rw-r--r--ui/app/components/send/tests/send-selectors.test.js10
-rw-r--r--ui/app/components/shift-list-item.js5
-rw-r--r--ui/app/components/signature-request.js2
-rw-r--r--ui/app/components/token-cell.js2
-rw-r--r--ui/app/components/token-input/tests/token-input.component.test.js12
-rw-r--r--ui/app/components/transaction-activity-log/tests/transaction-activity-log.container.test.js3
-rw-r--r--ui/app/components/transaction-activity-log/transaction-activity-log.component.js21
-rw-r--r--ui/app/components/transaction-activity-log/transaction-activity-log.container.js3
-rw-r--r--ui/app/components/transaction-activity-log/transaction-activity-log.util.js11
-rw-r--r--ui/app/components/transaction-breakdown/index.js2
-rw-r--r--ui/app/components/transaction-breakdown/transaction-breakdown.component.js7
-rw-r--r--ui/app/components/transaction-breakdown/transaction-breakdown.container.js11
-rw-r--r--ui/app/components/transaction-list-item/index.scss2
-rw-r--r--ui/app/components/transaction-list-item/transaction-list-item.component.js19
-rw-r--r--ui/app/components/transaction-list-item/transaction-list-item.container.js10
-rw-r--r--ui/app/components/transaction-list/index.scss3
-rw-r--r--ui/app/components/transaction-view-balance/index.scss9
-rw-r--r--ui/app/components/transaction-view-balance/transaction-view-balance.container.js3
-rw-r--r--ui/app/components/transaction-view/index.scss1
-rw-r--r--ui/app/components/user-preferenced-currency-display/tests/user-preferenced-currency-display.container.test.js22
-rw-r--r--ui/app/components/user-preferenced-currency-display/user-preferenced-currency-display.component.js1
-rw-r--r--ui/app/components/user-preferenced-currency-display/user-preferenced-currency-display.container.js18
-rw-r--r--ui/app/components/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js6
-rw-r--r--ui/app/components/user-preferenced-currency-input/tests/user-preferenced-currency-input.container.test.js4
-rw-r--r--ui/app/components/user-preferenced-currency-input/user-preferenced-currency-input.component.js6
-rw-r--r--ui/app/components/user-preferenced-currency-input/user-preferenced-currency-input.container.js4
-rw-r--r--ui/app/components/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js6
-rw-r--r--ui/app/components/user-preferenced-token-input/tests/user-preferenced-token-input.container.test.js4
-rw-r--r--ui/app/components/user-preferenced-token-input/user-preferenced-token-input.component.js6
-rw-r--r--ui/app/components/user-preferenced-token-input/user-preferenced-token-input.container.js4
-rw-r--r--ui/app/components/wallet-view.js3
-rw-r--r--ui/app/constants/error-keys.js1
-rw-r--r--ui/app/css/itcss/components/buttons.scss5
-rw-r--r--ui/app/css/itcss/components/request-signature.scss2
-rw-r--r--ui/app/css/itcss/components/wallet-balance.scss5
-rw-r--r--ui/app/ducks/confirm-transaction.duck.js11
-rw-r--r--ui/app/helpers/confirm-transaction/util.js8
-rw-r--r--ui/app/helpers/conversions.util.js10
-rw-r--r--ui/app/helpers/transactions.util.js15
-rw-r--r--ui/app/reducers.js26
-rw-r--r--ui/app/reducers/metamask.js2
-rw-r--r--ui/app/selectors.js5
-rw-r--r--ui/app/selectors/confirm-transaction.js1
-rw-r--r--ui/app/util.js8
143 files changed, 3782 insertions, 2196 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 00ba9ffa2..60867e181 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -324,7 +324,7 @@ jobs:
command: >
git config user.name metamaskbot &&
git config user.email admin@metamask.io &&
- gh-pages -d docs/jsdocs
+ npm run publish-docs
test-unit:
docker:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5a9d7703c..71920def2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,18 @@
## Current Develop Branch
+## 4.17.0 Thursday November 1 2018
+
+- Fix bug where data lookups like balances would get stale data (stopped block-tracker bug)
+- Transaction Details now show entry for onchain failure
+- [#5559](https://github.com/MetaMask/metamask-extension/pull/5559) Localize language names in translation select list
+- [#5283](https://github.com/MetaMask/metamask-extension/pull/5283): Fix bug when eth.getCode() called with no contract
+- [#5563](https://github.com/MetaMask/metamask-extension/pull/5563#pullrequestreview-166769174) Feature: improve Hatian Creole translations
+- Feature: improve Slovenian translations
+- Add support for alternate `wallet_watchAsset` rpc method name
+- Attempt chain ID lookup via `eth_chainId` before `net_version`
+- Fix account display width for large currency values
+
## 4.16.0 Wednesday October 17 2018
- Feature: Add toggle for primary currency (eth/fiat)
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index bf5854a31..26d0422cb 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -692,9 +692,27 @@
"newRecipient": {
"message": "New Recipient"
},
- "newRPC": {
+ "newNetwork": {
+ "message": "New Network"
+ },
+ "rpcURL": {
"message": "New RPC URL"
},
+ "showAdvancedOptions": {
+ "message": "Show Advanced Options"
+ },
+ "hideAdvancedOptions": {
+ "message": "Hide Advanced Options"
+ },
+ "optionalChainId": {
+ "message": "ChainID (optional)"
+ },
+ "optionalSymbol": {
+ "message": "Symbol (optional)"
+ },
+ "optionalNickname": {
+ "message": "Nickname (optional)"
+ },
"next": {
"message": "Next"
},
@@ -803,7 +821,7 @@
"message": "Primary Currency"
},
"primaryCurrencySettingDescription": {
- "message": "Select ETH to prioritize displaying values in ETH. Select Fiat to prioritize displaying values in your selected currency."
+ "message": "Select native to prioritize displaying values in the native currency of the chain (e.g. ETH). Select Fiat to prioritize displaying values in your selected fiat currency."
},
"privacyMsg": {
"message": "Privacy Policy"
@@ -1169,12 +1187,18 @@
"transactionUpdatedGas": {
"message": "Transaction updated with a gas price of $1 on $2."
},
+ "transactionErrored": {
+ "message": "Transaction encountered an error."
+ },
"transactions": {
"message": "transactions"
},
"transactionError": {
"message": "Transaction Error. Exception thrown in contract code."
},
+ "transactionErrorNoContract": {
+ "message": "Trying to call a function on a non-contract address."
+ },
"transactionMemo": {
"message": "Transaction memo (optional)"
},
diff --git a/app/_locales/ht/messages.json b/app/_locales/ht/messages.json
index 50a0ec2bb..81ce18018 100644
--- a/app/_locales/ht/messages.json
+++ b/app/_locales/ht/messages.json
@@ -1,1237 +1,1312 @@
{
- "accept": {
- "message": "Aksepte"
- },
- "accessingYourCamera": {
- "message": "Aksè a Kamera"
- },
- "account": {
- "message": "Kont"
- },
- "accountDetails": {
- "message": "Detay Kont"
- },
- "accountName": {
- "message": "Non Kont"
- },
- "accountSelectionRequired": {
- "message": "Ou bezwen chwazi yon kont!"
- },
- "activityLog": {
- "message": "aktivite ki fèt"
- },
- "address": {
- "message": "Adrès"
- },
- "addCustomToken": {
- "message": "Ajoute token"
- },
- "addToken": {
- "message": "Ajoute Token"
- },
- "addTokens": {
- "message": "Ajoute Token"
- },
- "addSuggestedTokens": {
- "message": "Ajoute Token Yo Sikjere W"
- },
- "addAcquiredTokens": {
- "message": "Ajoute tokens yo ou te achte lè l sèvi avèk MetaMask"
- },
- "amount": {
- "message": "Kantite lajan"
- },
- "amountPlusGas": {
- "message": "Kantite lajan + Gaz"
- },
- "appDescription": {
- "message": "Ethereum Ekstansyon Navigatè",
- "description": "The description of the application"
- },
- "appName": {
- "message": "MetaMask",
- "description": "The name of the application"
- },
- "approve": {
- "message": "Apwouve"
- },
- "approved": {
- "message": "Apwouve"
- },
- "attemptingConnect": {
- "message": "Eseye konekte nan blockchain."
- },
- "attributions": {
- "message": "Atribisyon"
- },
- "available": {
- "message": "Disponib"
- },
- "back": {
- "message": "Retounen"
- },
- "balance": {
- "message": "Balans"
- },
- "balances": {
- "message": "Balans Token"
- },
- "balanceIsInsufficientGas": {
- "message": "Ensifizan balans pou total gaz aktyèl la"
- },
- "beta": {
- "message": "BETA"
- },
- "betweenMinAndMax": {
- "message": "dwe plis pase oswa egal a $ 1 mwens ke oswa egal a $ 2.",
- "description": "helper for inputting hex as decimal input"
- },
- "blockiesIdenticon": {
- "message": "Itilize Blockies Identicon"
- },
- "borrowDharma": {
- "message": "Prete Avèk Dharma (Beta)"
- },
- "browserNotSupported": {
- "message": "Navigatè ou a pa sipòte..."
- },
- "builtInCalifornia": {
- "message": "MetaMask fèt e bati nan California."
- },
- "buy": {
- "message": "Achte"
- },
- "buyCoinbase": {
- "message": "Achte sou Coinbase"
- },
- "buyCoinbaseExplainer": {
- "message": "Coinbase se fason ki pi popilè nan mond lan yo achte ak vann Bitcoin, Ethereum, ak Litecoin."
- },
- "bytes": {
- "message": "Bytes"
- },
- "ok": {
- "message": "Oke"
- },
- "cancel": {
- "message": "Anile"
- },
- "classicInterface": {
- "message": "Sèvi ak fas klasik la"
- },
- "clickCopy": {
- "message": "Klike sou kopi"
- },
- "close": {
- "message": "Fèmen"
- },
- "chromeRequiredForHardwareWallets": {
- "message": "Ou bezwen sèvi ak MetaMask sou Google Chrome yo nan lòd yo konekte sou Hardware Wallet."
- },
- "confirm": {
- "message": "Konfime"
- },
- "confirmed": {
- "message": "Konfime"
- },
- "confirmContract": {
- "message": "Konfime Kontra"
- },
- "confirmPassword": {
- "message": "Konfime Modpas"
- },
- "confirmTransaction": {
- "message": "Konfime Tranzaksyon"
- },
- "connectHardwareWallet": {
- "message": "Konekte Hardware Wallet"
- },
- "connect": {
- "message": "Konekte"
- },
- "connecting": {
- "message": "Koneksyon..."
- },
- "connectToLedger": {
- "message": "Konekte ak Ledger"
- },
- "connectToTrezor": {
- "message": "Konekte ak Trezor"
- },
- "continue": {
- "message": "Kontinye"
- },
- "continueToCoinbase": {
- "message": "Kontinye Coinbase"
- },
- "contractDeployment": {
- "message": "Kontra Deplwaman"
- },
- "conversionProgress": {
- "message": "Konvèsyon nan Pwogrè"
- },
- "copiedButton": {
- "message": "Kopye"
- },
- "copiedClipboard": {
- "message": "Kopi nan Clipboard"
- },
- "copiedExclamation": {
- "message": "Kopye!"
- },
- "copiedSafe": {
- "message": "Mwen te kopye li yon kote ki san danje"
- },
- "copy": {
- "message": "Kopye"
- },
- "copyAddress": {
- "message": "Kopi adrès clipboard"
- },
- "copyToClipboard": {
- "message": "Kopi clipboard"
- },
- "copyButton": {
- "message": " Kopi "
- },
- "copyPrivateKey": {
- "message": "Sa a se kle prive ou (klike pou ou kopye)"
- },
- "create": {
- "message": "Kreye"
- },
- "createAccount": {
- "message": "Kreye Kont"
- },
- "createDen": {
- "message": "Kreye"
- },
- "crypto": {
- "message": "Crypto",
- "description": "Change tip (cryptocurrencies)"
- },
- "currentConversion": {
- "message": "Konvèsyon aktyèl"
- },
- "currentNetwork": {
- "message": "Rezo aktyèl"
- },
- "customGas": {
- "message": "Koutim Gaz"
- },
- "customToken": {
- "message": "Koutim Token"
- },
- "customize": {
- "message": "Koutim"
- },
- "customRPC": {
- "message": "Koutim RPC"
- },
- "decimalsMustZerotoTen": {
- "message": "Desimal yo dwe omwen 0, epi pa dwe plis pase 36."
- },
- "decimal": {
- "message": "Presizyon desimal la"
- },
- "defaultNetwork": {
- "message": "Dfo rezo a pou tranzaksyon Ether se Mainnet."
- },
- "denExplainer": {
- "message": "DEN ou se depo modpas avèk chif ou nan MetaMask."
- },
- "deposit": {
- "message": "Depo"
- },
- "depositBTC": {
- "message": "Depoze BTC ou nan adrès ki anba a:"
- },
- "depositCoin": {
- "message": "Depoze $1 ou nan adrès ki anba a",
- "description": "Tells the user what coin they have selected to deposit with shapeshift"
- },
- "depositEth": {
- "message": "Depo Eth"
- },
- "depositEther": {
- "message": "Depo Ether"
- },
- "depositFiat": {
- "message": "Depo ak Fiat"
- },
- "depositFromAccount": {
- "message": "Depo nan yon lòt kont"
- },
- "depositShapeShift": {
- "message": "Depo avèk ShapeShift"
- },
- "depositShapeShiftExplainer": {
- "message": "Si ou posede lòt cryptocurrencies, ou ka chanje ak depo Ether dirèkteman nan Wallet MetaMask ou. Pa gen kont ki nesesè."
- },
- "details": {
- "message": "Detay yo"
- },
- "directDeposit": {
- "message": "Depo Dirèk"
- },
- "directDepositEther": {
- "message": "Dirèkteman Depo Ether"
- },
- "directDepositEtherExplainer": {
- "message": "Si ou deja gen kèk Ether, fason ki pi rapid yo ka resevwa Ether nan nouvo Wallet ou pa depo dirèk."
- },
- "done": {
- "message": "Fini"
- },
- "downloadGoogleChrome": {
- "message": "Telechaje Google Chrome"
- },
- "downloadStateLogs": {
- "message": "Telechaje State Logs"
- },
- "dontHaveAHardwareWallet": {
- "message": "Pa gen yon materyèl bous?"
- },
- "dropped": {
- "message": "Tonbe"
- },
- "edit": {
- "message": "Korije"
- },
- "editAccountName": {
- "message": "Korije Non Kont"
- },
- "editingTransaction": {
- "message": "Fè chanjman nan tranzaksyon ou"
- },
- "emailUs": {
- "message": "Imèl nou!"
- },
- "encryptNewDen": {
- "message": "Ankripte nouvo DEN ou"
- },
- "ensNameNotFound": {
- "message": "Nou pa jwenn non ENS ou a"
- },
- "enterPassword": {
- "message": "Mete modpas"
- },
- "enterPasswordConfirm": {
- "message": "Antre nan modpas ou a konfime"
- },
- "enterPasswordContinue": {
- "message": "Mete modpas pou kontinye"
- },
- "parameters": {
- "message": "Paramèt"
- },
- "passwordNotLongEnough": {
- "message": "Modpas la pa ase"
- },
- "passwordsDontMatch": {
- "message": "Modpas Pa Koresponn ak"
- },
- "etherscanView": {
- "message": "Gade kont sou Etherscan"
- },
- "exchangeRate": {
- "message": "Chanje to"
- },
- "exportPrivateKey": {
- "message": "Voye Kòd Prive"
- },
- "exportPrivateKeyWarning": {
- "message": "Voye kle prive ak pwòp risk ou."
- },
- "failed": {
- "message": "Tonbe"
- },
- "fiat": {
- "message": "FIAT",
- "description": "Exchange type"
- },
- "fileImportFail": {
- "message": "Enpòte dosye ki pa travay? Klike la a!",
- "description": "Helps user import their account from a JSON file"
- },
- "followTwitter": {
- "message": "Swiv nou sou Twitter"
- },
- "forgetDevice": {
- "message": "Bliye aparèy sa a"
- },
- "from": {
- "message": "Soti nan"
- },
- "fromToSame": {
- "message": "Adrès orijinal le ak sa ou resevwa pake menm"
- },
- "fromShapeShift": {
- "message": "Soti nan ShapeShift"
- },
- "functionType": {
- "message": "Kalite Fonksyon"
- },
- "gas": {
- "message": "Gaz",
- "description": "Short indication of gas cost"
- },
- "gasFee": {
- "message": "Frè gaz"
- },
- "gasLimit": {
- "message": "Limit gaz"
- },
- "gasLimitCalculation": {
- "message": "Nou kalkile gaz limit sijere a ki baze sou pousantaj siksè rezo a."
- },
- "gasLimitRequired": {
- "message": "Limit gaz nesesè"
- },
- "gasLimitTooLow": {
- "message": "Limit gaz dwe omwen 21000"
- },
- "generatingSeed": {
- "message": "Génération Seed..."
- },
- "gasPrice": {
- "message": "Pri gaz (GWEI)"
- },
- "gasPriceCalculation": {
- "message": "Nou kalkile pri yo gaz ki sijere ki baze sou pousantaj siksè rezo."
- },
- "gasPriceRequired": {
- "message": "Pri Gaz la Egzije"
- },
- "generatingTransaction": {
- "message": "Tranzaksyon kap fè"
- },
- "getEther": {
- "message": "Jwenn Ether"
- },
- "getEtherFromFaucet": {
- "message": "Jwenn Ether nan yon tiyo pou $1 la",
- "description": "Displays network name for Ether faucet"
- },
- "getHelp": {
- "message": "Jwenn èd."
- },
- "greaterThanMin": {
- "message": "dwe pi gran pase oswa egal a $ 1.",
- "description": "helper for inputting hex as decimal input"
- },
- "hardware": {
- "message": "hardware"
- },
- "hardwareWalletConnected": {
- "message": "Hardware Wallet konekte"
- },
- "hardwareWallets": {
- "message": "Hardware Wallet konekte"
- },
- "hardwareWalletsMsg": {
- "message": "Chwazi yon Hardware Wallet ou ta renmen itilize ak MetaMask"
- },
- "havingTroubleConnecting": {
- "message": "Èske w gen pwoblèm pou konekte?"
- },
- "here": {
- "message": "isit la",
- "description": "as in -click here- for more information (goes with troubleTokenBalances)"
- },
- "hereList": {
- "message": "Isit la nan yon lis !!!!"
- },
- "hexData": {
- "message": "Hex Data"
- },
- "hide": {
- "message": "Kache"
- },
- "hideToken": {
- "message": "Kache Token"
- },
- "hideTokenPrompt": {
- "message": "Kache Token?"
- },
- "history": {
- "message": "Istwa"
- },
- "howToDeposit": {
- "message": "Ki jan ou ta renmen depo Ether?"
- },
- "holdEther": {
- "message": "Li pèmèt ou kenbe ether & tokens, epi sèvi kòm on pon pou desantralize aplikasyon."
- },
- "import": {
- "message": "Pòte",
- "description": "Button to import an account from a selected file"
- },
- "importAccount": {
- "message": "Pòte Kont"
- },
- "importAccountMsg": {
- "message": " Kont pòte pa pral asosye avèk orijinal ou te kreye nan kont MetaMask seed fraz. Aprann plis sou kont enpòte "
- },
- "importAnAccount": {
- "message": "Pòte yon kont"
- },
- "importDen": {
- "message": "Pòte ki deja egziste DEN"
- },
- "imported": {
- "message": "Pòte",
- "description": "status showing that an account has been fully loaded into the keyring"
- },
- "importUsingSeed": {
- "message": "Pòte lè sèvi avèk seed fraz"
- },
- "infoHelp": {
- "message": "Enfo & Èd"
- },
- "initialTransactionConfirmed": {
- "message": "Premye tranzaksyon ou konfime sou rezo a. Klike sou OK pou tounen."
- },
- "insufficientFunds": {
- "message": "Lajan ensifizan."
- },
- "insufficientTokens": {
- "message": "Tokens pa valab."
- },
- "invalidAddress": {
- "message": "Adrès pa valab"
- },
- "invalidAddressRecipient": {
- "message": "Moun ki resevwa adrès la pa valab"
- },
- "invalidGasParams": {
- "message": "Gaz Paramèt la pa valab"
- },
- "invalidInput": {
- "message": "Sa ou rantre a pa valab"
- },
- "invalidRequest": {
- "message": "Demann pa valab"
- },
- "invalidRPC": {
- "message": "RPC URI pa valab"
- },
- "invalidSeedPhrase": {
- "message": "Seed fraz pa valab"
- },
- "jsonFail": {
- "message": "Yon bagay ale mal. Tanpri, asire w ke dosye JSON ou an byen fòmate."
- },
- "jsonFile": {
- "message": "JSON Dosye",
- "description": "format for importing an account"
- },
- "keepTrackTokens": {
- "message": "Gade tokens yo ou te achte ak kont MetaMask ou."
- },
- "kovan": {
- "message": "Kovan Tès Rezo"
- },
- "knowledgeDataBase": {
- "message": "Vizite baz nou an"
- },
- "max": {
- "message": "Maksimòm"
- },
- "learnMore": {
- "message": "Aprann plis"
- },
- "ledgerAccountRestriction": {
- "message": "Ou bezwen sèvi ak dènye kont ou anvan ou ka ajoute yon nouvo."
- },
- "lessThanMax": {
- "message": "dwe mwens pase oswa egal a $ 1.",
- "description": "helper for inputting hex as decimal input"
- },
- "likeToAddTokens": {
- "message": "Èske ou ta renmen ajoute sa nan tokens?"
- },
- "links": {
- "message": "Lyen"
- },
- "limit": {
- "message": "Limitasyon"
- },
- "loading": {
- "message": "Telechaje..."
- },
- "loadingTokens": {
- "message": "Telechaje Tokens..."
- },
- "localhost": {
- "message": "Localhost 8545"
- },
- "login": {
- "message": "Ouvri"
- },
- "logout": {
- "message": "Dekonekte"
- },
- "loose": {
- "message": "Pèdi"
- },
- "loweCaseWords": {
- "message": "seed mo sèlman gen karaktè miniskil"
- },
- "mainnet": {
- "message": "Main Ethereum Network"
- },
- "menu": {
- "message": "Opsyon"
- },
- "message": {
- "message": "Mesaje"
- },
- "metamaskDescription": {
- "message": "MetaMask sekirize idantite pou Ethereum."
- },
- "metamaskSeedWords": {
- "message": "MetaMask Seed Mo"
- },
- "min": {
- "message": "Minimòm"
- },
- "myAccounts": {
- "message": "Kont mwen"
- },
- "mustSelectOne": {
- "message": "Ou dwe chwazi omwen 1 token."
- },
- "needEtherInWallet": {
- "message": "Pou kominike avèk aplikasyon desantralize ou dwe itilize MetaMask, ou pral bezwen Ether nan Wallet ou."
- },
- "needImportFile": {
- "message": "Ou dwe chwazi yon dosye pou enpòte.",
- "description": "User is important an account and needs to add a file to continue"
- },
- "needImportPassword": {
- "message": "Ou dwe antre nan yon modpas pou dosye ou te chwazi a.",
- "description": "Password and file needed to import an account"
- },
- "negativeETH": {
- "message": "Pa ka voye kantite lajan negatif ETH."
- },
- "networks": {
- "message": "Rezo"
- },
- "nevermind": {
- "message": "Pa pwoblèm"
- },
- "newAccount": {
- "message": "Nouvo Kont"
- },
- "newAccountNumberName": {
- "message": "Kont $1",
- "description": "Default name of next account to be created on create account screen"
- },
- "newContract": {
- "message": "Nouvo Kontra"
- },
- "newPassword": {
- "message": "Nouvo modpas (minit 8)"
- },
- "newRecipient": {
- "message": "Nouvo Benefisyè"
- },
- "newRPC": {
- "message": "Nouvo RPC URL"
- },
- "next": {
- "message": "Aprè sa"
- },
- "noAddressForName": {
- "message": "Pa gen adrès ki etabli pou non sa a."
- },
- "noDeposits": {
- "message": "Pa gen depo ou te resevwa"
- },
- "noConversionRateAvailable": {
- "message": "Pa gen okenn Konvèsyon Disponib"
- },
- "noTransactionHistory": {
- "message": "Pa gen istwa tranzaksyon."
- },
- "noTransactions": {
- "message": "Pa gen tranzaksyon"
- },
- "notFound": {
- "message": "Pa jwenn"
- },
- "notStarted": {
- "message": "Pa kòmanse"
- },
- "noWebcamFoundTitle": {
- "message": "Pa jwenn webcam"
- },
- "noWebcamFound": {
- "message": "Nou pakay jwenn webcam òdinatè ou. Tanpri eseye ankò."
- },
- "oldUI": {
- "message": "Ansyen Itilizatè kouòdone"
- },
- "oldUIMessage": {
- "message": "Ou te retounen nan Ansyen Itilizatè kouòdone. Ou ka chanje tounen nan nouvo Ansyen Itilizatè nan opsyon a nan meni an tèt la."
- },
- "openInTab": {
- "message": "Louvri nan etikèt"
- },
- "or": {
- "message": "oubyen",
- "description": "choice between creating or importing a new account"
- },
- "origin": {
- "message": "Orijin"
- },
- "password": {
- "message": "Modpas"
- },
- "passwordCorrect": {
- "message": "Tanpri asire ke modpas ou kòrèk."
- },
- "passwordMismatch": {
- "message": "modpas sa pa menm",
- "description": "in password creation process, the two new password fields did not match"
- },
- "passwordShort": {
- "message": "modpas pa sifi",
- "description": "in password creation process, the password is not long enough to be secure"
- },
- "pastePrivateKey": {
- "message": "Kole fraz prive ou a la:",
- "description": "For importing an account from a private key"
- },
- "pasteSeed": {
- "message": "Kole seed fraz ou a la!"
- },
- "pending": {
- "message": "l ap mache"
- },
- "personalAddressDetected": {
- "message": "Adrès pèsonèl detekte. Antre adrès kontra token la."
- },
- "pleaseReviewTransaction": {
- "message": "Tanpri revize tranzaksyon ou."
- },
- "popularTokens": {
- "message": "Popilè Tokens"
- },
- "prev": {
- "message": "Avan"
- },
- "privacyMsg": {
- "message": "Règleman sou enfòmasyon prive"
- },
- "privateKey": {
- "message": "Prive kle",
- "description": "select this type of file to use to import an account"
- },
- "privateKeyWarning": {
- "message": "Atansyon: pa janm divilge kle sa. Nenpòt moun kapab avèk kle prive ou a vòlè sa ou gen ou sou kont ou a."
- },
- "privateNetwork": {
- "message": "Rezo Prive"
- },
- "qrCode": {
- "message": "Montre QR Kòd"
- },
- "queue": {
- "message": "Queue"
- },
- "readdToken": {
- "message": "Ou ka ajoute token sa aprè sa ankò ou prale nan \"Ajoute token\" nan opsyon meni kont ou an."
- },
- "readMore": {
- "message": "Li plis isit la."
- },
- "readMore2": {
- "message": "Li plis isit la."
- },
- "receive": {
- "message": "Resevwa"
- },
- "recipientAddress": {
- "message": "Adrès pou resevwa"
- },
- "refundAddress": {
- "message": "Adrès pou resevwa"
- },
- "rejected": {
- "message": "Rejte"
- },
- "reset": {
- "message": "Repwograme"
- },
- "resetAccount": {
- "message": "Repwograme Kont"
- },
- "resetAccountDescription": {
- "message": "Repwograme kont a netwaye tranzaksyon ou yo."
- },
- "restoreFromSeed": {
- "message": "Restore kont?"
- },
- "restoreVault": {
- "message": "Retabli kazye"
- },
- "restoreAccountWithSeed": {
- "message": "Retabli kont ou avèk yo Seed Fraz"
- },
- "required": {
- "message": "Egzije"
- },
- "retryWithMoreGas": {
- "message": "Reseye ak yon pri gaz pi wo isit la"
- },
- "walletSeed": {
- "message": "Wallet Seed"
- },
- "restore": {
- "message": "Retabli"
- },
- "revealSeedWords": {
- "message": "Revele Seed Mo Yo"
- },
- "revealSeedWordsTitle": {
- "message": "Seed Fraz"
- },
- "revealSeedWordsDescription": {
- "message": "Si ou pa janm chanje navigatè ou deplase òdinatè, ou pral bezwen fraz seed la pou ka gen aksè a kont ou. Sere yo on kote an sekirite e an sekrè."
- },
- "revealSeedWordsWarningTitle": {
- "message": "PA pataje fraz sa a avèk nenpòt moun!"
- },
- "revealSeedWordsWarning": {
- "message": "Yo ka itilize mo sa pou vòlè kont ou."
- },
- "revert": {
- "message": "Retounen"
- },
- "remove": {
- "message": "retire"
- },
- "removeAccount": {
- "message": "Retire kont"
- },
- "removeAccountDescription": {
- "message": "Kont sa a pral retire nan Wallet ou. Tanpri, asire ou ke ou gen orijinal fraz seed la oubyen kle prive pou rantre kont lan avan ou kontinye. Oubyen ou ka rantre kont ou ankò apati kont \"drop-down\" ou an."
- },
- "readyToConnect": {
- "message": "Pare pou konekte?"
- },
- "rinkeby": {
- "message": "Rinkeby Tès Rezo"
- },
- "ropsten": {
- "message": "Ropsten Tès Rezo"
- },
- "rpc": {
- "message": "Koutim RPC"
- },
- "currentRpc": {
- "message": "Kounya RPC"
- },
- "connectingToMainnet": {
- "message": "Konekte ak Main (Prensipal) Ethereum Rezo a"
- },
- "connectingToRopsten": {
- "message": "Konekte ak Ropsten Tès Rezo a"
- },
- "connectingToKovan": {
- "message": "Konekte nan Kovan Tès Rezo a"
- },
- "connectingToRinkeby": {
- "message": "Konekte nan Rinkeby Tès Rezo a"
- },
- "connectingToUnknown": {
- "message": "Konekte nan rezo enkoni"
- },
- "sampleAccountName": {
- "message": "Pa egzanp, Nouvo kont mwen an",
- "description": "Help user understand concept of adding a human-readable name to their account"
- },
- "save": {
- "message": "Sove"
- },
- "speedUp": {
- "message": "pi vit"
- },
- "speedUpTitle": {
- "message": "Monte vitès tranzaksyon"
- },
- "speedUpSubtitle": {
- "message": "Ogmante pri gaz ou pou eseye efase tranzaksyon ou pi vit"
- },
- "saveAsCsvFile": {
- "message": "Sove kòm dosye CSV"
- },
- "saveAsFile": {
- "message": "Sove kòm dosye",
- "description": "Account export process"
- },
- "saveSeedAsFile": {
- "message": "Sove pawòl seed kòm dosye"
- },
- "search": {
- "message": "Rechèch"
- },
- "searchResults": {
- "message": "Rezilta rechèch"
- },
- "secretPhrase": {
- "message": "Antre fraz sekrè douz mo ou a pou w restore kòf ou a."
- },
- "showHexData": {
- "message": "Montre Hex Data"
- },
- "showHexDataDescription": {
- "message": "Pran sa pouw ka montre chan entèfas hex data a"
- },
- "newPassword8Chars": {
- "message": "Nouvo modpas (pou pi pit 8)"
- },
- "seedPhraseReq": {
- "message": "Seed fraz yo se 12 long mo"
- },
- "select": {
- "message": "Chwazi"
- },
- "selectCurrency": {
- "message": "Chwazi Lajan"
- },
- "selectService": {
- "message": "Chwazi Sèvis"
- },
- "selectType": {
- "message": "Chwazi Kalite"
- },
- "send": {
- "message": "Voye"
- },
- "sendETH": {
- "message": "Voye ETH"
- },
- "sendTokens": {
- "message": "Voye Tokens"
- },
- "sentEther": {
- "message": "Voye ether"
- },
- "sentTokens": {
- "message": "tokens deja voye"
- },
- "separateEachWord": {
- "message": "Separe chak mo ak yon sèl espas"
- },
- "onlySendToEtherAddress": {
- "message": "Sèlman voye ETH nan yon adrès Ethereum."
- },
- "onlySendTokensToAccountAddress": {
- "message": "Sèlman voye $ 1 nan yon adrès kont Ethereum.",
- "description": "displays token symbol"
- },
- "orderOneHere": {
- "message": "Mete nan lòd on Trezor oswa Ledger epi kenbe lajan ou nan yon stòk frèt."
- },
- "outgoing": {
- "message": "Ap kite"
- },
- "searchTokens": {
- "message": "Rechèch Tokens"
- },
- "selectAnAddress": {
- "message": "Chwazi yon adrès"
- },
- "selectAnAccount": {
- "message": "Chwazi yon kont"
- },
- "selectAnAccountHelp": {
- "message": "Chwazi kont pou wè nan MetaMask"
- },
- "selectHdPath": {
- "message": "Chwazi chemen HD"
- },
- "selectPathHelp": {
- "message": "Si ou pa wè kont Ledger ou te genyen an anba a, eseye chanje chemen an \"Eritaj (MEW / MyCrypto)\""
- },
- "sendTokensAnywhere": {
- "message": "Voye Tokens pou nenpòt moun ki gen yon kont Ethereum"
- },
- "settings": {
- "message": "Paramèt"
- },
- "step1HardwareWallet": {
- "message": "1. Konekte Materyèl bous"
- },
- "step1HardwareWalletMsg": {
- "message": "Konekte materyèl bous ou dirèkteman nan òdinatè ou."
- },
- "step2HardwareWallet": {
- "message": "2. Chwazi yon kont"
- },
- "step2HardwareWalletMsg": {
- "message": "Chwazi kont ou vle wè a. Ou ka chwazi youn sèlman nan yon moman."
- },
- "step3HardwareWallet": {
- "message": "3. Kòmanse itilize dApps ak plis ankò!"
- },
- "step3HardwareWalletMsg": {
- "message": "Sèvi ak kont materyèl ou menm jan ou t ap fè pou kont Etherum. Ouvri sesyon an nan dApps, voye Eth, achte ak stòke ERC20 tokens ak e ki pake chanje tokens tankou CryptoKitties."
- },
- "info": {
- "message": "Enfòmasyon"
- },
- "scanInstructions": {
- "message": "Mete kòd QR la devan kamera ou"
- },
- "scanQrCode": {
- "message": "Enspeksyon QR Kòd"
- },
- "shapeshiftBuy": {
- "message": "Achte avèk Shapeshift"
- },
- "showPrivateKeys": {
- "message": "Montre Kle Prive"
- },
- "showQRCode": {
- "message": "Montre Kòd QR"
- },
- "sign": {
- "message": "Siyen"
- },
- "signatureRequest": {
- "message": "Siyati Mande"
- },
- "signed": {
- "message": "Te Siyen"
- },
- "signMessage": {
- "message": "Siyen mesaj"
- },
- "signNotice": {
- "message": "Lè w siyen mesaj sa a ka gen efè segondè ki \ndanjere. Sèlman \nsit mesaj ki soti nan sit ou konplètman fè konfyans ak tout kont ou. \n Metòd danjere sa yo pral retire nan yon vèsyon fiti. "
- },
- "sigRequest": {
- "message": "Demann Siyati"
- },
- "sigRequested": {
- "message": "Demann Siyati"
- },
- "spaceBetween": {
- "message": "ka gen sèlman yon espas ant mo yo"
- },
- "status": {
- "message": "Kondisyon"
- },
- "stateLogs": {
- "message": "State Logs"
- },
- "stateLogsDescription": {
- "message": "State logs gen adrès kont piblik ou yo epi tranzaksyon ou te voye yo."
- },
- "stateLogError": {
- "message": "Erè nan retwouve State Logs yo."
- },
- "submit": {
- "message": "Soumèt"
- },
- "submitted": {
- "message": "Te Soumèt"
- },
- "supportCenter": {
- "message": "Vizite Sant Sipò Nou"
- },
- "symbolBetweenZeroTen": {
- "message": "Senbòl yo dwe ant 0 ak 10 karaktè."
- },
- "takesTooLong": {
- "message": "Pran twò lontan?"
- },
- "terms": {
- "message": "Tèm pou itilize"
- },
- "testFaucet": {
- "message": "Tès Tiyo"
- },
- "to": {
- "message": "Pou"
- },
- "toETHviaShapeShift": {
- "message": "$1 pou ETH pa ShapeShift",
- "description": "system will fill in deposit type in start of message"
- },
- "token": {
- "message": "Token"
- },
- "tokenAddress": {
- "message": "Adrès Token"
- },
- "tokenAlreadyAdded": {
- "message": "Ou te deja ajoute token."
- },
- "tokenBalance": {
- "message": "Balans Token ou se:"
- },
- "tokenSelection": {
- "message": "Chache Tokens oswa chwazi nan lis Tokens popilè nou an."
- },
- "tokenSymbol": {
- "message": "Token Senbòl"
- },
- "tokenWarning1": {
- "message": "Kenbe tras token yo ou te achte ak kont MetaMask ou. Si ou te achte tokens pandan wap itilize yon kont diferan tokens sa yo pa pral parèt la."
- },
- "total": {
- "message": "Total"
- },
- "transactions": {
- "message": "tranzaksyon yo"
- },
- "transactionConfirmed": {
- "message": "Tranzaksyon ou te konfime pou $2."
- },
- "transactionCreated": {
- "message": "Tranzaksyon ou te kreye avèk on valè de $1 pou $2."
- },
- "transactionDropped": {
- "message": "Tranzaksyon ou te tonbe a $2."
- },
- "transactionSubmitted": {
- "message": "Tranzaksyon ou te soumèt a $2."
- },
- "transactionUpdated": {
- "message": "Tranzaksyon ou te aktyalize a $2."
- },
- "transactionUpdatedGas": {
- "message": "Tranzaksyon ou te aktyalize avèk on pri gaz de $1 a $2."
- },
- "transactionError": {
- "message": "Erè tranzaksyon. Eksepsyon jete nan kòd kontra."
- },
- "transactionMemo": {
- "message": "Memo tranzaksyon (opsyonèl)"
- },
- "transactionNumber": {
- "message": "Nimewo Tranzaksyon"
- },
- "transfer": {
- "message": "Transfè"
- },
- "transfers": {
- "message": "Transfè yo"
- },
- "trezorHardwareWallet": {
- "message": "TREZOR Materyèl Bous"
- },
- "troubleTokenBalances": {
- "message": "Nou te gen pwoblèm chaje balans token ou. Ou ka wè yo ",
- "description": "Followed by a link (here) to view token balances"
- },
- "tryAgain": {
- "message": "Eseye anko"
- },
- "twelveWords": {
- "message": "12 mo sa yo se sèl fason pou retabli kont MetaMask ou yo. \nKenbe yo yon kote ki an sekirite ak sekrè."
- },
- "typePassword": {
- "message": "Tape modpas ou"
- },
- "uiWelcome": {
- "message": "Byenveni nan New itilizatè koòdone (Beta)"
- },
- "uiWelcomeMessage": {
- "message": "Kounya w ap itilize nouvo MetaMask UI (itilizatè koòdone) a."
- },
- "unapproved": {
- "message": "Pa apwouve"
- },
- "unavailable": {
- "message": "Pa disponib"
- },
- "units": {
- "message": "inite yo"
- },
- "unknown": {
- "message": "Enkoni"
- },
- "unknownFunction": {
- "message": "Fonksyon enkoni"
- },
- "unknownNetwork": {
- "message": "Rezo Prive Enkoni"
- },
- "unknownNetworkId": {
- "message": "Rezo ID Enkoni"
- },
- "unknownQrCode": {
- "message": "Erè: Nou pa t kapab idantifye QR kòd sa"
- },
- "unknownCameraErrorTitle": {
- "message": "Ooops! Yon bagay te ale mal...."
- },
- "unknownCameraError": {
- "message": "Te gen yon erè pandan y ap eseye jwenn aksè nan kamera ou. Tanpri eseye ankò..."
- },
- "unlock": {
- "message": "Debloke"
- },
- "unlockMessage": {
- "message": "Entènèt desantralize a ap tann"
- },
- "uriErrorMsg": {
- "message": "URIs mande pou apwopriye prefiks HTTP / HTTPS a."
- },
- "usaOnly": {
- "message": "USA sèlman",
- "description": "Using this exchange is limited to people inside the USA"
- },
- "usedByClients": {
- "message": "Itilize pa yon varyete de kliyan diferan"
- },
- "useOldUI": {
- "message": "Itilizasyon ansyen UI (itilizatè koòdone)"
- },
- "validFileImport": {
- "message": "Ou dwe chwazi yon dosye ki valab pou enpòte."
- },
- "vaultCreated": {
- "message": "Kòf Kreye"
- },
- "viewAccount": {
- "message": "Wè Kont"
- },
- "viewOnEtherscan": {
- "message": "Wè sou Etherscan"
- },
- "visitWebSite": {
- "message": "Vizite sit entènèt nou an"
- },
- "warning": {
- "message": "Avètisman"
- },
- "welcomeBack": {
- "message": "Bon retou!"
- },
- "welcomeBeta": {
- "message": "Byenveni nan MetaMask Beta"
- },
- "whatsThis": {
- "message": "Kisa sa ye?"
- },
- "youNeedToAllowCameraAccess": {
- "message": "Ou bezwen bay kamera aksè pou sèvi ak fonksyon sa."
- },
- "yourSigRequested": {
- "message": "Yo mande siyati ou"
- },
- "youSign": {
- "message": "Ou ap siyen kounya"
- },
- "yourPrivateSeedPhrase": {
- "message": "Seed fraz prive ou a"
- }
+ "accept": {
+ "message": "Aksepte"
+ },
+ "accessingYourCamera": {
+ "message": "Aksè a Kamera"
+ },
+ "account": {
+ "message": "Kont"
+ },
+ "accountDetails": {
+ "message": "Detay Kont"
+ },
+ "accountName": {
+ "message": "Non Kont"
+ },
+ "accountOptions": {
+ "message": "Opsyon kont"
+ },
+ "accountSelectionRequired": {
+ "message": "Ou bezwen chwazi yon kont!"
+ },
+ "activityLog": {
+ "message": "aktivite ki fèt"
+ },
+ "address": {
+ "message": "Adrès"
+ },
+ "addCustomToken": {
+ "message": "Ajoute token"
+ },
+ "addToken": {
+ "message": "Ajoute Token"
+ },
+ "addTokens": {
+ "message": "Ajoute Token"
+ },
+ "addSuggestedTokens": {
+ "message": "Ajoute Token Yo Sikjere W"
+ },
+ "addAcquiredTokens": {
+ "message": "Ajoute tokens yo ou te achte lè l sèvi avèk MetaMask"
+ },
+ "amount": {
+ "message": "Kantite lajan"
+ },
+ "amountPlusGas": {
+ "message": "Kantite lajan + Gaz"
+ },
+ "appDescription": {
+ "message": "Ekstansyon Navigatè Ethereum",
+ "description": "The description of the application"
+ },
+ "appName": {
+ "message": "MetaMask",
+ "description": "The name of the application"
+ },
+ "approve": {
+ "message": "Apwouve"
+ },
+ "approved": {
+ "message": "Apwouve"
+ },
+ "attemptingConnect": {
+ "message": "Eseye konekte nan blockchain."
+ },
+ "attemptToCancel": {
+ "message": "Eseye anile?"
+ },
+ "attemptToCancelDescription": {
+ "message": "Soumèt tantativ sa a pa garanti ke yo pral anile tranzaksyon ou anile. Si tantativ anile an gen siksè, ou pral chaje frè yo tranzaksyon pi wo a."
+ },
+ "attributions": {
+ "message": "Atribisyon"
+ },
+ "available": {
+ "message": "Disponib"
+ },
+ "back": {
+ "message": "Retounen"
+ },
+ "balance": {
+ "message": "Balans"
+ },
+ "balances": {
+ "message": "Balans Token"
+ },
+ "balanceIsInsufficientGas": {
+ "message": "Ensifizan balans pou total gaz aktyèl la"
+ },
+ "beta": {
+ "message": "BETA"
+ },
+ "betweenMinAndMax": {
+ "message": "dwe plis pase oswa egal a $ 1 mwens ke oswa egal a $ 2.",
+ "description": "helper for inputting hex as decimal input"
+ },
+ "blockiesIdenticon": {
+ "message": "Itilize Blockies Identicon"
+ },
+ "borrowDharma": {
+ "message": "Prete Avèk Dharma (Beta)"
+ },
+ "browserNotSupported": {
+ "message": "Navigatè ou a pa sipòte..."
+ },
+ "builtInCalifornia": {
+ "message": "MetaMask fèt e bati nan California."
+ },
+ "buy": {
+ "message": "Achte"
+ },
+ "buyCoinbase": {
+ "message": "Achte sou Coinbase"
+ },
+ "buyCoinbaseExplainer": {
+ "message": "Coinbase se fason ki pi popilè nan mond lan yo achte ak vann Bitcoin, Ethereum, ak Litecoin."
+ },
+ "bytes": {
+ "message": "Bytes"
+ },
+ "ok": {
+ "message": "Oke"
+ },
+ "cancel": {
+ "message": "Anile"
+ },
+ "cancelAttempt": {
+ "message": "Teste Anile"
+ },
+ "cancellationGasFee": {
+ "message": "Anilasyon Gaz Chaj"
+ },
+ "cancelN": {
+ "message": "Anile tout $ 1 tranzaksyon"
+ },
+ "classicInterface": {
+ "message": "Sèvi ak fas klasik la"
+ },
+ "clickCopy": {
+ "message": "Klike sou kopi"
+ },
+ "clickToAdd": {
+ "message": "Klike sou $ 1 pou ajoute yo nan kont ou"
+ },
+ "close": {
+ "message": "Fèmen"
+ },
+ "chromeRequiredForHardwareWallets": {
+ "message": "Ou bezwen sèvi ak MetaMask sou Google Chrome yo nan lòd yo konekte sou Hardware Wallet."
+ },
+ "confirm": {
+ "message": "Konfime"
+ },
+ "confirmed": {
+ "message": "Konfime"
+ },
+ "confirmContract": {
+ "message": "Konfime Kontra"
+ },
+ "confirmPassword": {
+ "message": "Konfime Modpas"
+ },
+ "confirmTransaction": {
+ "message": "Konfime Tranzaksyon"
+ },
+ "connectHardwareWallet": {
+ "message": "Konekte Materyèl Wallet"
+ },
+ "connect": {
+ "message": "Konekte"
+ },
+ "connecting": {
+ "message": "Koneksyon..."
+ },
+ "connectingToKovan": {
+ "message": "Konekte nan Kovan Tès Rezo a"
+ },
+ "connectingToMainnet": {
+ "message": "Konekte ak Prensipal Ethereum Rezo a"
+ },
+ "connectingToRopsten": {
+ "message": "Konekte ak Ropsten Tès Rezo a"
+ },
+ "connectingToRinkeby": {
+ "message": "Konekte nan Rinkeby Tès Rezo a"
+ },
+ "connectingToUnknown": {
+ "message": "Konekte nan rezo enkoni"
+ },
+ "connectToLedger": {
+ "message": "Konekte ak Ledger"
+ },
+ "connectToTrezor": {
+ "message": "Konekte ak Trezor"
+ },
+ "continue": {
+ "message": "Kontinye"
+ },
+ "continueToCoinbase": {
+ "message": "Kontinye Coinbase"
+ },
+ "contractDeployment": {
+ "message": "Kontra Deplwaman"
+ },
+ "conversionProgress": {
+ "message": "Konvèsyon nan Pwogrè"
+ },
+ "copiedButton": {
+ "message": "Kopye"
+ },
+ "copiedClipboard": {
+ "message": "Kopi nan Clipboard"
+ },
+ "copiedExclamation": {
+ "message": "Kopye!"
+ },
+ "copiedSafe": {
+ "message": "Mwen te kopye li yon kote ki san danje"
+ },
+ "copy": {
+ "message": "Kopye"
+ },
+ "copyAddress": {
+ "message": "Kopi adrès clipboard"
+ },
+ "copyToClipboard": {
+ "message": "Kopi clipboard"
+ },
+ "copyButton": {
+ "message": " Kopi "
+ },
+ "copyPrivateKey": {
+ "message": "Sa a se kle prive ou (klike pou ou kopye)"
+ },
+ "create": {
+ "message": "Kreye"
+ },
+ "createAccount": {
+ "message": "Kreye Kont"
+ },
+ "createDen": {
+ "message": "Kreye"
+ },
+ "crypto": {
+ "message": "Crypto",
+ "description": "Exchange type (cryptocurrencies)"
+ },
+ "currentConversion": {
+ "message": "Konvèsyon aktyèl"
+ },
+ "currentLanguage": {
+ "message": "Lang Aktyèl"
+ },
+ "currentNetwork": {
+ "message": "Rezo aktyèl"
+ },
+ "currentRpc": {
+ "message": "Aktyèl RPC"
+ },
+ "customGas": {
+ "message": "Koutim Gaz"
+ },
+ "customToken": {
+ "message": "Koutim Token"
+ },
+ "customize": {
+ "message": "Koutim"
+ },
+ "customRPC": {
+ "message": "Koutim RPC"
+ },
+ "decimalsMustZerotoTen": {
+ "message": "Desimal yo dwe omwen 0, epi pa dwe plis pase 36."
+ },
+ "decimal": {
+ "message": "Presizyon desimal la"
+ },
+ "defaultNetwork": {
+ "message": "Dfo rezo a pou tranzaksyon Ether se Mainnet."
+ },
+ "denExplainer": {
+ "message": "DEN ou se depo modpas avèk chif ou nan MetaMask."
+ },
+ "deposit": {
+ "message": "Depo"
+ },
+ "depositBTC": {
+ "message": "Depoze BTC ou nan adrès ki anba a:"
+ },
+ "depositCoin": {
+ "message": "Depoze $1 ou nan adrès ki anba a",
+ "description": "Tells the user what coin they have selected to deposit with shapeshift"
+ },
+ "depositEth": {
+ "message": "Depo Eth"
+ },
+ "depositEther": {
+ "message": "Depo Ether"
+ },
+ "depositFiat": {
+ "message": "Depo ak Fiat"
+ },
+ "depositFromAccount": {
+ "message": "Depo nan yon lòt kont"
+ },
+ "depositShapeShift": {
+ "message": "Depo avèk ShapeShift"
+ },
+ "depositShapeShiftExplainer": {
+ "message": "Si ou posede lòt cryptocurrencies, ou ka chanje ak depo Ether dirèkteman nan Wallet MetaMask ou. Pa gen kont ki nesesè."
+ },
+ "details": {
+ "message": "Detay yo"
+ },
+ "directDeposit": {
+ "message": "Depo Dirèk"
+ },
+ "directDepositEther": {
+ "message": "Dirèkteman Depo Ether"
+ },
+ "directDepositEtherExplainer": {
+ "message": "Si ou deja gen kèk Ether, fason ki pi rapid yo ka resevwa Ether nan nouvo Wallet ou pa depo dirèk."
+ },
+ "done": {
+ "message": "Fini"
+ },
+ "downloadGoogleChrome": {
+ "message": "Telechaje Google Chrome"
+ },
+ "downloadStateLogs": {
+ "message": "Telechaje State Logs"
+ },
+ "dontHaveAHardwareWallet": {
+ "message": "Pa gen yon materyèl bous?"
+ },
+ "dropped": {
+ "message": "Tonbe"
+ },
+ "edit": {
+ "message": "Korije"
+ },
+ "editAccountName": {
+ "message": "Korije Non Kont"
+ },
+ "editingTransaction": {
+ "message": "Fè chanjman nan tranzaksyon ou"
+ },
+ "emailUs": {
+ "message": "Imèl nou!"
+ },
+ "encryptNewDen": {
+ "message": "Ankripte nouvo DEN ou"
+ },
+ "ensNameNotFound": {
+ "message": "Nou pa jwenn non ENS ou a"
+ },
+ "enterPassword": {
+ "message": "Mete modpas"
+ },
+ "enterPasswordConfirm": {
+ "message": "Antre nan modpas ou a konfime"
+ },
+ "enterPasswordContinue": {
+ "message": "Mete modpas pou kontinye"
+ },
+ "eth": {
+ "message": "ETH"
+ },
+ "etherscanView": {
+ "message": "Gade kont sou Etherscan"
+ },
+ "exchangeRate": {
+ "message": "Chanje to"
+ },
+ "expandView": {
+ "message": "Elaji Wè"
+ },
+ "exportPrivateKey": {
+ "message": "Voye Kòd Prive"
+ },
+ "exportPrivateKeyWarning": {
+ "message": "Voye kle prive ak pwòp risk ou."
+ },
+ "failed": {
+ "message": "Tonbe"
+ },
+ "fiat": {
+ "message": "FIAT",
+ "description": "Exchange type"
+ },
+ "fileImportFail": {
+ "message": "Enpòte dosye ki pa travay? Klike la a!",
+ "description": "Helps user import their account from a JSON file"
+ },
+ "followTwitter": {
+ "message": "Swiv nou sou Twitter"
+ },
+ "forgetDevice": {
+ "message": "Bliye aparèy sa a"
+ },
+ "from": {
+ "message": "Soti nan"
+ },
+ "fromToSame": {
+ "message": "Adrès orijinal le ak sa ou resevwa pake menm"
+ },
+ "fromShapeShift": {
+ "message": "Soti nan ShapeShift"
+ },
+ "functionType": {
+ "message": "Kalite Fonksyon"
+ },
+ "gas": {
+ "message": "Gaz",
+ "description": "Short indication of gas cost"
+ },
+ "gasFee": {
+ "message": "Frè gaz"
+ },
+ "gasLimit": {
+ "message": "Limit gaz"
+ },
+ "gasLimitCalculation": {
+ "message": "Nou kalkile gaz limit sijere a ki baze sou pousantaj siksè rezo a."
+ },
+ "gasLimitRequired": {
+ "message": "Limit gaz nesesè"
+ },
+ "gasLimitTooLow": {
+ "message": "Limit gaz dwe omwen 21000"
+ },
+ "gasUsed": {
+ "message": "Gaz yo Itilize"
+ },
+ "generatingSeed": {
+ "message": "Grenn jenerasyon..."
+ },
+ "gasPrice": {
+ "message": "Pri gaz (GWEI)"
+ },
+ "gasPriceCalculation": {
+ "message": "Nou kalkile pri yo gaz ki sijere ki baze sou pousantaj siksè rezo."
+ },
+ "gasPriceRequired": {
+ "message": "Pri Gaz la Egzije"
+ },
+ "generatingTransaction": {
+ "message": "Tranzaksyon kap fè"
+ },
+ "getEther": {
+ "message": "Jwenn Ether"
+ },
+ "getEtherFromFaucet": {
+ "message": "Jwenn Ether nan yon tiyo pou $1 la",
+ "description": "Displays network name for Ether faucet"
+ },
+ "getHelp": {
+ "message": "Jwenn èd."
+ },
+ "greaterThanMin": {
+ "message": "dwe pi gran pase oswa egal a $ 1.",
+ "description": "helper for inputting hex as decimal input"
+ },
+ "hardware": {
+ "message": "materyèl"
+ },
+ "hardwareWalletConnected": {
+ "message": "Materyèl Wallet konekte"
+ },
+ "hardwareWallets": {
+ "message": "Materyèl Wallet konekte"
+ },
+ "hardwareWalletsMsg": {
+ "message": "Chwazi yon Materyèl Wallet ou ta renmen itilize ak MetaMask"
+ },
+ "havingTroubleConnecting": {
+ "message": "Èske w gen pwoblèm pou konekte?"
+ },
+ "here": {
+ "message": "isit la",
+ "description": "as in -click here- for more information (goes with troubleTokenBalances)"
+ },
+ "hereList": {
+ "message": "Isit la nan yon lis !!!!"
+ },
+ "hexData": {
+ "message": "Hex Data"
+ },
+ "hide": {
+ "message": "Kache"
+ },
+ "hideToken": {
+ "message": "Kache Token"
+ },
+ "hideTokenPrompt": {
+ "message": "Kache Token?"
+ },
+ "history": {
+ "message": "Istwa"
+ },
+ "howToDeposit": {
+ "message": "Ki jan ou ta renmen depo Ether?"
+ },
+ "holdEther": {
+ "message": "Li pèmèt ou kenbe ether & tokens, epi sèvi kòm on pon pou desantralize aplikasyon."
+ },
+ "import": {
+ "message": "Pòte",
+ "description": "Button to import an account from a selected file"
+ },
+ "importAccount": {
+ "message": "Pòte Kont"
+ },
+ "importAccountMsg": {
+ "message": " Kont pòte pa pral asosye avèk orijinal ou te kreye nan kont MetaMask seed fraz. Aprann plis sou kont enpòte "
+ },
+ "importAnAccount": {
+ "message": "Pòte yon kont"
+ },
+ "importDen": {
+ "message": "Pòte ki deja egziste DEN"
+ },
+ "imported": {
+ "message": "Pòte",
+ "description": "status showing that an account has been fully loaded into the keyring"
+ },
+ "importUsingSeed": {
+ "message": "Pòte lè sèvi avèk seed fraz"
+ },
+ "info": {
+ "message": "Enfo"
+ },
+ "infoHelp": {
+ "message": "Enfo & Èd"
+ },
+ "initialTransactionConfirmed": {
+ "message": "Premye tranzaksyon ou konfime sou rezo a. Klike sou OK pou tounen."
+ },
+ "insufficientFunds": {
+ "message": "Lajan ensifizan."
+ },
+ "insufficientTokens": {
+ "message": "Tokens pa valab."
+ },
+ "invalidAddress": {
+ "message": "Adrès pa valab"
+ },
+ "invalidAddressRecipient": {
+ "message": "Moun ki resevwa adrès la pa valab"
+ },
+ "invalidGasParams": {
+ "message": "Gaz Paramèt la pa valab"
+ },
+ "invalidInput": {
+ "message": "Sa ou rantre a pa valab"
+ },
+ "invalidRequest": {
+ "message": "Demann pa valab"
+ },
+ "invalidRPC": {
+ "message": "RPC URI pa valab"
+ },
+ "invalidSeedPhrase": {
+ "message": "Seed fraz pa valab"
+ },
+ "jsonFail": {
+ "message": "Yon bagay ale mal. Tanpri, asire w ke dosye JSON ou an byen fòmate."
+ },
+ "jsonFile": {
+ "message": "JSON Dosye",
+ "description": "format for importing an account"
+ },
+ "keepTrackTokens": {
+ "message": "Gade tokens yo ou te achte ak kont MetaMask ou."
+ },
+ "kovan": {
+ "message": "Kovan Tès Rezo"
+ },
+ "knowledgeDataBase": {
+ "message": "Vizite baz nou an"
+ },
+ "max": {
+ "message": "Maksimòm"
+ },
+ "learnMore": {
+ "message": "Aprann plis"
+ },
+ "ledgerAccountRestriction": {
+ "message": "Ou bezwen sèvi ak dènye kont ou anvan ou ka ajoute yon nouvo."
+ },
+ "lessThanMax": {
+ "message": "dwe mwens pase oswa egal a $ 1.",
+ "description": "helper for inputting hex as decimal input"
+ },
+ "likeToAddTokens": {
+ "message": "Èske ou ta renmen ajoute sa nan tokens?"
+ },
+ "links": {
+ "message": "Lyen"
+ },
+ "limit": {
+ "message": "Limitasyon"
+ },
+ "loading": {
+ "message": "Telechaje..."
+ },
+ "loadingTokens": {
+ "message": "Telechaje Tokens..."
+ },
+ "localhost": {
+ "message": "Localhost 8545"
+ },
+ "login": {
+ "message": "Ouvri"
+ },
+ "logout": {
+ "message": "Dekonekte"
+ },
+ "loose": {
+ "message": "Pèdi"
+ },
+ "loweCaseWords": {
+ "message": "seed mo sèlman gen karaktè miniskil"
+ },
+ "mainnet": {
+ "message": "Prensipal Ethereum Rezo a"
+ },
+ "menu": {
+ "message": "Opsyon"
+ },
+ "message": {
+ "message": "Mesaje"
+ },
+ "metamaskDescription": {
+ "message": "MetaMask sekirize idantite pou Ethereum."
+ },
+ "metamaskSeedWords": {
+ "message": "MetaMask Seed Mo"
+ },
+ "metamaskVersion": {
+ "message": "MetaMask Vèsyon"
+ },
+ "min": {
+ "message": "Minimòm"
+ },
+ "missingYourTokens": {
+ "message": "Ou pa wè token ou a?"
+ },
+ "myAccounts": {
+ "message": "Kont mwen"
+ },
+ "mustSelectOne": {
+ "message": "Ou dwe chwazi omwen 1 token."
+ },
+ "needEtherInWallet": {
+ "message": "Pou kominike avèk aplikasyon desantralize ou dwe itilize MetaMask, ou pral bezwen Ether nan Wallet ou."
+ },
+ "needImportFile": {
+ "message": "Ou dwe chwazi yon dosye pou enpòte.",
+ "description": "User is important an account and needs to add a file to continue"
+ },
+ "needImportPassword": {
+ "message": "Ou dwe antre nan yon modpas pou dosye ou te chwazi a.",
+ "description": "Password and file needed to import an account"
+ },
+ "negativeETH": {
+ "message": "Pa ka voye kantite lajan negatif ETH."
+ },
+ "networks": {
+ "message": "Rezo"
+ },
+ "nevermind": {
+ "message": "Pa pwoblèm"
+ },
+ "newAccount": {
+ "message": "Nouvo Kont"
+ },
+ "newAccountNumberName": {
+ "message": "Kont $1",
+ "description": "Default name of next account to be created on create account screen"
+ },
+ "newContract": {
+ "message": "Nouvo Kontra"
+ },
+ "newPassword": {
+ "message": "Nouvo modpas (minit 8)"
+ },
+ "newPassword8Chars": {
+ "message": "Nouvo modpas (minit 8)"
+ },
+ "newRecipient": {
+ "message": "Nouvo Benefisyè"
+ },
+ "newRPC": {
+ "message": "Nouvo RPC URL"
+ },
+ "next": {
+ "message": "Aprè sa"
+ },
+ "noAddressForName": {
+ "message": "Pa gen adrès ki etabli pou non sa a."
+ },
+ "noDeposits": {
+ "message": "Pa gen depo ou te resevwa"
+ },
+ "noConversionRateAvailable": {
+ "message": "Pa gen okenn Konvèsyon Disponib"
+ },
+ "noTransactionHistory": {
+ "message": "Pa gen istwa tranzaksyon."
+ },
+ "noTransactions": {
+ "message": "Pa gen tranzaksyon"
+ },
+ "notFound": {
+ "message": "Pa jwenn"
+ },
+ "notStarted": {
+ "message": "Pa kòmanse"
+ },
+ "noWebcamFoundTitle": {
+ "message": "Pa jwenn webcam"
+ },
+ "noWebcamFound": {
+ "message": "Nou pakay jwenn webcam òdinatè ou. Tanpri eseye ankò."
+ },
+ "oldUI": {
+ "message": "Ansyen Itilizatè kouòdone"
+ },
+ "oldUIMessage": {
+ "message": "Ou te retounen nan Ansyen Itilizatè kouòdone. Ou ka chanje tounen nan nouvo Ansyen Itilizatè nan opsyon a nan meni an tèt la."
+ },
+ "onlySendToEtherAddress": {
+ "message": "Sèlman voye ETH nan yon adrès Ethereum."
+ },
+ "onlySendTokensToAccountAddress": {
+ "message": "Sèlman voye $ 1 nan yon adrès kont Ethereum.",
+ "description": "displays token symbol"
+ },
+ "openInTab": {
+ "message": "Louvri nan etikèt"
+ },
+ "or": {
+ "message": "oubyen",
+ "description": "choice between creating or importing a new account"
+ },
+ "orderOneHere": {
+ "message": "Mete nan lòd on Trezor oswa Ledger epi kenbe lajan ou nan yon stòk frèt."
+ },
+ "origin": {
+ "message": "Orijin"
+ },
+ "outgoing": {
+ "message": "Ap kite"
+ },
+ "parameters": {
+ "message": "Paramèt"
+ },
+ "password": {
+ "message": "Modpas"
+ },
+ "passwordCorrect": {
+ "message": "Tanpri asire ke modpas ou kòrèk."
+ },
+ "passwordsDontMatch": {
+ "message": "Modpas pa matche"
+ },
+ "passwordMismatch": {
+ "message": "modpas sa pa menm",
+ "description": "in password creation process, the two new password fields did not match"
+ },
+ "passwordNotLongEnough": {
+ "message": "Modpas pa lontan ase"
+ },
+ "passwordShort": {
+ "message": "modpas pa sifi",
+ "description": "in password creation process, the password is not long enough to be secure"
+ },
+ "pastePrivateKey": {
+ "message": "Kole fraz prive ou a la:",
+ "description": "For importing an account from a private key"
+ },
+ "pasteSeed": {
+ "message": "Kole seed fraz ou a la!"
+ },
+ "pending": {
+ "message": "l ap mache"
+ },
+ "personalAddressDetected": {
+ "message": "Adrès pèsonèl detekte. Antre adrès kontra token la."
+ },
+ "pleaseReviewTransaction": {
+ "message": "Tanpri revize tranzaksyon ou."
+ },
+ "popularTokens": {
+ "message": "Popilè Tokens"
+ },
+ "prev": {
+ "message": "Avan"
+ },
+ "primaryCurrencySetting": {
+ "message": "Lajan ou itilize pi plis la"
+ },
+ "primaryCurrencySettingDescription": {
+ "message": "Chwazi ETH pou bay priyorite montre valè nan ETH. Chwazi Fiat priyorite montre valè nan lajan ou chwazi a."
+ },
+ "privacyMsg": {
+ "message": "Règleman sou enfòmasyon prive"
+ },
+ "privateKey": {
+ "message": "Prive kle",
+ "description": "select this type of file to use to import an account"
+ },
+ "privateKeyWarning": {
+ "message": "Atansyon: pa janm divilge kle sa. Nenpòt moun kapab avèk kle prive ou a vòlè sa ou gen ou sou kont ou a."
+ },
+ "privateNetwork": {
+ "message": "Rezo Prive"
+ },
+ "qrCode": {
+ "message": "Montre QR Kòd"
+ },
+ "queue": {
+ "message": "Queue"
+ },
+ "readdToken": {
+ "message": "Ou ka ajoute token sa aprè sa ankò ou prale nan \"Ajoute token\" nan opsyon meni kont ou an."
+ },
+ "readMore": {
+ "message": "Li plis isit la."
+ },
+ "readMore2": {
+ "message": "Li plis isit la."
+ },
+ "receive": {
+ "message": "Resevwa"
+ },
+ "recipientAddress": {
+ "message": "Adrès pou resevwa"
+ },
+ "refundAddress": {
+ "message": "Adrès pou resevwa"
+ },
+ "reject": {
+ "message": "Rejte"
+ },
+ "rejectAll": {
+ "message": "Rejte Tout"
+ },
+ "rejectTxsN": {
+ "message": "Rejete $ 1 tranzaksyon"
+ },
+ "rejectTxsDescription": {
+ "message": "Ou se sou rejte $ 1 yon anpil nan tranzaksyon yo."
+ },
+ "rejected": {
+ "message": "Rejete"
+ },
+ "reset": {
+ "message": "Repwograme"
+ },
+ "resetAccount": {
+ "message": "Repwograme Kont"
+ },
+ "resetAccountDescription": {
+ "message": "Repwograme kont a netwaye tranzaksyon ou yo."
+ },
+ "restoreFromSeed": {
+ "message": "Restore kont?"
+ },
+ "restoreVault": {
+ "message": "Retabli kazye"
+ },
+ "restoreAccountWithSeed": {
+ "message": "Retabli kont ou avèk yo Seed Fraz"
+ },
+ "required": {
+ "message": "Egzije"
+ },
+ "retryWithMoreGas": {
+ "message": "Reseye ak yon pri gaz pi wo isit la"
+ },
+ "restore": {
+ "message": "Retabli"
+ },
+ "revealSeedWords": {
+ "message": "Revele Seed Mo Yo"
+ },
+ "revealSeedWordsTitle": {
+ "message": "Seed Fraz"
+ },
+ "revealSeedWordsDescription": {
+ "message": "Si ou pa janm chanje navigatè ou deplase òdinatè, ou pral bezwen fraz seed la pou ka gen aksè a kont ou. Sere yo on kote an sekirite e an sekrè."
+ },
+ "revealSeedWordsWarningTitle": {
+ "message": "PA pataje fraz sa a avèk nenpòt moun!"
+ },
+ "revealSeedWordsWarning": {
+ "message": "Yo ka itilize mo sa pou vòlè kont ou."
+ },
+ "revert": {
+ "message": "Retounen"
+ },
+ "remove": {
+ "message": "retire"
+ },
+ "removeAccount": {
+ "message": "Retire kont"
+ },
+ "removeAccountDescription": {
+ "message": "Kont sa a pral retire nan Wallet ou. Tanpri, asire ou ke ou gen orijinal fraz seed la oubyen kle prive pou rantre kont lan avan ou kontinye. Oubyen ou ka rantre kont ou ankò apati kont \"drop-down\" ou an."
+ },
+ "readyToConnect": {
+ "message": "Pare pou konekte?"
+ },
+ "rinkeby": {
+ "message": "Rinkeby Tès Rezo"
+ },
+ "ropsten": {
+ "message": "Ropsten Tès Rezo"
+ },
+ "rpc": {
+ "message": "Koutim RPC"
+ },
+ "sampleAccountName": {
+ "message": "Pa egzanp, Nouvo kont mwen an",
+ "description": "Help user understand concept of adding a human-readable name to their account"
+ },
+ "save": {
+ "message": "Sove"
+ },
+ "saveAsCsvFile": {
+ "message": "Sove kòm dosye CSV"
+ },
+ "saveAsFile": {
+ "message": "Sove kòm dosye",
+ "description": "Account export process"
+ },
+ "saveSeedAsFile": {
+ "message": "Sove pawòl seed kòm dosye"
+ },
+ "scanInstructions": {
+ "message": "Mete kòd QR la devan kamera ou"
+ },
+ "scanQrCode": {
+ "message": "Enspeksyon QR Kòd"
+ },
+ "search": {
+ "message": "Rechèch"
+ },
+ "searchResults": {
+ "message": "Rezilta rechèch"
+ },
+ "secretPhrase": {
+ "message": "Antre fraz sekrè douz mo ou a pou w restore kòf ou a."
+ },
+ "seedPhraseReq": {
+ "message": "Seed fraz yo se 12 long mo"
+ },
+ "select": {
+ "message": "Chwazi"
+ },
+ "selectCurrency": {
+ "message": "Chwazi Lajan"
+ },
+ "selectLocale": {
+ "message": "Chwazi Lokasyon"
+ },
+ "selectService": {
+ "message": "Chwazi Sèvis"
+ },
+ "selectType": {
+ "message": "Chwazi Kalite"
+ },
+ "send": {
+ "message": "Voye"
+ },
+ "sendETH": {
+ "message": "Voye ETH"
+ },
+ "sendTokens": {
+ "message": "Voye Tokens"
+ },
+ "sentEther": {
+ "message": "Voye ether"
+ },
+ "sentTokens": {
+ "message": "tokens deja voye"
+ },
+ "separateEachWord": {
+ "message": "Separe chak mo ak yon sèl espas"
+ },
+ "searchTokens": {
+ "message": "Rechèch Tokens"
+ },
+ "selectAnAddress": {
+ "message": "Chwazi yon adrès"
+ },
+ "selectAnAccount": {
+ "message": "Chwazi yon kont"
+ },
+ "selectAnAccountHelp": {
+ "message": "Chwazi kont pou wè nan MetaMask"
+ },
+ "selectHdPath": {
+ "message": "Chwazi chemen HD"
+ },
+ "selectPathHelp": {
+ "message": "Si ou pa wè kont Ledger ou te genyen an anba a, eseye chanje chemen an \"Eritaj (MEW / MyCrypto)\""
+ },
+ "sendTokensAnywhere": {
+ "message": "Voye Tokens pou nenpòt moun ki gen yon kont Ethereum"
+ },
+ "settings": {
+ "message": "Paramèt"
+ },
+ "shapeshiftBuy": {
+ "message": "Achte avèk Shapeshift"
+ },
+ "showPrivateKeys": {
+ "message": "Montre Kle Prive"
+ },
+ "showQRCode": {
+ "message": "Montre Kòd QR"
+ },
+ "showHexData": {
+ "message": "Montre Hex Data"
+ },
+ "showHexDataDescription": {
+ "message": "Pran sa pouw ka montre chan entèfas hex data a"
+ },
+ "sign": {
+ "message": "Siyen"
+ },
+ "signatureRequest": {
+ "message": "Siyati Mande"
+ },
+ "signed": {
+ "message": "Te Siyen"
+ },
+ "signMessage": {
+ "message": "Siyen mesaj"
+ },
+ "signNotice": {
+ "message": "Lè w siyen mesaj sa a ka gen efè segondè ki \ndanjere. Sèlman \nsit mesaj ki soti nan sit ou konplètman fè konfyans ak tout kont ou. \n Metòd danjere sa yo pral retire nan yon vèsyon fiti. "
+ },
+ "sigRequest": {
+ "message": "Demann Siyati"
+ },
+ "sigRequested": {
+ "message": "Demann Siyati"
+ },
+ "spaceBetween": {
+ "message": "ka gen sèlman yon espas ant mo yo"
+ },
+ "speedUp": {
+ "message": "pi vit"
+ },
+ "speedUpTitle": {
+ "message": "Monte vitès tranzaksyon"
+ },
+ "speedUpSubtitle": {
+ "message": "Ogmante pri gaz ou pou eseye efase tranzaksyon ou pi vit"
+ },
+ "status": {
+ "message": "Kondisyon"
+ },
+ "stateLogs": {
+ "message": "State Logs"
+ },
+ "stateLogsDescription": {
+ "message": "State logs gen adrès kont piblik ou yo epi tranzaksyon ou te voye yo."
+ },
+ "stateLogError": {
+ "message": "Erè nan retwouve State Logs yo."
+ },
+ "step1HardwareWallet": {
+ "message": "1. Konekte Materyèl bous"
+ },
+ "step1HardwareWalletMsg": {
+ "message": "Konekte materyèl bous ou dirèkteman nan òdinatè ou."
+ },
+ "step2HardwareWallet": {
+ "message": "2. Chwazi yon kont"
+ },
+ "step2HardwareWalletMsg": {
+ "message": "Chwazi kont ou vle wè a. Ou ka chwazi youn sèlman nan yon moman."
+ },
+ "step3HardwareWallet": {
+ "message": "3. Kòmanse itilize dApps ak plis ankò!"
+ },
+ "step3HardwareWalletMsg": {
+ "message": "Sèvi ak kont materyèl ou menm jan ou t ap fè pou kont Etherum. Ouvri sesyon an nan dApps, voye Eth, achte ak stòke ERC20 tokens ak e ki pake chanje tokens tankou CryptoKitties."
+ },
+ "submit": {
+ "message": "Soumèt"
+ },
+ "submitted": {
+ "message": "Te Soumèt"
+ },
+ "supportCenter": {
+ "message": "Vizite Sant Sipò Nou"
+ },
+ "symbolBetweenZeroTen": {
+ "message": "Senbòl yo dwe ant 0 ak 10 karaktè."
+ },
+ "takesTooLong": {
+ "message": "Pran twò lontan?"
+ },
+ "terms": {
+ "message": "Tèm pou itilize"
+ },
+ "testFaucet": {
+ "message": "Tès Tiyo"
+ },
+ "to": {
+ "message": "Pou"
+ },
+ "toETHviaShapeShift": {
+ "message": "$1 pou ETH pa ShapeShift",
+ "description": "system will fill in deposit type in start of message"
+ },
+ "token": {
+ "message": "Token"
+ },
+ "tokenAddress": {
+ "message": "Adrès Token"
+ },
+ "tokenAlreadyAdded": {
+ "message": "Ou te deja ajoute token."
+ },
+ "tokenBalance": {
+ "message": "Balans Token ou se:"
+ },
+ "tokenSelection": {
+ "message": "Chache Tokens oswa chwazi nan lis Tokens popilè nou an."
+ },
+ "tokenSymbol": {
+ "message": "Token Senbòl"
+ },
+ "tokenWarning1": {
+ "message": "Kenbe tras token yo ou te achte ak kont MetaMask ou. Si ou te achte tokens pandan wap itilize yon kont diferan tokens sa yo pa pral parèt la."
+ },
+ "total": {
+ "message": "Total"
+ },
+ "transaction": {
+ "message": "tranzaksyon yo"
+ },
+ "transactionConfirmed": {
+ "message": "Tranzaksyon ou te konfime pou $2."
+ },
+ "transactionCreated": {
+ "message": "Tranzaksyon ou te kreye avèk on valè de $1 pou $2."
+ },
+ "transactionWithNonce": {
+ "message": "Tranzaksyon $1"
+ },
+ "transactionDropped": {
+ "message": "Tranzaksyon ou te tonbe a $2."
+ },
+ "transactionSubmitted": {
+ "message": "Tranzaksyon ou te soumèt a $2."
+ },
+ "transactionUpdated": {
+ "message": "Tranzaksyon ou te aktyalize a $2."
+ },
+ "transactionUpdatedGas": {
+ "message": "Tranzaksyon ou te aktyalize avèk on pri gaz de $1 a $2."
+ },
+ "transactions": {
+ "message": "transactions"
+ },
+ "transactionError": {
+ "message": "Erè tranzaksyon. Eksepsyon jete nan kòd kontra."
+ },
+ "transactionMemo": {
+ "message": "Memo tranzaksyon (opsyonèl)"
+ },
+ "transactionNumber": {
+ "message": "Nimewo Tranzaksyon"
+ },
+ "transfer": {
+ "message": "Transfè"
+ },
+ "transferFrom": {
+ "message": "Transfer From"
+ },
+ "transfers": {
+ "message": "Transfè yo"
+ },
+ "trezorHardwareWallet": {
+ "message": "TREZOR Materyèl Bous"
+ },
+ "troubleTokenBalances": {
+ "message": "Nou te gen pwoblèm chaje balans token ou. Ou ka wè yo ",
+ "description": "Followed by a link (here) to view token balances"
+ },
+ "tryAgain": {
+ "message": "Eseye anko"
+ },
+ "twelveWords": {
+ "message": "12 mo sa yo se sèl fason pou retabli kont MetaMask ou yo. \nKenbe yo yon kote ki an sekirite ak sekrè."
+ },
+ "typePassword": {
+ "message": "Tape modpas ou"
+ },
+ "uiWelcome": {
+ "message": "Byenveni nan New itilizatè koòdone (Beta)"
+ },
+ "uiWelcomeMessage": {
+ "message": "Kounya w ap itilize nouvo MetaMask UI (itilizatè koòdone) a."
+ },
+ "unapproved": {
+ "message": "Pa apwouve"
+ },
+ "unavailable": {
+ "message": "Pa disponib"
+ },
+ "units": {
+ "message": "inite yo"
+ },
+ "unknown": {
+ "message": "Enkoni"
+ },
+ "unknownFunction": {
+ "message": "Fonksyon enkoni"
+ },
+ "unknownNetwork": {
+ "message": "Rezo Prive Enkoni"
+ },
+ "unknownNetworkId": {
+ "message": "Rezo ID Enkoni"
+ },
+ "unknownQrCode": {
+ "message": "Erè: Nou pa t kapab idantifye QR kòd sa"
+ },
+ "unknownCameraErrorTitle": {
+ "message": "Ooops! Yon bagay te ale mal...."
+ },
+ "unknownCameraError": {
+ "message": "Te gen yon erè pandan y ap eseye jwenn aksè nan kamera ou. Tanpri eseye ankò..."
+ },
+ "unlock": {
+ "message": "Debloke"
+ },
+ "unlockMessage": {
+ "message": "Entènèt desantralize a ap tann"
+ },
+ "updatedWithDate": {
+ "message": "Mete ajou $1"
+ },
+ "uriErrorMsg": {
+ "message": "URIs mande pou apwopriye prefiks HTTP / HTTPS a."
+ },
+ "usaOnly": {
+ "message": "USA sèlman",
+ "description": "Using this exchange is limited to people inside the USA"
+ },
+ "usedByClients": {
+ "message": "Itilize pa yon varyete de kliyan diferan"
+ },
+ "useOldUI": {
+ "message": "Itilizasyon ansyen UI (itilizatè koòdone)"
+ },
+ "validFileImport": {
+ "message": "Ou dwe chwazi yon dosye ki valab pou enpòte."
+ },
+ "vaultCreated": {
+ "message": "Kòf Kreye"
+ },
+ "viewAccount": {
+ "message": "Wè Kont"
+ },
+ "viewOnEtherscan": {
+ "message": "Wè sou Etherscan"
+ },
+ "visitWebSite": {
+ "message": "Vizite sit entènèt nou an"
+ },
+ "walletSeed": {
+ "message": "Bous Seed"
+ },
+ "warning": {
+ "message": "Avètisman"
+ },
+ "welcomeBack": {
+ "message": "Bon Retou!"
+ },
+ "welcomeBeta": {
+ "message": "Byenveni nan MetaMask Beta"
+ },
+ "whatsThis": {
+ "message": "Kisa sa ye?"
+ },
+ "yesLetsTry": {
+ "message": "Wi, ann eseye"
+ },
+ "youNeedToAllowCameraAccess": {
+ "message": "Ou bezwen bay kamera aksè pou sèvi ak fonksyon sa."
+ },
+ "yourSigRequested": {
+ "message": "Yo mande siyati ou"
+ },
+ "youSign": {
+ "message": "Ou ap siyen kounya"
+ },
+ "yourPrivateSeedPhrase": {
+ "message": "Seed fraz prive ou a"
+ }
}
diff --git a/app/_locales/index.json b/app/_locales/index.json
index 46933dc3f..234215e39 100644
--- a/app/_locales/index.json
+++ b/app/_locales/index.json
@@ -1,24 +1,24 @@
[
- { "code": "cs", "name": "Czech" },
- { "code": "de", "name": "German" },
+ { "code": "cs", "name": "Čeština" },
+ { "code": "de", "name": "Deutsche" },
{ "code": "en", "name": "English" },
- { "code": "es", "name": "Spanish" },
- { "code": "fr", "name": "French" },
- { "code": "ht", "name": "Haitian Creole" },
- { "code": "hn", "name": "Hindi" },
- { "code": "it", "name": "Italian" },
- { "code": "ja", "name": "Japanese" },
- { "code": "ko", "name": "Korean" },
- { "code": "nl", "name": "Dutch" },
- { "code": "ph", "name": "Tagalog" },
- { "code": "pl", "name": "Polish" },
- { "code": "pt", "name": "Portuguese" },
- { "code": "ru", "name": "Russian" },
- { "code": "sl", "name": "Slovenian" },
- { "code": "th", "name": "Thai" },
- { "code": "tml", "name": "Tamil" },
- { "code": "tr", "name": "Turkish" },
- { "code": "vi", "name": "Vietnamese" },
- { "code": "zh_CN", "name": "Chinese (Simplified)" },
- { "code": "zh_TW", "name": "Chinese (Traditional)" }
+ { "code": "es", "name": "Español" },
+ { "code": "fr", "name": "Français" },
+ { "code": "ht", "name": "Kreyòl ayisyen" },
+ { "code": "hn", "name": "हिन्दी" },
+ { "code": "it", "name": "Italiano" },
+ { "code": "ja", "name": "日本語" },
+ { "code": "ko", "name": "한국어" },
+ { "code": "nl", "name": "Nederlands" },
+ { "code": "ph", "name": "Pilipino" },
+ { "code": "pl", "name": "Polskie" },
+ { "code": "pt", "name": "Português" },
+ { "code": "ru", "name": "Русский" },
+ { "code": "sl", "name": "Slovenščina" },
+ { "code": "th", "name": "ไทย" },
+ { "code": "tml", "name": "தமிழ்" },
+ { "code": "tr", "name": "Türkçe" },
+ { "code": "vi", "name": "Tiếng Việt" },
+ { "code": "zh_CN", "name": "中文(简体)" },
+ { "code": "zh_TW", "name": "中文(繁體)" }
]
diff --git a/app/_locales/nl/messages.json b/app/_locales/nl/messages.json
index e6d09c123..fc3450290 100644
--- a/app/_locales/nl/messages.json
+++ b/app/_locales/nl/messages.json
@@ -435,7 +435,7 @@
"message": "back-up woorden hebben alleen kleine letters"
},
"mainnet": {
- "message": "belangrijkste Ethereum-netwerk"
+ "message": "Main Netwerk"
},
"message": {
"message": "Bericht"
diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json
index a4b04d34b..242cf66bf 100644
--- a/app/_locales/sl/messages.json
+++ b/app/_locales/sl/messages.json
@@ -1,6 +1,48 @@
{
+ "privacyMode": {
+ "message": "Način zasebnosti"
+ },
+ "privacyModeDescription": {
+ "message": "Spletne strani morajo zahtevati dostop za ogled podatkov o vašem računu."
+ },
+ "exposeAccounts": {
+ "message": "Razkrij račune"
+ },
+ "exposeDescription": {
+ "message": "Razkrij račune trenutni spletni strani. Priporočeno za starejše dApps."
+ },
+ "confirmExpose": {
+ "message": "Ste prepričani da želite razkriti račune trenutni spletni strani?"
+ },
+ "confirmClear": {
+ "message": "Ste prepričani da želite počistiti odobrene spletne strani?"
+ },
+ "clearApprovalDataSuccess": {
+ "message": "Odobrene spletne strani uspešno počiščene."
+ },
+ "approvalData": {
+ "message": "Zasebni podatki"
+ },
+ "approvalDataDescription": {
+ "message": "Počistite zasebne podatke, tako da bodo morale vse spletne strani ponovno zahtevati dovoljenje."
+ },
+ "clearApprovalData": {
+ "message": "Počisti zasebne podatke"
+ },
+ "providerAPIRequest": {
+ "message": "Zahteva za Ethereum API"
+ },
+ "reviewProviderRequest": {
+ "message": "Preglejte zahtevo za Ethereum API."
+ },
+ "providerRequestInfo": {
+ "message": "Domena zahteva dostop do verige blokov in ogled vašega računa. Pred potrditvjo vedno preverite ali ste na želeni spletni strani."
+ },
"accept": {
- "message": "Sprejmi"
+ "message": "Potrdi"
+ },
+ "accessingYourCamera": {
+ "message": "Dostopanje do vaše kamere ..."
},
"account": {
"message": "Račun"
@@ -11,6 +53,15 @@
"accountName": {
"message": "Ime računa"
},
+ "accountOptions": {
+ "message": "Možnosti računa"
+ },
+ "accountSelectionRequired": {
+ "message": "Izbrati morate račun!"
+ },
+ "activityLog": {
+ "message": "dnevnik dejavnosti"
+ },
"address": {
"message": "Naslov"
},
@@ -23,6 +74,12 @@
"addTokens": {
"message": "Dodaj žetone"
},
+ "addSuggestedTokens": {
+ "message": "Dodaj priporočene žetone"
+ },
+ "addAcquiredTokens": {
+ "message": "Dodaj žetone pridobljene z MetaMask"
+ },
"amount": {
"message": "Znesek"
},
@@ -37,9 +94,21 @@
"message": "MetaMask",
"description": "The name of the application"
},
+ "approve": {
+ "message": "Potrdi"
+ },
+ "approved": {
+ "message": "Potrjeno"
+ },
"attemptingConnect": {
"message": "Povezovanje z verigo blokov ..."
},
+ "attemptToCancel": {
+ "message": "Želite preklicati?"
+ },
+ "attemptToCancelDescription": {
+ "message": "Če pošljete ta poskus, ne boste zagotovili, da bo vaša prvotna transakcija preklicana. Če bo poskus preklica uspešen, se bo zaračunala zgornja transakcija."
+ },
"attributions": {
"message": "Dodelitve"
},
@@ -50,13 +119,13 @@
"message": "Nazaj"
},
"balance": {
- "message": "Znesek:"
+ "message": "Znesek"
},
"balances": {
- "message": "Vaš znesek"
+ "message": "Znesek žetonov"
},
"balanceIsInsufficientGas": {
- "message": "Napačen znesek za skupno gas vrednost"
+ "message": "Nezadnosten znesek za trenutni gas"
},
"beta": {
"message": "BETA"
@@ -66,13 +135,16 @@
"description": "helper for inputting hex as decimal input"
},
"blockiesIdenticon": {
- "message": "Uporabite Blockies Identicon"
+ "message": "Uporabi identifikacijo Blockies"
},
"borrowDharma": {
"message": "Izposoja z Dharma (Beta)"
},
+ "browserNotSupported": {
+ "message": "Vaš brskalnik ni podptrt ..."
+ },
"builtInCalifornia": {
- "message": "MetaMask je ustvarjen v Kaliforniji."
+ "message": "MetaMask je zasnovan in ustvarjen v Kaliforniji."
},
"buy": {
"message": "Kupi"
@@ -83,18 +155,45 @@
"buyCoinbaseExplainer": {
"message": "Coinbase je najpopularnejši načun za kupovanje in prodajo bitcoinov, ethereuma, in litecoina."
},
+ "bytes": {
+ "message": "Bajti"
+ },
+ "ok": {
+ "message": "V redu"
+ },
"cancel": {
"message": "Prekliči"
},
+ "cancelAttempt": {
+ "message": "Prekliči poskus"
+ },
+ "cancellationGasFee": {
+ "message": "Preklicani znesek gas"
+ },
+ "cancelN": {
+ "message": "Prekliči vseh $1 transakcij"
+ },
"classicInterface": {
- "message": "Uporabi navaden način"
+ "message": "Uporabi klasični vmesnik"
},
"clickCopy": {
"message": "Kliknite za kopiranje"
},
+ "clickToAdd": {
+ "message": "Kliknite na $1 za dodajo v vaš račun"
+ },
+ "close": {
+ "message": "Zapri"
+ },
+ "chromeRequiredForHardwareWallets": {
+ "message": "Za uporabo strojne denarnice potrebujete Google Chrome."
+ },
"confirm": {
"message": "Potrdi"
},
+ "confirmed": {
+ "message": "Potrjeno"
+ },
"confirmContract": {
"message": "Potrdi pogodbo"
},
@@ -104,6 +203,36 @@
"confirmTransaction": {
"message": "Potrdi transakcijo"
},
+ "connectHardwareWallet": {
+ "message": "Poveži strojno denarnico"
+ },
+ "connect": {
+ "message": "Poveži"
+ },
+ "connecting": {
+ "message": "Povezovanje ..."
+ },
+ "connectingToKovan": {
+ "message": "Povezovanje na testno omrežje Kovan"
+ },
+ "connectingToMainnet": {
+ "message": "Povezovanje na glavno omrežje"
+ },
+ "connectingToRopsten": {
+ "message": "Povezovanje na testno omrežje Ropsten"
+ },
+ "connectingToRinkeby": {
+ "message": "Povezovanje na testno omrežje Rinkeby"
+ },
+ "connectingToUnknown": {
+ "message": "Povezovanje na neznano omrežje"
+ },
+ "connectToLedger": {
+ "message": "Poveži z Ledger"
+ },
+ "connectToTrezor": {
+ "message": "Poveži z Trezor"
+ },
"continue": {
"message": "Nadaljuj"
},
@@ -114,23 +243,26 @@
"message": "Ustvarjanje pogodbe"
},
"conversionProgress": {
- "message": "Poteka pretvorba"
+ "message": "Pretvorba v teku"
},
"copiedButton": {
"message": "Kopirano"
},
"copiedClipboard": {
- "message": "Kopirano v odložišče"
+ "message": "Kopirano v odložišče!"
},
"copiedExclamation": {
"message": "Kopirano!"
},
"copiedSafe": {
- "message": "Prilepil sem ga na varno!"
+ "message": "Prilepil sem ga na varno"
},
"copy": {
"message": "Kopiraj"
},
+ "copyAddress": {
+ "message": "Kopiraj naslov v odložišče"
+ },
"copyToClipboard": {
"message": "Kopiraj v odložišče"
},
@@ -154,31 +286,40 @@
"description": "Exchange type (cryptocurrencies)"
},
"currentConversion": {
- "message": "Trenutna cena"
+ "message": "Trenutna pretvorba"
+ },
+ "currentLanguage": {
+ "message": "Trenutni jezik"
},
"currentNetwork": {
"message": "Trenutno omrežje"
},
+ "currentRpc": {
+ "message": "Trenutni RPC"
+ },
"customGas": {
"message": "Prilagodi gas"
},
+ "customToken": {
+ "message": "Žeton po meri"
+ },
"customize": {
"message": "Prilagodi"
},
"customRPC": {
- "message": "Poljuben RPC"
+ "message": "RPC po meri"
},
"decimalsMustZerotoTen": {
- "message": "Decimalk mora biti vsaj 0, in ne več kot 36."
+ "message": "Decimalk mora biti med 0 in 36."
},
"decimal": {
- "message": "Decimalke natančnosti"
+ "message": "Decimalna natančnost"
},
"defaultNetwork": {
- "message": "Privzeto omrežje za transakcije je Main Net."
+ "message": "Privzeto omrežje za transkacije je glavno omrežje."
},
"denExplainer": {
- "message": "DEN je vaša šifrirana shramba v MetaMasku."
+ "message": "Vaš DEN je z geslom šifrirana shramba v MetaMask."
},
"deposit": {
"message": "Vplačaj"
@@ -187,14 +328,14 @@
"message": "Vplačajte vaš BTC na spodnji naslov:"
},
"depositCoin": {
- "message": "Vplačajte $1 na spodnji naslov",
+ "message": "Vplačajte vaš $1 na spodnji naslov",
"description": "Tells the user what coin they have selected to deposit with shapeshift"
},
"depositEth": {
"message": "Vplačilo ETH"
},
"depositEther": {
- "message": "Vplačilo ethera"
+ "message": "Vplačilo ethra"
},
"depositFiat": {
"message": "Vplačilo s klasičnimi valutami"
@@ -206,25 +347,34 @@
"message": "Vplačilo z ShapeShift"
},
"depositShapeShiftExplainer": {
- "message": "Če imate druge kriptovalute, lahko vpačate ether neposredno v MetaMask. Brez računov."
+ "message": "Če imate druge kriptovalute, lahko Ether vplačate neposredno v MetaMask. Brez računov."
},
"details": {
"message": "Podrobnosti"
},
"directDeposit": {
- "message": "Direktno vplačilo"
+ "message": "Neposredno vplačilo"
},
"directDepositEther": {
- "message": "Direktno vplačilo ehera"
+ "message": "Neposredno vplačilo ehera"
},
"directDepositEtherExplainer": {
- "message": "Če že imate ether, ga lahko najhitreje dobite v MetaMask z direktnim vplačilom."
+ "message": "Če že imate Ether, ga lahko najhitreje dobite v MetaMask z neposrednim vplačilom."
},
"done": {
"message": "Končano"
},
+ "downloadGoogleChrome": {
+ "message": "Prenesi Google Chrome"
+ },
"downloadStateLogs": {
- "message": "Prenesi state dnevnike"
+ "message": "Prenesi dnevnike state"
+ },
+ "dontHaveAHardwareWallet": {
+ "message": "Nimate strojne denarnice?"
+ },
+ "dropped": {
+ "message": "Izpusti"
},
"edit": {
"message": "Uredi"
@@ -232,62 +382,83 @@
"editAccountName": {
"message": "Uredi ime računa"
},
+ "editingTransaction": {
+ "message": "Uredite transakcijo"
+ },
"emailUs": {
"message": "Pišite nam!"
},
"encryptNewDen": {
- "message": "Šifrirajte DEN"
+ "message": "Šifrirajte vaš DEN"
+ },
+ "ensNameNotFound": {
+ "message": "Ime ENS ni najdeno"
},
"enterPassword": {
- "message": "Vpišite geslo"
+ "message": "Vnesite geslo"
},
"enterPasswordConfirm": {
"message": "Potrdite geslo"
},
+ "enterPasswordContinue": {
+ "message": "Za nadaljevanje vnesite geslo"
+ },
+ "eth": {
+ "message": "ETH"
+ },
"etherscanView": {
- "message": "Poglejte račun na Etherscan"
+ "message": "Poglej račun na Etherscan"
},
"exchangeRate": {
"message": "Menjalni tečaj"
},
+ "expandView": {
+ "message": "Razširi pogled"
+ },
"exportPrivateKey": {
"message": "Izvozi zasebni ključ"
},
"exportPrivateKeyWarning": {
- "message": "Izvažanje zasebnih ključev je na lastno odgovornost."
+ "message": "Izvoz zasebnega ključa na lastno odgovornost."
},
"failed": {
"message": "Ni uspelo"
},
"fiat": {
- "message": "FIAT",
+ "message": "Klasične",
"description": "Exchange type"
},
"fileImportFail": {
- "message": "Uvoz z datoteko ni uspel? Kliknite tukaj!",
+ "message": "Uvoz z datoteko ne deluje? Kliknite tukaj!",
"description": "Helps user import their account from a JSON file"
},
"followTwitter": {
"message": "Sledite nam na Twitterju"
},
+ "forgetDevice": {
+ "message": "Pozabi to napravo"
+ },
"from": {
"message": "Od"
},
"fromToSame": {
- "message": "From and To address cannot be the same"
+ "message": "Naslova pošiljatelja in prejemnika ne smeta biti enaka"
},
"fromShapeShift": {
"message": "Od ShapeShift"
},
+ "functionType": {
+ "message": "Vrsta funkcije"
+ },
"gas": {
"message": "Gas",
"description": "Short indication of gas cost"
},
"gasFee": {
- "message": "Gas fee"
+ "message": "Gas Fee"
},
"gasLimit": {
- "message": "Gas limit"
+ "message": "Gas Limit"
},
"gasLimitCalculation": {
"message": "Priporočen gas limit je izračunan glede na omrežje."
@@ -296,37 +467,64 @@
"message": "Gas limit je zahtevan"
},
"gasLimitTooLow": {
- "message": "Gas limit mora biti najmanj 21000"
+ "message": "Gas limit mora biti vsaj 21000"
+ },
+ "gasUsed": {
+ "message": "Uporabljen gas"
},
"generatingSeed": {
"message": "Ustvarjenje seed ..."
},
"gasPrice": {
- "message": "Gas price (GWEI)"
+ "message": "Gas Price (GWEI)"
},
"gasPriceCalculation": {
- "message": "Priporočen gas price je izračunan glede na omrežje"
+ "message": "Priporočen gas price je izračunan glede na omrežje."
},
"gasPriceRequired": {
"message": "Gas price je zahtevan"
},
+ "generatingTransaction": {
+ "message": "Ustvarjanje transakcije"
+ },
"getEther": {
- "message": "Pridobite ether"
+ "message": "Pridobi Ether"
},
"getEtherFromFaucet": {
- "message": "Pridobite ether iz fauceta za $1",
+ "message": "Pridobite Ether iz fauceta za $1",
"description": "Displays network name for Ether faucet"
},
+ "getHelp": {
+ "message": "Get Help."
+ },
"greaterThanMin": {
- "message": "mora biti višji ali enak $1.",
+ "message": "mora biti večji ali enak $1.",
"description": "helper for inputting hex as decimal input"
},
+ "hardware": {
+ "message": "strojna"
+ },
+ "hardwareWalletConnected": {
+ "message": "Strojna denarnica povezana"
+ },
+ "hardwareWallets": {
+ "message": "Poveži strojno denarnico"
+ },
+ "hardwareWalletsMsg": {
+ "message": "Izberite vrsto strojne denarnice"
+ },
+ "havingTroubleConnecting": {
+ "message": "Imate težave?"
+ },
"here": {
"message": "tukaj",
"description": "as in -click here- for more information (goes with troubleTokenBalances)"
},
"hereList": {
- "message": "Tukaj je seznam!!!"
+ "message": "Tukaj je seznam!!!!"
+ },
+ "hexData": {
+ "message": "Hex Data"
},
"hide": {
"message": "Skrij"
@@ -337,24 +535,27 @@
"hideTokenPrompt": {
"message": "Skrijem žeton?"
},
+ "history": {
+ "message": "Zgodovina"
+ },
"howToDeposit": {
- "message": "Kako želite vplačati ether?"
+ "message": "Kako želite vplačati Ether?"
},
"holdEther": {
- "message": "Omogoča vam, da imate eter in žetone in služi kot most za decentralizirane aplikacije."
+ "message": "Omogoča vam shranjevanje ethra in žetonov ter povezovanje decentraliziranih aplikacij."
},
"import": {
- "message": "Uvozi",
+ "message": "Uvoz",
"description": "Button to import an account from a selected file"
},
"importAccount": {
- "message": "Uvozi račun"
+ "message": "Uvoz računa"
},
"importAccountMsg": {
- "message": " Uvoženi računi ne bodo povezani s prvotnim seedphaseom. Preberite več o uvoženih računih "
+ "message": " Uvoženi računa ne bodo povezani s prvotnim seed phase. Preberite več o uvoženih računih "
},
"importAnAccount": {
- "message": "Uvozi račun"
+ "message": "IUvozi račun"
},
"importDen": {
"message": "Uvozi DEN"
@@ -363,9 +564,18 @@
"message": "Uvoženo",
"description": "status showing that an account has been fully loaded into the keyring"
},
+ "importUsingSeed": {
+ "message": "Uvozi z seed phase"
+ },
+ "info": {
+ "message": "Info"
+ },
"infoHelp": {
"message": "Info & Pomoč"
},
+ "initialTransactionConfirmed": {
+ "message": "Vaša prvotna transakcija je bila potrjena. Pritisnite V redu in se vrnite nazaj."
+ },
"insufficientFunds": {
"message": "Nezadostna sredstva."
},
@@ -373,45 +583,63 @@
"message": "Nezadostni žetoni."
},
"invalidAddress": {
- "message": "Nepravilen naslov"
+ "message": "Neveljaven naslov"
},
"invalidAddressRecipient": {
- "message": "Prejemnikov naslov je neveljaven"
+ "message": "Neveljaven nasklov prejemnika"
},
"invalidGasParams": {
- "message": "Nepravilno nastavljen gas"
+ "message": "Neveljavne gas nastavitve"
},
"invalidInput": {
- "message": "Napačen vnos."
+ "message": "Neveljaven vnos."
},
"invalidRequest": {
- "message": "Napačna zahteva"
+ "message": "Neveljavna zahteva"
},
"invalidRPC": {
- "message": "Napačen RPC URI"
+ "message": "Neveljaven RPC URL"
+ },
+ "invalidSeedPhrase": {
+ "message": "Neveljavna seed phrase"
},
"jsonFail": {
- "message": "Nekaj je bilo narobe. Prepričajte se, da je JSON datoteka pravilno oblikovana."
+ "message": "Nekaj je bilo narobe. Prepričajte se, da je datoteka JSON pravilno oblikovana."
},
"jsonFile": {
- "message": "JSON datoteka",
+ "message": "Datoteka JSON",
"description": "format for importing an account"
},
+ "keepTrackTokens": {
+ "message": "Sledite žetonom, ki ste jih pridobili z MetaMask."
+ },
"kovan": {
"message": "Testno omrežje Kovan"
},
"knowledgeDataBase": {
"message": "Obiščite našo pomoč"
},
+ "max": {
+ "message": "Max"
+ },
+ "learnMore": {
+ "message": "Preberite več"
+ },
+ "ledgerAccountRestriction": {
+ "message": "Za dodajanje novega računa morate uporabiti zadnji račun."
+ },
"lessThanMax": {
- "message": "mora biti večji ali enak $1.",
+ "message": "mora biti manjši ali enak $1.",
"description": "helper for inputting hex as decimal input"
},
"likeToAddTokens": {
"message": "Želite dodati te žetone?"
},
+ "links": {
+ "message": "Povezave"
+ },
"limit": {
- "message": "Omejitev"
+ "message": "Meja"
},
"loading": {
"message": "Nalaganje ..."
@@ -432,20 +660,32 @@
"message": "Loose"
},
"loweCaseWords": {
- "message": "seed words imajo lahko le male črke"
+ "message": "seed words lahko vsebujejo samo male črke"
},
"mainnet": {
"message": "Glavno omrežje"
},
+ "menu": {
+ "message": "Meni"
+ },
"message": {
"message": "Sporočilo"
},
"metamaskDescription": {
"message": "MetaMask je varen identitetni sklad za Ethereum."
},
+ "metamaskSeedWords": {
+ "message": "Seed Words"
+ },
+ "metamaskVersion": {
+ "message": "Različica"
+ },
"min": {
"message": "Najmanj"
},
+ "missingYourTokens": {
+ "message": "Ne vidite vaših žetonov?"
+ },
"myAccounts": {
"message": "Moji računi"
},
@@ -453,7 +693,7 @@
"message": "Izbran mora biti vsaj 1 žeton."
},
"needEtherInWallet": {
- "message": "Za interakcijo z decentraliziranimi aplikacijami, ki uporabljajo MetaMask, boste v svoji denarnici potrebovali eter."
+ "message": "Za interakcijo z decentraliziranimi aplikacijami boste v svoji denarnici potrebovali Eter."
},
"needImportFile": {
"message": "Za uvoz morate izbrati datoteko.",
@@ -464,11 +704,14 @@
"description": "Password and file needed to import an account"
},
"negativeETH": {
- "message": "Ni mogoče poslati negativne vsote ETH."
+ "message": "Negativnih zneskov ETH ni mogoče poslati."
},
"networks": {
"message": "Omrežja"
},
+ "nevermind": {
+ "message": "Pozabi"
+ },
"newAccount": {
"message": "Nov račun"
},
@@ -480,31 +723,64 @@
"message": "Nova pogodba"
},
"newPassword": {
- "message": "Novo geslo (min. 8. črk)"
+ "message": "Novo geslo (min 8 znakov)"
+ },
+ "newPassword8Chars": {
+ "message": "Novo geslo (min 8 znakov)"
},
"newRecipient": {
"message": "Nov prejemnik"
},
- "newRPC": {
+ "newNetwork": {
+ "message": "Novo omrežje"
+ },
+ "rpcURL": {
"message": "Nov RPC URL"
},
+ "showAdvancedOptions": {
+ "message": "Pokaži napredne možnosti"
+ },
+ "hideAdvancedOptions": {
+ "message": "Skrij napredne možnosti"
+ },
+ "optionalChainId": {
+ "message": "ChainID (nezahtevano)"
+ },
+ "optionalSymbol": {
+ "message": "Simbol (nezahtevano)"
+ },
+ "optionalNickname": {
+ "message": "Uporabniško ime (nezahtevano)"
+ },
"next": {
"message": "Naprej"
},
"noAddressForName": {
- "message": "Za to ime ni bil nastavljen noben naslov."
+ "message": "Za to ime ni naslovov."
},
"noDeposits": {
- "message": "Ni prejetih vplačil"
+ "message": "Prejetih ni nič vplačil"
+ },
+ "noConversionRateAvailable": {
+ "message": "Menjalni tečaj ni na voljo"
},
"noTransactionHistory": {
"message": "Ni zgodovine transakcij."
},
"noTransactions": {
- "message": "Ni transakcij"
+ "message": "Nimate transakcij"
+ },
+ "notFound": {
+ "message": "Ni najdeno"
},
"notStarted": {
- "message": "Ni se začelo"
+ "message": "Ni začeto"
+ },
+ "noWebcamFoundTitle": {
+ "message": "Spletna kamera ni najdena"
+ },
+ "noWebcamFound": {
+ "message": "Spletna kamera ni najdena. Poskusite znova kasneje."
},
"oldUI": {
"message": "Star UI"
@@ -512,43 +788,89 @@
"oldUIMessage": {
"message": "Vrnili ste se v star uporabniški vmesnik. V novega se lahko vrnete z možnostjo v spustnem meniju v zgornjem desnem kotu."
},
+ "onlySendToEtherAddress": {
+ "message": "Na Ethereum naslov pošljute samo ETH."
+ },
+ "onlySendTokensToAccountAddress": {
+ "message": "Na Ethereum naslov pošljute samo $1.",
+ "description": "displays token symbol"
+ },
+ "openInTab": {
+ "message": "Odpri v zavihku"
+ },
"or": {
"message": "ali",
"description": "choice between creating or importing a new account"
},
+ "orderOneHere": {
+ "message": "Naročite Trezor ali Ledger i n zavarujte svoje premoženje s strojno denarnico"
+ },
+ "origin": {
+ "message": "Izvor"
+ },
+ "outgoing": {
+ "message": "Odhodni"
+ },
+ "parameters": {
+ "message": "Parametri"
+ },
+ "password": {
+ "message": "Geslo"
+ },
"passwordCorrect": {
"message": "Prepričajte se, da je geslo pravilno."
},
+ "passwordsDontMatch": {
+ "message": "Gesli se ne ujemata"
+ },
"passwordMismatch": {
"message": "gesli se ne ujemata",
"description": "in password creation process, the two new password fields did not match"
},
+ "passwordNotLongEnough": {
+ "message": "Geslo ni dovolj dolgo"
+ },
"passwordShort": {
"message": "geslo ni dovolj dolgo",
"description": "in password creation process, the password is not long enough to be secure"
},
"pastePrivateKey": {
- "message": "Tukaj prilepite zasebni ključ:",
+ "message": "Tukaj prilepite vaš zasebni ključ:",
"description": "For importing an account from a private key"
},
"pasteSeed": {
- "message": "Tukaj prilepite seed phrase!"
+ "message": "Tukaj prilepite seed phase!"
+ },
+ "pending": {
+ "message": "v obdelavi"
},
"personalAddressDetected": {
- "message": "Osebni naslov je zaznan. Vnesite naslov žetona."
+ "message": "Zaznan je osebni naslov. Vnesite naslov pogodbe žetona."
},
"pleaseReviewTransaction": {
- "message": "Preglejte transakcijo."
+ "message": "Preglejte vašo transakcijo."
+ },
+ "popularTokens": {
+ "message": "Priljubljeni žetoni"
+ },
+ "prev": {
+ "message": "Prej"
+ },
+ "primaryCurrencySetting": {
+ "message": "Glavna valuta"
+ },
+ "primaryCurrencySettingDescription": {
+ "message": "Izberite Native za prikaz vrednosti v privzeti valuti verige (npr. ETH). Izberite Klasične za prikaz vrednosti v izbrani klasični valuti."
},
"privacyMsg": {
- "message": "Politika zasebnosti"
+ "message": "Zasebnost"
},
"privateKey": {
- "message": "Zasebni ključ",
+ "message": "Zasebni lljuč",
"description": "select this type of file to use to import an account"
},
"privateKeyWarning": {
- "message": "Opozorilo: Nikoli ne razkrijte tega ključa. Vsakdo s svojimi zasebnimi ključi lahko ukrade vse premoženje v računu."
+ "message": "Opozorilo: Nikoli ne razkrijte tega ključa. Kdorkoli lahko z njim ukrade vse vaše premoženje v računu."
},
"privateNetwork": {
"message": "Zasebno omrežje"
@@ -556,47 +878,98 @@
"qrCode": {
"message": "Prikaži QR kodo"
},
+ "queue": {
+ "message": "Čakalna vrsta"
+ },
"readdToken": {
- "message": "Ta žeton lahko dodate tudi v prihodnosti, tako da odprete možnost »Dodaj žeton« v meniju z računi."
+ "message": "Ta žeton lahko dodate tudi kasneje z uporabo gumba “Dodaj žeton” v možnostih vašega računa."
},
"readMore": {
- "message": "Preberite več."
+ "message": "Tukaj preberite več."
},
"readMore2": {
"message": "Preberite več."
},
"receive": {
- "message": "Prejmite"
+ "message": "Prejmi"
},
"recipientAddress": {
"message": "Prejemnikov naslov"
},
"refundAddress": {
- "message": "Vaš naslov za vračilo"
+ "message": "Naslov za vračilo."
+ },
+ "reject": {
+ "message": "Zavrni"
+ },
+ "rejectAll": {
+ "message": "Zavrni vse"
+ },
+ "rejectTxsN": {
+ "message": "Zavrni $1 transakcij"
+ },
+ "rejectTxsDescription": {
+ "message": "Zavrnili boste $1 transakcij."
},
"rejected": {
"message": "Zavrnjeno"
},
+ "reset": {
+ "message": "Ponastavi"
+ },
"resetAccount": {
"message": "Ponastavi račun"
},
+ "resetAccountDescription": {
+ "message": "Ponastavljanje računa bo izbrisalo zgodovino transakcij."
+ },
"restoreFromSeed": {
- "message": "Obnovi iz seed phrase"
+ "message": "Obnovim račun?"
+ },
+ "restoreVault": {
+ "message": "Obnovi shrambo"
+ },
+ "restoreAccountWithSeed": {
+ "message": "Obnovi račun z seed phrase"
},
"required": {
"message": "Zahtevano"
},
"retryWithMoreGas": {
- "message": "Poskusi z višjim gas price"
+ "message": "Poskusite z večjim gas price"
+ },
+ "restore": {
+ "message": "Obnovi"
},
"revealSeedWords": {
- "message": "Prikaži seed words"
+ "message": "Razkrij seed words"
+ },
+ "revealSeedWordsTitle": {
+ "message": "Seed Phrase"
+ },
+ "revealSeedWordsDescription": {
+ "message": "Če želite zamenjati brskalnik ali računalnik, potrebujete vaš seed phase za dostop do računa. Shranite ga na varno skrito mesto."
+ },
+ "revealSeedWordsWarningTitle": {
+ "message": "Tega ne delite z nikomer!"
},
"revealSeedWordsWarning": {
- "message": "Ne obnovite seed words na javnem mestu! Te besede se lahko uporabijo za krajo vseh vaših računov."
+ "message": "S temi besedami lahko kdorkoli ukrade vse vaše račune."
},
"revert": {
- "message": "Povrni"
+ "message": "Obnovi"
+ },
+ "remove": {
+ "message": "izbriši"
+ },
+ "removeAccount": {
+ "message": "Izbriši račun"
+ },
+ "removeAccountDescription": {
+ "message": "Ta račun bo izbrisan. Prepričajte se, da imate seed phase ali zasebni ključ tega računa, da ga boste lahko kasneje obnovili. "
+ },
+ "readyToConnect": {
+ "message": "Pripravljeni na povezovanje?"
},
"rinkeby": {
"message": "Testno omrežje Rinkeby"
@@ -604,13 +977,19 @@
"ropsten": {
"message": "Testno omrežje Ropsten"
},
+ "rpc": {
+ "message": "RPC po meri"
+ },
"sampleAccountName": {
- "message": "npr. Moj nov račun",
+ "message": "npr. Moj račun",
"description": "Help user understand concept of adding a human-readable name to their account"
},
"save": {
"message": "Shrani"
},
+ "saveAsCsvFile": {
+ "message": "Shrani kot CSV datoteko"
+ },
"saveAsFile": {
"message": "Shrani kot datoteko",
"description": "Account export process"
@@ -618,14 +997,23 @@
"saveSeedAsFile": {
"message": "Shrani seed words kot datoteko"
},
+ "scanInstructions": {
+ "message": "Postavite QR kodo pred vašo kamero"
+ },
+ "scanQrCode": {
+ "message": "Skeniraj QR kodo"
+ },
"search": {
"message": "Iskanje"
},
+ "searchResults": {
+ "message": "Rezultati iskanja"
+ },
"secretPhrase": {
- "message": "Tukaj vnesite svoje seed words, da obnovite svoje račune."
+ "message": "Vnesite vaših dvanajst besed za obnovitev vaših računov."
},
"seedPhraseReq": {
- "message": "seed phrases so dolgi 12 besed"
+ "message": "Seed phrase mora biti dolg 12 besed"
},
"select": {
"message": "Izberi"
@@ -633,6 +1021,9 @@
"selectCurrency": {
"message": "Izberi valuto"
},
+ "selectLocale": {
+ "message": "Izberi jezik"
+ },
"selectService": {
"message": "Izberi storitev"
},
@@ -648,24 +1039,63 @@
"sendTokens": {
"message": "Pošlji žetone"
},
+ "sentEther": {
+ "message": "poslani ether"
+ },
+ "sentTokens": {
+ "message": "poslani žetoni"
+ },
+ "separateEachWord": {
+ "message": "Vsako besedo ločite z enim presledkom"
+ },
+ "searchTokens": {
+ "message": "Iskanje žetonov"
+ },
+ "selectAnAddress": {
+ "message": "Izberi naslov"
+ },
+ "selectAnAccount": {
+ "message": "Izberi račun"
+ },
+ "selectAnAccountHelp": {
+ "message": "Izberi račun za prikaz v MetaMask"
+ },
+ "selectHdPath": {
+ "message": "Izberi HD Path"
+ },
+ "selectPathHelp": {
+ "message": "Če obstoječih Ledger ne vidite, poskusite izbrati \"Legacy (MEW / MyCrypto)\""
+ },
"sendTokensAnywhere": {
- "message": "Pošljite žetone vsem, ki imajo Ethereum račun"
+ "message": "Pošljite žetone komurkoli z Ethereum naslovom"
},
"settings": {
"message": "Nastavitve"
},
"shapeshiftBuy": {
- "message": "Kupite z Shapeshift"
+ "message": "Kupi z Shapeshift"
},
"showPrivateKeys": {
- "message": "Prikaži zasebne ključe"
+ "message": "Pokaži zasebni ključ"
},
"showQRCode": {
- "message": "Prikaži QR kodo"
+ "message": "Pokaži QR kodo"
+ },
+ "showHexData": {
+ "message": "Pokaži Hex Data"
+ },
+ "showHexDataDescription": {
+ "message": "Izberite za prikaz hex podatkov na zaslonu za pošiljanje"
},
"sign": {
"message": "Podpiši"
},
+ "signatureRequest": {
+ "message": "Zahteva za podpis"
+ },
+ "signed": {
+ "message": "Podpisano"
+ },
"signMessage": {
"message": "Podpiši sporočilo"
},
@@ -676,11 +1106,20 @@
"message": "Zahteva za podpis"
},
"sigRequested": {
- "message": "Podpis je zahtevan"
+ "message": "Podpis zahtevan"
},
"spaceBetween": {
"message": "med besedami je lahko samo presledek"
},
+ "speedUp": {
+ "message": "pospeši"
+ },
+ "speedUpTitle": {
+ "message": "Pospeši transakcijo"
+ },
+ "speedUpSubtitle": {
+ "message": "Povečajte gas prise za pospešitev transakcije"
+ },
"status": {
"message": "Status"
},
@@ -688,19 +1127,43 @@
"message": "State dnevniki"
},
"stateLogsDescription": {
- "message": "State dnevniki vsebujejo naslove vašega računa in poslane transakcije.."
+ "message": "State vsebujejo vaš javni nasklov in zgodovino transakcij."
+ },
+ "stateLogError": {
+ "message": "Napaka pri pridobivanju state dnevnikov."
+ },
+ "step1HardwareWallet": {
+ "message": "1. Povežite strojno denarnico"
+ },
+ "step1HardwareWalletMsg": {
+ "message": "Z računalnikom povežite strojno denarnico."
+ },
+ "step2HardwareWallet": {
+ "message": "2. Izberite račun"
+ },
+ "step2HardwareWalletMsg": {
+ "message": "Izberite račun, ki ga želute uporabiti. Trenutno lahko izberete le en račun na enkrat."
+ },
+ "step3HardwareWallet": {
+ "message": "3. Začnite uporabljati dApps in več!"
+ },
+ "step3HardwareWalletMsg": {
+ "message": "Uporabite strojno denarnico kot katerikoli drug Ethereum račun. Prijavite se v dApps, pošljite Ether in ERC20 žetone in žetone kot CryptoKitties."
},
"submit": {
"message": "Potrdi"
},
+ "submitted": {
+ "message": "Potrjeno"
+ },
"supportCenter": {
- "message": "Obiščite našo podporo"
+ "message": "Obiščite naše središče za podporo"
},
"symbolBetweenZeroTen": {
- "message": "Simbol mora biti dolg od 0 do 10 znakov."
+ "message": "Simbol mora imeti med 0 in 10 znakov."
},
"takesTooLong": {
- "message": "Traja predolgo?"
+ "message": "Trava predolgo?"
},
"terms": {
"message": "Pogoji uporabe"
@@ -715,79 +1178,151 @@
"message": "$1 v ETH prek ShapeShift",
"description": "system will fill in deposit type in start of message"
},
+ "token": {
+ "message": "Žeton"
+ },
"tokenAddress": {
"message": "Naslov žetona"
},
"tokenAlreadyAdded": {
- "message": "Žeton je že bil dodan."
+ "message": "Žeton je bil že dodan."
},
"tokenBalance": {
- "message": "Vaš znesek žetona:"
+ "message": "Vaš znesek žetonov je:"
},
"tokenSelection": {
- "message": "Poiščite žetone ali jih izberite z našega seznama priljubljenih žetonov."
+ "message": "Iščite žetone ali pa jih izberite iz seznama priljubljenih."
},
"tokenSymbol": {
"message": "Simbol žetona"
},
"tokenWarning1": {
- "message": "Spremljajte žetone, ki ste jih kupili s svojim MetaMask računom. Če ste kupili žetone z drugačnim računom, ti žetoni ne bodo prikazani tukaj."
+ "message": "Sledite žetonom, ki ste jih kupili z MetaMask metamask računom. Če ste jih kupili drugje, ne bodo prikazani tukaj."
},
"total": {
"message": "Skupno"
},
+ "transaction": {
+ "message": "transakcija"
+ },
+ "transactionConfirmed": {
+ "message": "Transakcija potrjena na $2."
+ },
+ "transactionCreated": {
+ "message": "Transakcija z vrednostjo $1 ustvarjena na $2."
+ },
+ "transactionWithNonce": {
+ "message": "Transakcija $1"
+ },
+ "transactionDropped": {
+ "message": "Transakcija na $2 preklicana."
+ },
+ "transactionSubmitted": {
+ "message": "Transakcija na $2 oddana."
+ },
+ "transactionUpdated": {
+ "message": "Transakcija na $2 spremenjena."
+ },
+ "transactionUpdatedGas": {
+ "message": "Transakcija spremenjena z gas price $1 na $2."
+ },
+ "transactionErrored": {
+ "message": "Napaka pri transakciji."
+ },
"transactions": {
"message": "transakcije"
},
+ "transactionError": {
+ "message": "Napaka pri transakciji. Izjema sprožena v kodi pogodbe."
+ },
"transactionMemo": {
- "message": "Opis transakcije (ni zahtevano)"
+ "message": "Opomba transakcije (nezahtevano)"
},
"transactionNumber": {
"message": "Številka transakcije"
},
+ "transfer": {
+ "message": "Prenesi"
+ },
+ "transferFrom": {
+ "message": "Prenesi od"
+ },
"transfers": {
"message": "Prenosi"
},
+ "trezorHardwareWallet": {
+ "message": "Strojna denarnica TREZOR"
+ },
"troubleTokenBalances": {
- "message": "Imeli smo težave pri nalaganju vaših žetonov. Ogledate si jih lahko ",
+ "message": "Če imate težave pri ogledu zneskov žetonov si jih lahko ogledate ",
"description": "Followed by a link (here) to view token balances"
},
+ "tryAgain": {
+ "message": "Poskusi znova"
+ },
"twelveWords": {
"message": "Edini način za obnovitev MetaMask računa, je teh 12 besed.\nShranite jih na varno in skrivno mesto."
},
"typePassword": {
- "message": "Vpišite vaše geslo"
+ "message": "Vnesite vaše MetaMask geslo"
},
"uiWelcome": {
"message": "Dobrodošli v nov UI (Beta)"
},
"uiWelcomeMessage": {
- "message": "Zdaj uporabljate novi MetaMask uporabniški vmesnik. Razglejte se, preizkusite nove funkcije, kot so pošiljanje žetonov, in nas obvestite, če imate kakšne težave."
+ "message": "Uporabljate nov uporabniški vmesnik."
+ },
+ "unapproved": {
+ "message": "Neodobreno"
},
"unavailable": {
"message": "Ni na voljo"
},
+ "units": {
+ "message": "enote"
+ },
"unknown": {
"message": "Neznano"
},
+ "unknownFunction": {
+ "message": "Neznana funkcija"
+ },
"unknownNetwork": {
"message": "Neznano zasebno omrežje"
},
"unknownNetworkId": {
"message": "Neznan ID omrežja"
},
+ "unknownQrCode": {
+ "message": "Napaka: Te QR kode ni bilo mogoče prepoznati"
+ },
+ "unknownCameraErrorTitle": {
+ "message": "Ooops! Nekaj je šlo narobe ...."
+ },
+ "unknownCameraError": {
+ "message": "Pri dostopanju do vaše kamere je prišlo do napake. Poskusite znova kasneje ..."
+ },
+ "unlock": {
+ "message": "Odkleni"
+ },
+ "unlockMessage": {
+ "message": "Decentralizirana spletna denarnica"
+ },
+ "updatedWithDate": {
+ "message": "Posodobljeno $1"
+ },
"uriErrorMsg": {
- "message": "URI-ji zahtevajo ustrezno HTTP/HTTPS predpono."
+ "message": "URI zahtevajo ustrezno HTTP/HTTPS predpono."
},
"usaOnly": {
"message": "Samo za ZDA",
"description": "Using this exchange is limited to people inside the USA"
},
"usedByClients": {
- "message": "Uporablja jih več različnih odjemalcev"
+ "message": "Uporabljen s strani večih različnih odjemalcev"
},
"useOldUI": {
- "message": "Uporabi star uporabniški vmesnik"
+ "message": "Uporabi star UI"
},
"validFileImport": {
"message": "Za uvoz morate izbrati pravilno datoteko."
@@ -798,22 +1333,40 @@
"viewAccount": {
"message": "Poglej račun"
},
+ "viewOnEtherscan": {
+ "message": "Poglej na Etherscan"
+ },
"visitWebSite": {
"message": "Obiščite našo spletno stran"
},
+ "walletSeed": {
+ "message": "Wallet Seed"
+ },
"warning": {
"message": "Opozorilo"
},
+ "welcomeBack": {
+ "message": "Dobrodošli nazaj!"
+ },
"welcomeBeta": {
"message": "Dobrodošli v MetaMask Beta"
},
"whatsThis": {
"message": "Kaj je to?"
},
+ "yesLetsTry": {
+ "message": "Pa poskusimo"
+ },
+ "youNeedToAllowCameraAccess": {
+ "message": "Za uporabo te funkcije boste potrebovali dostop do kamere."
+ },
"yourSigRequested": {
- "message": "Vaš podpis je bil zahtevan"
+ "message": "Zahtevan je bil vaš podpis"
},
"youSign": {
- "message": "Podpisani ste"
+ "message": "Podpisali boste"
+ },
+ "yourPrivateSeedPhrase": {
+ "message": "Vaš zasebni seed phrase"
}
}
diff --git a/app/loading.html b/app/loading.html
index aef5d9607..71403a5ac 100644
--- a/app/loading.html
+++ b/app/loading.html
@@ -1,5 +1,9 @@
-<html>
+<!DOCTYPE html>
+<html lang="en">
<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>MetaMask Loading</title>
<style>
#div-logo {
@@ -31,5 +35,11 @@
<div id="div-logo">
<img id="logo" src="./images/loginglogo.svg">
</div>
+ <script type="text/javascript">
+ // redirect to 404 after one minute
+ setTimeout(() => {
+ location.href = './404.html'
+ }, 60000)
+ </script>
</body>
</html>
diff --git a/app/manifest.json b/app/manifest.json
index aabacd49a..fc566311e 100644
--- a/app/manifest.json
+++ b/app/manifest.json
@@ -1,7 +1,7 @@
{
"name": "__MSG_appName__",
"short_name": "__MSG_appName__",
- "version": "4.16.0",
+ "version": "4.17.0",
"manifest_version": 2,
"author": "https://metamask.io",
"description": "__MSG_appDescription__",
diff --git a/app/scripts/background.js b/app/scripts/background.js
index 509a0001d..2a3c5b08b 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -23,13 +23,13 @@ const createStreamSink = require('./lib/createStreamSink')
const NotificationManager = require('./lib/notification-manager.js')
const MetamaskController = require('./metamask-controller')
const rawFirstTimeState = require('./first-time-state')
-const setupRaven = require('./lib/setupRaven')
+const setupSentry = require('./lib/setupSentry')
const reportFailedTxToSentry = require('./lib/reportFailedTxToSentry')
const setupMetamaskMeshMetrics = require('./lib/setupMetamaskMeshMetrics')
const EdgeEncryptor = require('./edge-encryptor')
const getFirstPreferredLangCode = require('./lib/get-first-preferred-lang-code')
const getObjStructure = require('./lib/getObjStructure')
-const ipfsContent = require('./lib/ipfsContent.js')
+const setupEnsIpfsResolver = require('./lib/ens-ipfs/setup')
const {
ENVIRONMENT_TYPE_POPUP,
@@ -50,7 +50,7 @@ global.METAMASK_NOTIFIER = notificationManager
// setup sentry error reporting
const release = platform.getVersion()
-const raven = setupRaven({ release })
+const sentry = setupSentry({ release })
// browser check if it is Edge - https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser
// Internet Explorer 6-11
@@ -58,7 +58,6 @@ const isIE = !!document.documentMode
// Edge 20+
const isEdge = !isIE && !!window.StyleMedia
-let ipfsHandle
let popupIsOpen = false
let notificationIsOpen = false
const openMetamaskTabsIDs = {}
@@ -164,7 +163,6 @@ async function initialize () {
const initLangCode = await getFirstPreferredLangCode()
await setupController(initState, initLangCode)
log.debug('MetaMask initialization complete.')
- ipfsHandle = ipfsContent(initState.NetworkController.provider)
}
//
@@ -197,14 +195,14 @@ async function loadStateFromPersistence () {
// we were able to recover (though it might be old)
versionedData = diskStoreState
const vaultStructure = getObjStructure(versionedData)
- raven.captureMessage('MetaMask - Empty vault found - recovered from diskStore', {
+ sentry.captureMessage('MetaMask - Empty vault found - recovered from diskStore', {
// "extra" key is required by Sentry
extra: { vaultStructure },
})
} else {
// unable to recover, clear state
versionedData = migrator.generateInitialState(firstTimeState)
- raven.captureMessage('MetaMask - Empty vault found - unable to recover')
+ sentry.captureMessage('MetaMask - Empty vault found - unable to recover')
}
}
@@ -212,7 +210,7 @@ async function loadStateFromPersistence () {
migrator.on('error', (err) => {
// get vault structure without secrets
const vaultStructure = getObjStructure(versionedData)
- raven.captureException(err, {
+ sentry.captureException(err, {
// "extra" key is required by Sentry
extra: { vaultStructure },
})
@@ -269,17 +267,15 @@ function setupController (initState, initLangCode) {
})
global.metamaskController = controller
- controller.networkController.on('networkDidChange', () => {
- ipfsHandle && ipfsHandle.remove()
- ipfsHandle = ipfsContent(controller.networkController.providerStore.getState())
- })
+ const provider = controller.provider
+ setupEnsIpfsResolver({ provider })
// report failed transactions to Sentry
controller.txController.on(`tx:status-update`, (txId, status) => {
if (status !== 'failed') return
const txMeta = controller.txController.txStateManager.getTx(txId)
try {
- reportFailedTxToSentry({ raven, txMeta })
+ reportFailedTxToSentry({ sentry, txMeta })
} catch (e) {
console.error(e)
}
diff --git a/app/scripts/controllers/blacklist.js b/app/scripts/controllers/blacklist.js
index 89c7cc888..e55b09d03 100644
--- a/app/scripts/controllers/blacklist.js
+++ b/app/scripts/controllers/blacklist.js
@@ -83,8 +83,25 @@ class BlacklistController {
*
*/
async updatePhishingList () {
- const response = await fetch('https://api.infura.io/v2/blacklist')
- const phishing = await response.json()
+ // make request
+ let response
+ try {
+ response = await fetch('https://api.infura.io/v2/blacklist')
+ } catch (err) {
+ log.error(new Error(`BlacklistController - failed to fetch blacklist:\n${err.stack}`))
+ return
+ }
+ // parse response
+ let rawResponse
+ let phishing
+ try {
+ const rawResponse = await response.text()
+ phishing = JSON.parse(rawResponse)
+ } catch (err) {
+ log.error(new Error(`BlacklistController - failed to parse blacklist:\n${rawResponse}`))
+ return
+ }
+ // update current blacklist
this.store.updateState({ phishing })
this._setupPhishingDetector(phishing)
return phishing
@@ -97,9 +114,9 @@ class BlacklistController {
*/
scheduleUpdates () {
if (this._phishingUpdateIntervalRef) return
- this.updatePhishingList().catch(log.warn)
+ this.updatePhishingList()
this._phishingUpdateIntervalRef = setInterval(() => {
- this.updatePhishingList().catch(log.warn)
+ this.updatePhishingList()
}, POLLING_INTERVAL)
}
diff --git a/app/scripts/controllers/currency.js b/app/scripts/controllers/currency.js
index d5bc5fe2b..fce65fd9c 100644
--- a/app/scripts/controllers/currency.js
+++ b/app/scripts/controllers/currency.js
@@ -21,6 +21,7 @@ class CurrencyController {
* since midnight of January 1, 1970
* @property {number} conversionInterval The id of the interval created by the scheduleConversionInterval method.
* Used to clear an existing interval on subsequent calls of that method.
+ * @property {string} nativeCurrency The ticker/symbol of the native chain currency
*
*/
constructor (opts = {}) {
@@ -28,6 +29,7 @@ class CurrencyController {
currentCurrency: 'usd',
conversionRate: 0,
conversionDate: 'N/A',
+ nativeCurrency: 'ETH',
}, opts.initState)
this.store = new ObservableStore(initState)
}
@@ -37,6 +39,29 @@ class CurrencyController {
//
/**
+ * A getter for the nativeCurrency property
+ *
+ * @returns {string} A 2-4 character shorthand that describes the specific currency
+ *
+ */
+ getNativeCurrency () {
+ return this.store.getState().nativeCurrency
+ }
+
+ /**
+ * A setter for the nativeCurrency property
+ *
+ * @param {string} nativeCurrency The new currency to set as the nativeCurrency in the store
+ *
+ */
+ setNativeCurrency (nativeCurrency) {
+ this.store.updateState({
+ nativeCurrency,
+ ticker: nativeCurrency,
+ })
+ }
+
+ /**
* A getter for the currentCurrency property
*
* @returns {string} A 2-4 character shorthand that describes a specific currency, currently selected by the user
@@ -104,17 +129,60 @@ class CurrencyController {
*
*/
async updateConversionRate () {
- let currentCurrency
+ let currentCurrency, nativeCurrency
try {
currentCurrency = this.getCurrentCurrency()
- const response = await fetch(`https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`)
- const parsedResponse = await response.json()
- this.setConversionRate(Number(parsedResponse.bid))
- this.setConversionDate(Number(parsedResponse.timestamp))
+ nativeCurrency = this.getNativeCurrency()
+ // select api
+ let apiUrl
+ if (nativeCurrency === 'ETH') {
+ // ETH
+ apiUrl = `https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`
+ } else {
+ // ETC
+ apiUrl = `https://min-api.cryptocompare.com/data/price?fsym=${nativeCurrency.toUpperCase()}&tsyms=${currentCurrency.toUpperCase()}`
+ }
+ // attempt request
+ let response
+ try {
+ response = await fetch(apiUrl)
+ } catch (err) {
+ log.error(new Error(`CurrencyController - Failed to request currency from Infura:\n${err.stack}`))
+ return
+ }
+ // parse response
+ let rawResponse
+ let parsedResponse
+ try {
+ rawResponse = await response.text()
+ parsedResponse = JSON.parse(rawResponse)
+ } catch (err) {
+ log.error(new Error(`CurrencyController - Failed to parse response "${rawResponse}"`))
+ return
+ }
+ // set conversion rate
+ if (nativeCurrency === 'ETH') {
+ // ETH
+ this.setConversionRate(Number(parsedResponse.bid))
+ this.setConversionDate(Number(parsedResponse.timestamp))
+ } else {
+ // ETC
+ if (parsedResponse[currentCurrency.toUpperCase()]) {
+ this.setConversionRate(Number(parsedResponse[currentCurrency.toUpperCase()]))
+ this.setConversionDate(parseInt((new Date()).getTime() / 1000))
+ } else {
+ this.setConversionRate(0)
+ this.setConversionDate('N/A')
+ }
+ }
} catch (err) {
- log.warn(`MetaMask - Failed to query currency conversion:`, currentCurrency, err)
+ // reset current conversion rate
+ log.warn(`MetaMask - Failed to query currency conversion:`, nativeCurrency, currentCurrency, err)
this.setConversionRate(0)
this.setConversionDate('N/A')
+ // throw error
+ log.error(new Error(`CurrencyController - Failed to query rate for currency "${currentCurrency}":\n${err.stack}`))
+ return
}
}
diff --git a/app/scripts/controllers/network/createMetamaskMiddleware.js b/app/scripts/controllers/network/createMetamaskMiddleware.js
index 9e6a45888..319c5bf3e 100644
--- a/app/scripts/controllers/network/createMetamaskMiddleware.js
+++ b/app/scripts/controllers/network/createMetamaskMiddleware.js
@@ -11,6 +11,7 @@ function createMetamaskMiddleware ({
processTransaction,
processEthSignMessage,
processTypedMessage,
+ processTypedMessageV3,
processPersonalMessage,
getPendingNonce,
}) {
@@ -25,6 +26,7 @@ function createMetamaskMiddleware ({
processTransaction,
processEthSignMessage,
processTypedMessage,
+ processTypedMessageV3,
processPersonalMessage,
}),
createPendingNonceMiddleware({ getPendingNonce }),
diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js
index c1667d9a6..c21e9c764 100644
--- a/app/scripts/controllers/network/network.js
+++ b/app/scripts/controllers/network/network.js
@@ -11,6 +11,8 @@ const createInfuraClient = require('./createInfuraClient')
const createJsonRpcClient = require('./createJsonRpcClient')
const createLocalhostClient = require('./createLocalhostClient')
const { createSwappableProxy, createEventEmitterProxy } = require('swappable-obj-proxy')
+const extend = require('extend')
+const networks = { networkList: {} }
const {
ROPSTEN,
@@ -29,6 +31,10 @@ const defaultProviderConfig = {
type: testMode ? RINKEBY : MAINNET,
}
+const defaultNetworkConfig = {
+ ticker: 'ETH',
+}
+
module.exports = class NetworkController extends EventEmitter {
constructor (opts = {}) {
@@ -39,7 +45,8 @@ module.exports = class NetworkController extends EventEmitter {
// create stores
this.providerStore = new ObservableStore(providerConfig)
this.networkStore = new ObservableStore('loading')
- this.store = new ComposedStore({ provider: this.providerStore, network: this.networkStore })
+ this.networkConfig = new ObservableStore(defaultNetworkConfig)
+ this.store = new ComposedStore({ provider: this.providerStore, network: this.networkStore, settings: this.networkConfig })
this.on('networkDidChange', this.lookupNetwork)
// provider and block tracker
this._provider = null
@@ -51,8 +58,8 @@ module.exports = class NetworkController extends EventEmitter {
initializeProvider (providerParams) {
this._baseProviderParams = providerParams
- const { type, rpcTarget } = this.providerStore.getState()
- this._configureProvider({ type, rpcTarget })
+ const { type, rpcTarget, chainId, ticker, nickname } = this.providerStore.getState()
+ this._configureProvider({ type, rpcTarget, chainId, ticker, nickname })
this.lookupNetwork()
}
@@ -72,7 +79,20 @@ module.exports = class NetworkController extends EventEmitter {
return this.networkStore.getState()
}
- setNetworkState (network) {
+ getNetworkConfig () {
+ return this.networkConfig.getState()
+ }
+
+ setNetworkState (network, type) {
+ if (network === 'loading') {
+ return this.networkStore.putState(network)
+ }
+
+ // type must be defined
+ if (!type) {
+ return
+ }
+ network = networks.networkList[type] && networks.networkList[type].chainId ? networks.networkList[type].chainId : network
return this.networkStore.putState(network)
}
@@ -85,18 +105,32 @@ module.exports = class NetworkController extends EventEmitter {
if (!this._provider) {
return log.warn('NetworkController - lookupNetwork aborted due to missing provider')
}
+ var { type } = this.providerStore.getState()
const ethQuery = new EthQuery(this._provider)
- ethQuery.sendAsync({ method: 'net_version' }, (err, network) => {
- if (err) return this.setNetworkState('loading')
- log.info('web3.getNetwork returned ' + network)
- this.setNetworkState(network)
+ // first attempt to perform lookup via eth_chainId
+ ethQuery.sendAsync({ method: 'eth_chainId' }, (err, chainIdHex) => {
+ if (err) {
+ // if eth_chainId is not supported, fallback to net_verion
+ ethQuery.sendAsync({ method: 'net_version' }, (err, network) => {
+ if (err) return this.setNetworkState('loading')
+ log.info(`net_version returned ${network}`)
+ this.setNetworkState(network, type)
+ })
+ return
+ }
+ const chainId = Number.parseInt(chainIdHex, 16)
+ log.info(`net_version returned ${chainId}`)
+ this.setNetworkState(chainId, type)
})
}
- setRpcTarget (rpcTarget) {
+ setRpcTarget (rpcTarget, chainId, ticker = 'ETH', nickname = '') {
const providerConfig = {
type: 'rpc',
rpcTarget,
+ chainId,
+ ticker,
+ nickname,
}
this.providerConfig = providerConfig
}
@@ -132,7 +166,7 @@ module.exports = class NetworkController extends EventEmitter {
}
_configureProvider (opts) {
- const { type, rpcTarget } = opts
+ const { type, rpcTarget, chainId, ticker, nickname } = opts
// infura type-based endpoints
const isInfura = INFURA_PROVIDER_TYPES.includes(type)
if (isInfura) {
@@ -142,7 +176,7 @@ module.exports = class NetworkController extends EventEmitter {
this._configureLocalhostProvider()
// url-based rpc endpoints
} else if (type === 'rpc') {
- this._configureStandardProvider({ rpcUrl: rpcTarget })
+ this._configureStandardProvider({ rpcUrl: rpcTarget, chainId, ticker, nickname })
} else {
throw new Error(`NetworkController - _configureProvider - unknown type "${type}"`)
}
@@ -152,6 +186,11 @@ module.exports = class NetworkController extends EventEmitter {
log.info('NetworkController - configureInfuraProvider', type)
const networkClient = createInfuraClient({ network: type })
this._setNetworkClient(networkClient)
+ // setup networkConfig
+ var settings = {
+ ticker: 'ETH',
+ }
+ this.networkConfig.putState(settings)
}
_configureLocalhostProvider () {
@@ -160,9 +199,22 @@ module.exports = class NetworkController extends EventEmitter {
this._setNetworkClient(networkClient)
}
- _configureStandardProvider ({ rpcUrl }) {
+ _configureStandardProvider ({ rpcUrl, chainId, ticker, nickname }) {
log.info('NetworkController - configureStandardProvider', rpcUrl)
const networkClient = createJsonRpcClient({ rpcUrl })
+ // hack to add a 'rpc' network with chainId
+ networks.networkList['rpc'] = {
+ chainId: chainId,
+ rpcUrl,
+ ticker: ticker || 'ETH',
+ nickname,
+ }
+ // setup networkConfig
+ var settings = {
+ network: chainId,
+ }
+ settings = extend(settings, networks.networkList['rpc'])
+ this.networkConfig.putState(settings)
this._setNetworkClient(networkClient)
}
diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js
index 8eb2bce0c..eaeaee499 100644
--- a/app/scripts/controllers/preferences.js
+++ b/app/scripts/controllers/preferences.js
@@ -25,7 +25,7 @@ class PreferencesController {
*/
constructor (opts = {}) {
const initState = extend({
- frequentRpcList: [],
+ frequentRpcListDetail: [],
currentAccountTab: 'history',
accountTokens: {},
assetImages: {},
@@ -39,7 +39,7 @@ class PreferencesController {
seedWords: null,
forgottenPassword: false,
preferences: {
- useETHAsPrimaryCurrency: true,
+ useNativeCurrencyAsPrimaryCurrency: true,
},
}, opts.initState)
@@ -104,7 +104,7 @@ class PreferencesController {
* @param {Function} - end
*/
async requestWatchAsset (req, res, next, end) {
- if (req.method === 'metamask_watchAsset') {
+ if (req.method === 'metamask_watchAsset' || req.method === 'wallet_watchAsset') {
const { type, options } = req.params
switch (type) {
case 'ERC20':
@@ -375,22 +375,6 @@ class PreferencesController {
}
/**
- * Gets an updated rpc list from this.addToFrequentRpcList() and sets the `frequentRpcList` to this update list.
- *
- * @param {string} _url The the new rpc url to add to the updated list
- * @param {bool} remove Remove selected url
- * @returns {Promise<void>} Promise resolves with undefined
- *
- */
- updateFrequentRpcList (_url, remove = false) {
- return this.addToFrequentRpcList(_url, remove)
- .then((rpcList) => {
- this.store.updateState({ frequentRpcList: rpcList })
- return Promise.resolve()
- })
- }
-
- /**
* Setter for the `currentAccountTab` property
*
* @param {string} currentAccountTab Specifies the new tab to be marked as current
@@ -405,35 +389,53 @@ class PreferencesController {
}
/**
- * Returns an updated rpcList based on the passed url and the current list.
- * The returned list will have a max length of 3. If the _url currently exists it the list, it will be moved to the
- * end of the list. The current list is modified and returned as a promise.
+ * Adds custom RPC url to state.
*
- * @param {string} _url The rpc url to add to the frequentRpcList.
- * @param {bool} remove Remove selected url
- * @returns {Promise<array>} The updated frequentRpcList.
+ * @param {string} url The RPC url to add to frequentRpcList.
+ * @param {number} chainId Optional chainId of the selected network.
+ * @param {string} ticker Optional ticker symbol of the selected network.
+ * @param {string} nickname Optional nickname of the selected network.
+ * @returns {Promise<array>} Promise resolving to updated frequentRpcList.
*
*/
- addToFrequentRpcList (_url, remove = false) {
- const rpcList = this.getFrequentRpcList()
- const index = rpcList.findIndex((element) => { return element === _url })
+ addToFrequentRpcList (url, chainId, ticker = 'ETH', nickname = '') {
+ const rpcList = this.getFrequentRpcListDetail()
+ const index = rpcList.findIndex((element) => { return element.rpcUrl === url })
if (index !== -1) {
rpcList.splice(index, 1)
}
- if (!remove && _url !== 'http://localhost:8545') {
- rpcList.push(_url)
+ if (url !== 'http://localhost:8545') {
+ rpcList.push({ rpcUrl: url, chainId, ticker, nickname })
+ }
+ this.store.updateState({ frequentRpcListDetail: rpcList })
+ return Promise.resolve(rpcList)
+ }
+
+ /**
+ * Removes custom RPC url from state.
+ *
+ * @param {string} url The RPC url to remove from frequentRpcList.
+ * @returns {Promise<array>} Promise resolving to updated frequentRpcList.
+ *
+ */
+ removeFromFrequentRpcList (url) {
+ const rpcList = this.getFrequentRpcListDetail()
+ const index = rpcList.findIndex((element) => { return element.rpcUrl === url })
+ if (index !== -1) {
+ rpcList.splice(index, 1)
}
+ this.store.updateState({ frequentRpcListDetail: rpcList })
return Promise.resolve(rpcList)
}
/**
- * Getter for the `frequentRpcList` property.
+ * Getter for the `frequentRpcListDetail` property.
*
- * @returns {array<string>} An array of one or two rpc urls.
+ * @returns {array<array>} An array of rpc urls.
*
*/
- getFrequentRpcList () {
- return this.store.getState().frequentRpcList
+ getFrequentRpcListDetail () {
+ return this.store.getState().frequentRpcListDetail
}
/**
diff --git a/app/scripts/controllers/transactions/tx-gas-utils.js b/app/scripts/controllers/transactions/tx-gas-utils.js
index 3dd45507f..def67c2c3 100644
--- a/app/scripts/controllers/transactions/tx-gas-utils.js
+++ b/app/scripts/controllers/transactions/tx-gas-utils.js
@@ -7,6 +7,8 @@ const {
const { addHexPrefix } = require('ethereumjs-util')
const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send.
+import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/constants/error-keys'
+
/**
tx-gas-utils are gas utility methods for Transaction manager
its passed ethquery
@@ -32,6 +34,7 @@ class TxGasUtil {
} catch (err) {
txMeta.simulationFails = {
reason: err.message,
+ errorKey: err.errorKey,
}
return txMeta
}
@@ -56,24 +59,38 @@ class TxGasUtil {
return txParams.gas
}
- // if recipient has no code, gas is 21k max:
const recipient = txParams.to
const hasRecipient = Boolean(recipient)
- let code
- if (recipient) code = await this.query.getCode(recipient)
- if (hasRecipient && (!code || code === '0x')) {
- txParams.gas = SIMPLE_GAS_COST
- txMeta.simpleSend = true // Prevents buffer addition
- return SIMPLE_GAS_COST
+ // see if we can set the gas based on the recipient
+ if (hasRecipient) {
+ const code = await this.query.getCode(recipient)
+ // For an address with no code, geth will return '0x', and ganache-core v2.2.1 will return '0x0'
+ const codeIsEmpty = !code || code === '0x' || code === '0x0'
+
+ if (codeIsEmpty) {
+ // if there's data in the params, but there's no contract code, it's not a valid transaction
+ if (txParams.data) {
+ const err = new Error('TxGasUtil - Trying to call a function on a non-contract address')
+ // set error key so ui can display localized error message
+ err.errorKey = TRANSACTION_NO_CONTRACT_ERROR_KEY
+ throw err
+ }
+
+ // This is a standard ether simple send, gas requirement is exactly 21k
+ txParams.gas = SIMPLE_GAS_COST
+ // prevents buffer addition
+ txMeta.simpleSend = true
+ return SIMPLE_GAS_COST
+ }
}
- // if not, fall back to block gasLimit
+ // fallback to block gasLimit
const blockGasLimitBN = hexToBn(blockGasLimitHex)
const saferGasLimitBN = BnMultiplyByFraction(blockGasLimitBN, 19, 20)
txParams.gas = bnToHex(saferGasLimitBN)
- // run tx
+ // estimate tx gas requirements
return await this.query.estimateGas(txParams)
}
diff --git a/app/scripts/lib/contracts/registrar.js b/app/scripts/lib/ens-ipfs/contracts/registrar.js
index 99ca24458..99ca24458 100644
--- a/app/scripts/lib/contracts/registrar.js
+++ b/app/scripts/lib/ens-ipfs/contracts/registrar.js
diff --git a/app/scripts/lib/contracts/resolver.js b/app/scripts/lib/ens-ipfs/contracts/resolver.js
index 1bf3f90ce..1bf3f90ce 100644
--- a/app/scripts/lib/contracts/resolver.js
+++ b/app/scripts/lib/ens-ipfs/contracts/resolver.js
diff --git a/app/scripts/lib/ens-ipfs/resolver.js b/app/scripts/lib/ens-ipfs/resolver.js
new file mode 100644
index 000000000..fe2dc1134
--- /dev/null
+++ b/app/scripts/lib/ens-ipfs/resolver.js
@@ -0,0 +1,54 @@
+const namehash = require('eth-ens-namehash')
+const multihash = require('multihashes')
+const Eth = require('ethjs-query')
+const EthContract = require('ethjs-contract')
+const registrarAbi = require('./contracts/registrar')
+const resolverAbi = require('./contracts/resolver')
+
+module.exports = resolveEnsToIpfsContentId
+
+
+async function resolveEnsToIpfsContentId ({ provider, name }) {
+ const eth = new Eth(provider)
+ const hash = namehash.hash(name)
+ const contract = new EthContract(eth)
+ // lookup registrar
+ const chainId = Number.parseInt(await eth.net_version(), 10)
+ const registrarAddress = getRegistrarForChainId(chainId)
+ if (!registrarAddress) {
+ throw new Error(`EnsIpfsResolver - no known ens-ipfs registrar for chainId "${chainId}"`)
+ }
+ const Registrar = contract(registrarAbi).at(registrarAddress)
+ // lookup resolver
+ const resolverLookupResult = await Registrar.resolver(hash)
+ const resolverAddress = resolverLookupResult[0]
+ if (hexValueIsEmpty(resolverAddress)) {
+ throw new Error(`EnsIpfsResolver - no resolver found for name "${name}"`)
+ }
+ const Resolver = contract(resolverAbi).at(resolverAddress)
+ // lookup content id
+ const contentLookupResult = await Resolver.content(hash)
+ const contentHash = contentLookupResult[0]
+ if (hexValueIsEmpty(contentHash)) {
+ throw new Error(`EnsIpfsResolver - no content ID found for name "${name}"`)
+ }
+ const nonPrefixedHex = contentHash.slice(2)
+ const buffer = multihash.fromHexString(nonPrefixedHex)
+ const contentId = multihash.toB58String(multihash.encode(buffer, 'sha2-256'))
+ return contentId
+}
+
+function hexValueIsEmpty(value) {
+ return [undefined, null, '0x', '0x0', '0x0000000000000000000000000000000000000000000000000000000000000000'].includes(value)
+}
+
+function getRegistrarForChainId (chainId) {
+ switch (chainId) {
+ // mainnet
+ case 1:
+ return '0x314159265dd8dbb310642f98f50c066173c1259b'
+ // ropsten
+ case 3:
+ return '0x112234455c3a32fd11230c42e7bccd4a84e02010'
+ }
+}
diff --git a/app/scripts/lib/ens-ipfs/setup.js b/app/scripts/lib/ens-ipfs/setup.js
new file mode 100644
index 000000000..45eb1ce14
--- /dev/null
+++ b/app/scripts/lib/ens-ipfs/setup.js
@@ -0,0 +1,63 @@
+const urlUtil = require('url')
+const extension = require('extensionizer')
+const resolveEnsToIpfsContentId = require('./resolver.js')
+
+const supportedTopLevelDomains = ['eth']
+
+module.exports = setupEnsIpfsResolver
+
+function setupEnsIpfsResolver({ provider }) {
+
+ // install listener
+ const urlPatterns = supportedTopLevelDomains.map(tld => `*://*.${tld}/*`)
+ extension.webRequest.onErrorOccurred.addListener(webRequestDidFail, { urls: urlPatterns })
+
+ // return api object
+ return {
+ // uninstall listener
+ remove () {
+ extension.webRequest.onErrorOccurred.removeListener(webRequestDidFail)
+ },
+ }
+
+ async function webRequestDidFail (details) {
+ const { tabId, url } = details
+ // ignore requests that are not associated with tabs
+ if (tabId === -1) return
+ // parse ens name
+ const urlData = urlUtil.parse(url)
+ const { hostname: name, path, search } = urlData
+ const domainParts = name.split('.')
+ const topLevelDomain = domainParts[domainParts.length - 1]
+ // if unsupported TLD, abort
+ if (!supportedTopLevelDomains.includes(topLevelDomain)) return
+ // otherwise attempt resolve
+ attemptResolve({ tabId, name, path, search })
+ }
+
+ async function attemptResolve({ tabId, name, path, search }) {
+ extension.tabs.update(tabId, { url: `loading.html` })
+ try {
+ const ipfsContentId = await resolveEnsToIpfsContentId({ provider, name })
+ let url = `https://gateway.ipfs.io/ipfs/${ipfsContentId}${path}${search || ''}`
+ try {
+ // check if ipfs gateway has result
+ const response = await fetch(url, { method: 'HEAD' })
+ // if failure, redirect to 404 page
+ if (response.status !== 200) {
+ extension.tabs.update(tabId, { url: '404.html' })
+ return
+ }
+ // otherwise redirect to the correct page
+ extension.tabs.update(tabId, { url })
+ } catch (err) {
+ console.warn(err)
+ // if HEAD fetch failed, redirect so user can see relevant error page
+ extension.tabs.update(tabId, { url })
+ }
+ } catch (err) {
+ console.warn(err)
+ extension.tabs.update(tabId, { url: `error.html?name=${name}` })
+ }
+ }
+}
diff --git a/app/scripts/lib/ipfsContent.js b/app/scripts/lib/ipfsContent.js
deleted file mode 100644
index 8b08453c4..000000000
--- a/app/scripts/lib/ipfsContent.js
+++ /dev/null
@@ -1,46 +0,0 @@
-const extension = require('extensionizer')
-const resolver = require('./resolver.js')
-
-module.exports = function (provider) {
- function ipfsContent (details) {
- const name = details.url.substring(7, details.url.length - 1)
- let clearTime = null
- if (/^.+\.eth$/.test(name) === false) return
-
- extension.tabs.query({active: true}, tab => {
- extension.tabs.update(tab.id, { url: 'loading.html' })
-
- clearTime = setTimeout(() => {
- return extension.tabs.update(tab.id, { url: '404.html' })
- }, 60000)
-
- resolver.resolve(name, provider).then(ipfsHash => {
- clearTimeout(clearTime)
- let url = 'https://ipfs.infura.io/ipfs/' + ipfsHash
- return fetch(url, { method: 'HEAD' }).then(response => response.status).then(statusCode => {
- if (statusCode !== 200) return extension.tabs.update(tab.id, { url: '404.html' })
- extension.tabs.update(tab.id, { url: url })
- })
- .catch(err => {
- url = 'https://ipfs.infura.io/ipfs/' + ipfsHash
- extension.tabs.update(tab.id, {url: url})
- return err
- })
- })
- .catch(err => {
- clearTimeout(clearTime)
- const url = err === 'unsupport' ? 'unsupport' : 'error'
- extension.tabs.update(tab.id, {url: `${url}.html?name=${name}`})
- })
- })
- return { cancel: true }
- }
-
- extension.webRequest.onErrorOccurred.addListener(ipfsContent, {urls: ['*://*.eth/'], types: ['main_frame']})
-
- return {
- remove () {
- extension.webRequest.onErrorOccurred.removeListener(ipfsContent)
- },
- }
-}
diff --git a/app/scripts/lib/reportFailedTxToSentry.js b/app/scripts/lib/reportFailedTxToSentry.js
index df5661e59..de4d57145 100644
--- a/app/scripts/lib/reportFailedTxToSentry.js
+++ b/app/scripts/lib/reportFailedTxToSentry.js
@@ -7,10 +7,10 @@ module.exports = reportFailedTxToSentry
// for sending to sentry
//
-function reportFailedTxToSentry ({ raven, txMeta }) {
+function reportFailedTxToSentry ({ sentry, txMeta }) {
const errorMessage = 'Transaction Failed: ' + extractEthjsErrorMessage(txMeta.err.message)
- raven.captureMessage(errorMessage, {
+ sentry.captureMessage(errorMessage, {
// "extra" key is required by Sentry
- extra: txMeta,
+ extra: { txMeta },
})
}
diff --git a/app/scripts/lib/resolver.js b/app/scripts/lib/resolver.js
deleted file mode 100644
index ff0fed161..000000000
--- a/app/scripts/lib/resolver.js
+++ /dev/null
@@ -1,71 +0,0 @@
-const namehash = require('eth-ens-namehash')
-const multihash = require('multihashes')
-const HttpProvider = require('ethjs-provider-http')
-const Eth = require('ethjs-query')
-const EthContract = require('ethjs-contract')
-const registrarAbi = require('./contracts/registrar')
-const resolverAbi = require('./contracts/resolver')
-
-function ens (name, provider) {
- const eth = new Eth(new HttpProvider(getProvider(provider.type)))
- const hash = namehash.hash(name)
- const contract = new EthContract(eth)
- const Registrar = contract(registrarAbi).at(getRegistrar(provider.type))
- return new Promise((resolve, reject) => {
- if (provider.type === 'mainnet' || provider.type === 'ropsten') {
- Registrar.resolver(hash).then((address) => {
- if (address === '0x0000000000000000000000000000000000000000') {
- reject(null)
- } else {
- const Resolver = contract(resolverAbi).at(address['0'])
- return Resolver.content(hash)
- }
- }).then((contentHash) => {
- if (contentHash['0'] === '0x0000000000000000000000000000000000000000000000000000000000000000') reject(null)
- if (contentHash.ret !== '0x') {
- const hex = contentHash['0'].substring(2)
- const buf = multihash.fromHexString(hex)
- resolve(multihash.toB58String(multihash.encode(buf, 'sha2-256')))
- } else {
- reject(null)
- }
- })
- } else {
- return reject('unsupport')
- }
- })
-}
-
-function getProvider (type) {
- switch (type) {
- case 'mainnet':
- return 'https://mainnet.infura.io/'
- case 'ropsten':
- return 'https://ropsten.infura.io/'
- default:
- return 'http://localhost:8545/'
- }
-}
-
-function getRegistrar (type) {
- switch (type) {
- case 'mainnet':
- return '0x314159265dd8dbb310642f98f50c066173c1259b'
- case 'ropsten':
- return '0x112234455c3a32fd11230c42e7bccd4a84e02010'
- default:
- return '0x0000000000000000000000000000000000000000'
- }
-}
-
-module.exports.resolve = function (name, provider) {
- const path = name.split('.')
- const topLevelDomain = path[path.length - 1]
- if (topLevelDomain === 'eth' || topLevelDomain === 'test') {
- return ens(name, provider)
- } else {
- return new Promise((resolve, reject) => {
- reject(null)
- })
- }
-}
diff --git a/app/scripts/lib/setupFetchDebugging.js b/app/scripts/lib/setupFetchDebugging.js
index dd87b65a6..c1ef22d21 100644
--- a/app/scripts/lib/setupFetchDebugging.js
+++ b/app/scripts/lib/setupFetchDebugging.js
@@ -2,7 +2,7 @@ module.exports = setupFetchDebugging
//
// This is a utility to help resolve cases where `window.fetch` throws a
-// `TypeError: Failed to Fetch` without any stack or context for the request
+// `TypeError: Failed to Fetch` without any stack or context for the request
// https://github.com/getsentry/sentry-javascript/pull/1293
//
@@ -17,9 +17,11 @@ function setupFetchDebugging() {
try {
return await originalFetch.call(window, ...args)
} catch (err) {
- console.warn('FetchDebugger - fetch encountered an Error', err)
- console.warn('FetchDebugger - overriding stack to point of original call')
- err.stack = initialStack
+ if (!err.stack) {
+ console.warn('FetchDebugger - fetch encountered an Error without a stack', err)
+ console.warn('FetchDebugger - overriding stack to point of original call')
+ err.stack = initialStack
+ }
throw err
}
}
diff --git a/app/scripts/lib/setupRaven.js b/app/scripts/lib/setupSentry.js
index e6e511640..69042bc19 100644
--- a/app/scripts/lib/setupRaven.js
+++ b/app/scripts/lib/setupSentry.js
@@ -1,58 +1,55 @@
-const Raven = require('raven-js')
+const Sentry = require('@sentry/browser')
const METAMASK_DEBUG = process.env.METAMASK_DEBUG
const extractEthjsErrorMessage = require('./extractEthjsErrorMessage')
-const PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505'
-const DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496'
+const SENTRY_DSN_PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505'
+const SENTRY_DSN_DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496'
-module.exports = setupRaven
+module.exports = setupSentry
-// Setup raven / sentry remote error reporting
-function setupRaven (opts) {
- const { release } = opts
- let ravenTarget
+// Setup sentry remote error reporting
+function setupSentry (opts) {
+ const { release, getState } = opts
+ let sentryTarget
// detect brave
const isBrave = Boolean(window.chrome.ipcRenderer)
if (METAMASK_DEBUG) {
- console.log('Setting up Sentry Remote Error Reporting: DEV')
- ravenTarget = DEV
+ console.log('Setting up Sentry Remote Error Reporting: SENTRY_DSN_DEV')
+ sentryTarget = SENTRY_DSN_DEV
} else {
- console.log('Setting up Sentry Remote Error Reporting: PROD')
- ravenTarget = PROD
+ console.log('Setting up Sentry Remote Error Reporting: SENTRY_DSN_PROD')
+ sentryTarget = SENTRY_DSN_PROD
}
- const client = Raven.config(ravenTarget, {
+ Sentry.init({
+ dsn: sentryTarget,
+ debug: METAMASK_DEBUG,
release,
- transport: function (opts) {
- opts.data.extra.isBrave = isBrave
- const report = opts.data
+ beforeSend: (report) => rewriteReport(report),
+ })
- try {
- // handle error-like non-error exceptions
- rewriteErrorLikeExceptions(report)
- // simplify certain complex error messages (e.g. Ethjs)
- simplifyErrorMessages(report)
- // modify report urls
- rewriteReportUrls(report)
- } catch (err) {
- console.warn(err)
- }
- // make request normally
- client._makeRequest(opts)
- },
+ Sentry.configureScope(scope => {
+ scope.setExtra('isBrave', isBrave)
})
- client.install()
- return Raven
-}
+ function rewriteReport(report) {
+ try {
+ // simplify certain complex error messages (e.g. Ethjs)
+ simplifyErrorMessages(report)
+ // modify report urls
+ rewriteReportUrls(report)
+ // append app state
+ if (getState) {
+ const appState = getState()
+ report.extra.appState = appState
+ }
+ } catch (err) {
+ console.warn(err)
+ }
+ return report
+ }
-function rewriteErrorLikeExceptions (report) {
- // handle errors that lost their error-ness in serialization (e.g. dnode)
- rewriteErrorMessages(report, (errorMessage) => {
- if (!errorMessage.includes('Non-Error exception captured with keys:')) return errorMessage
- if (!(report.extra && report.extra.__serialized__ && report.extra.__serialized__.message)) return errorMessage
- return `Non-Error Exception: ${report.extra.__serialized__.message}`
- })
+ return Sentry
}
function simplifyErrorMessages (report) {
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 32ceb6790..1f6a8659b 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -138,12 +138,12 @@ module.exports = class MetamaskController extends EventEmitter {
this.accountTracker.stop()
}
})
-
+
// ensure accountTracker updates balances after network change
this.networkController.on('networkDidChange', () => {
this.accountTracker._updateAccounts()
})
-
+
// key mgmt
const additionalKeyrings = [TrezorKeyring, LedgerBridgeKeyring]
this.keyringController = new KeyringController({
@@ -197,6 +197,8 @@ module.exports = class MetamaskController extends EventEmitter {
})
this.networkController.on('networkDidChange', () => {
this.balancesController.updateAllBalances()
+ var currentCurrency = this.currencyController.getCurrentCurrency()
+ this.setCurrentCurrency(currentCurrency, function() {})
})
this.balancesController.updateAllBalances()
@@ -275,6 +277,8 @@ module.exports = class MetamaskController extends EventEmitter {
processTransaction: this.newUnapprovedTransaction.bind(this),
// msg signing
processEthSignMessage: this.newUnsignedMessage.bind(this),
+ processTypedMessage: this.newUnsignedTypedMessage.bind(this),
+ processTypedMessageV3: this.newUnsignedTypedMessage.bind(this),
processPersonalMessage: this.newUnsignedPersonalMessage.bind(this),
getPendingNonce: this.getPendingNonce.bind(this),
}
@@ -978,8 +982,8 @@ module.exports = class MetamaskController extends EventEmitter {
* @param {Object} msgParams - The params passed to eth_signTypedData.
* @param {Function} cb - The callback function, called with the signature.
*/
- newUnsignedTypedMessage (msgParams, req) {
- const promise = this.typedMessageManager.addUnapprovedMessageAsync(msgParams, req)
+ newUnsignedTypedMessage (msgParams, req, version) {
+ const promise = this.typedMessageManager.addUnapprovedMessageAsync(msgParams, req, version)
this.sendUpdate()
this.opts.showUnconfirmedMessage()
return promise
@@ -1273,10 +1277,6 @@ module.exports = class MetamaskController extends EventEmitter {
engine.push(subscriptionManager.middleware)
// watch asset
engine.push(this.preferencesController.requestWatchAsset.bind(this.preferencesController))
- // sign typed data middleware
- engine.push(this.createTypedDataMiddleware('eth_signTypedData', 'V1').bind(this))
- engine.push(this.createTypedDataMiddleware('eth_signTypedData_v1', 'V1').bind(this))
- engine.push(this.createTypedDataMiddleware('eth_signTypedData_v3', 'V3', true).bind(this))
// forward to metamask primary provider
engine.push(createProviderMiddleware({ provider }))
@@ -1412,10 +1412,13 @@ module.exports = class MetamaskController extends EventEmitter {
* @param {Function} cb - A callback function returning currency info.
*/
setCurrentCurrency (currencyCode, cb) {
+ const { ticker } = this.networkController.getNetworkConfig()
try {
+ this.currencyController.setNativeCurrency(ticker)
this.currencyController.setCurrentCurrency(currencyCode)
this.currencyController.updateConversionRate()
const data = {
+ nativeCurrency: ticker || 'ETH',
conversionRate: this.currencyController.getConversionRate(),
currentCurrency: this.currencyController.getCurrentCurrency(),
conversionDate: this.currencyController.getConversionDate(),
@@ -1454,11 +1457,14 @@ module.exports = class MetamaskController extends EventEmitter {
/**
* A method for selecting a custom URL for an ethereum RPC provider.
* @param {string} rpcTarget - A URL for a valid Ethereum RPC API.
+ * @param {number} chainId - The chainId of the selected network.
+ * @param {string} ticker - The ticker symbol of the selected network.
+ * @param {string} nickname - Optional nickname of the selected network.
* @returns {Promise<String>} - The RPC Target URL confirmed.
*/
- async setCustomRpc (rpcTarget) {
- this.networkController.setRpcTarget(rpcTarget)
- await this.preferencesController.updateFrequentRpcList(rpcTarget)
+ async setCustomRpc (rpcTarget, chainId, ticker = 'ETH', nickname = '') {
+ this.networkController.setRpcTarget(rpcTarget, chainId, ticker, nickname)
+ await this.preferencesController.addToFrequentRpcList(rpcTarget, chainId, ticker, nickname)
return rpcTarget
}
@@ -1467,7 +1473,7 @@ module.exports = class MetamaskController extends EventEmitter {
* @param {string} rpcTarget - A RPC URL to delete.
*/
async delCustomRpc (rpcTarget) {
- await this.preferencesController.updateFrequentRpcList(rpcTarget, true)
+ await this.preferencesController.removeFromFrequentRpcList(rpcTarget)
}
/**
@@ -1542,27 +1548,6 @@ module.exports = class MetamaskController extends EventEmitter {
* @param {Function} - next
* @param {Function} - end
*/
- createTypedDataMiddleware (methodName, version, reverse) {
- return async (req, res, next, end) => {
- const { method, params } = req
- if (method === methodName) {
- const promise = this.typedMessageManager.addUnapprovedMessageAsync({
- data: reverse ? params[1] : params[0],
- from: reverse ? params[0] : params[1],
- }, req, version)
- this.sendUpdate()
- this.opts.showUnconfirmedMessage()
- try {
- res.result = await promise
- end()
- } catch (error) {
- end(error)
- }
- } else {
- next()
- }
- }
- }
/**
* Adds a domain to the {@link BlacklistController} whitelist
diff --git a/app/scripts/ui.js b/app/scripts/ui.js
index 98a036338..c4f6615db 100644
--- a/app/scripts/ui.js
+++ b/app/scripts/ui.js
@@ -9,7 +9,7 @@ const extension = require('extensionizer')
const ExtensionPlatform = require('./platforms/extension')
const NotificationManager = require('./lib/notification-manager')
const notificationManager = new NotificationManager()
-const setupRaven = require('./lib/setupRaven')
+const setupSentry = require('./lib/setupSentry')
const log = require('loglevel')
start().catch(log.error)
@@ -21,7 +21,17 @@ async function start () {
// setup sentry error reporting
const release = global.platform.getVersion()
- setupRaven({ release })
+ setupSentry({ release, getState })
+ // provide app state to append to error logs
+ function getState() {
+ // get app state
+ const state = window.getCleanAppState()
+ // remove unnecessary data
+ delete state.localeMessages
+ delete state.metamask.recentBlocks
+ // return state to be added to request
+ return state
+ }
// inject css
// const css = MetaMaskUiCss()
diff --git a/development/states/add-token.json b/development/states/add-token.json
index 6a525f2b3..b59e9b757 100644
--- a/development/states/add-token.json
+++ b/development/states/add-token.json
@@ -109,7 +109,7 @@
},
"currentLocale": "en",
"preferences": {
- "useETHAsPrimaryCurrency": true
+ "useNativeCurrencyAsPrimaryCurrency": true
}
},
"appState": {
diff --git a/development/states/confirm-sig-requests.json b/development/states/confirm-sig-requests.json
index c7103cd13..1ffde3938 100644
--- a/development/states/confirm-sig-requests.json
+++ b/development/states/confirm-sig-requests.json
@@ -152,7 +152,7 @@
},
"currentLocale": "en",
"preferences": {
- "useETHAsPrimaryCurrency": true
+ "useNativeCurrencyAsPrimaryCurrency": true
}
},
"appState": {
diff --git a/development/states/currency-localization.json b/development/states/currency-localization.json
index 7dea42ade..ef28891a3 100644
--- a/development/states/currency-localization.json
+++ b/development/states/currency-localization.json
@@ -110,7 +110,7 @@
},
"currentLocale": "en",
"preferences": {
- "useETHAsPrimaryCurrency": true
+ "useNativeCurrencyAsPrimaryCurrency": true
}
},
"appState": {
diff --git a/development/states/first-time.json b/development/states/first-time.json
index 3206b67a3..ff7078720 100644
--- a/development/states/first-time.json
+++ b/development/states/first-time.json
@@ -39,7 +39,7 @@
"tokens": [],
"currentLocale": "en",
"preferences": {
- "useETHAsPrimaryCurrency": true
+ "useNativeCurrencyAsPrimaryCurrency": true
}
},
"appState": {
diff --git a/development/states/send-new-ui.json b/development/states/send-new-ui.json
index d9924dd74..0cd2f23f2 100644
--- a/development/states/send-new-ui.json
+++ b/development/states/send-new-ui.json
@@ -111,7 +111,7 @@
},
"currentLocale": "en",
"preferences": {
- "useETHAsPrimaryCurrency": true
+ "useNativeCurrencyAsPrimaryCurrency": true
}
},
"appState": {
diff --git a/development/states/tx-list-items.json b/development/states/tx-list-items.json
index cbffa98e5..e83179a17 100644
--- a/development/states/tx-list-items.json
+++ b/development/states/tx-list-items.json
@@ -104,7 +104,7 @@
"send": {},
"currentLocale": "en",
"preferences": {
- "useETHAsPrimaryCurrency": true
+ "useNativeCurrencyAsPrimaryCurrency": true
}
},
"appState": {
diff --git a/gulpfile.js b/gulpfile.js
index 5a468d2f3..0a0e3b3d5 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -462,7 +462,9 @@ function generateBundler (opts, performBundle) {
bundler.transform(envify({
METAMASK_DEBUG: opts.devMode,
NODE_ENV: opts.devMode ? 'development' : 'production',
- }))
+ }), {
+ global: true,
+ })
if (opts.watch) {
bundler = watchify(bundler)
diff --git a/old-ui/app/app.js b/old-ui/app/app.js
index 9be21ebad..f5e03d4f6 100644
--- a/old-ui/app/app.js
+++ b/old-ui/app/app.js
@@ -73,7 +73,7 @@ function mapStateToProps (state) {
forgottenPassword: state.appState.forgottenPassword,
nextUnreadNotice: state.metamask.nextUnreadNotice,
lostAccounts: state.metamask.lostAccounts,
- frequentRpcList: state.metamask.frequentRpcList || [],
+ frequentRpcListDetail: state.metamask.frequentRpcListDetail || [],
featureFlags,
suggestedTokens: state.metamask.suggestedTokens,
diff --git a/old-ui/app/components/app-bar.js b/old-ui/app/components/app-bar.js
index 234c06a01..fa8e499ed 100644
--- a/old-ui/app/components/app-bar.js
+++ b/old-ui/app/components/app-bar.js
@@ -17,7 +17,7 @@ module.exports = class AppBar extends Component {
static propTypes = {
dispatch: PropTypes.func.isRequired,
- frequentRpcList: PropTypes.array.isRequired,
+ frequentRpcListDetail: PropTypes.array.isRequired,
isMascara: PropTypes.bool.isRequired,
isOnboarding: PropTypes.bool.isRequired,
identities: PropTypes.any.isRequired,
@@ -196,7 +196,7 @@ module.exports = class AppBar extends Component {
renderNetworkDropdown () {
const {
dispatch,
- frequentRpcList: rpcList,
+ frequentRpcListDetail: rpcList,
provider,
} = this.props
const {
@@ -321,8 +321,8 @@ module.exports = class AppBar extends Component {
])
}
- renderCustomOption ({ rpcTarget, type }) {
- const {dispatch} = this.props
+ renderCustomOption ({ rpcTarget, type, ticker }) {
+ const {dispatch, network} = this.props
if (type !== 'rpc') {
return null
@@ -340,7 +340,7 @@ module.exports = class AppBar extends Component {
default:
return h(DropdownMenuItem, {
key: rpcTarget,
- onClick: () => dispatch(actions.setRpcTarget(rpcTarget)),
+ onClick: () => dispatch(actions.setRpcTarget(rpcTarget, network, ticker)),
closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
}, [
h('i.fa.fa-question-circle.fa-lg.menu-icon'),
@@ -354,7 +354,8 @@ module.exports = class AppBar extends Component {
const {dispatch} = this.props
const reversedRpcList = rpcList.slice().reverse()
- return reversedRpcList.map((rpc) => {
+ return reversedRpcList.map((entry) => {
+ const rpc = entry.rpcUrl
const currentRpcTarget = provider.type === 'rpc' && rpc === provider.rpcTarget
if ((rpc === LOCALHOST_RPC_URL) || currentRpcTarget) {
@@ -363,7 +364,7 @@ module.exports = class AppBar extends Component {
return h(DropdownMenuItem, {
key: `common${rpc}`,
closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
- onClick: () => dispatch(actions.setRpcTarget(rpc)),
+ onClick: () => dispatch(actions.setRpcTarget(rpc, entry.chainId, entry.ticker)),
}, [
h('i.fa.fa-question-circle.fa-lg.menu-icon'),
rpc,
diff --git a/old-ui/app/components/balance.js b/old-ui/app/components/balance.js
index 57ca84564..8995f961f 100644
--- a/old-ui/app/components/balance.js
+++ b/old-ui/app/components/balance.js
@@ -1,12 +1,18 @@
const Component = require('react').Component
const h = require('react-hyperscript')
+const connect = require('react-redux').connect
const inherits = require('util').inherits
const formatBalance = require('../util').formatBalance
const generateBalanceObject = require('../util').generateBalanceObject
const Tooltip = require('./tooltip.js')
const FiatValue = require('./fiat-value.js')
-module.exports = EthBalanceComponent
+module.exports = connect(mapStateToProps)(EthBalanceComponent)
+function mapStateToProps (state) {
+ return {
+ ticker: state.metamask.ticker,
+ }
+}
inherits(EthBalanceComponent, Component)
function EthBalanceComponent () {
@@ -16,9 +22,10 @@ function EthBalanceComponent () {
EthBalanceComponent.prototype.render = function () {
var props = this.props
let { value } = props
+ const { ticker } = props
var style = props.style
var needsParse = this.props.needsParse !== undefined ? this.props.needsParse : true
- value = value ? formatBalance(value, 6, needsParse) : '...'
+ value = value ? formatBalance(value, 6, needsParse, ticker) : '...'
var width = props.width
return (
diff --git a/old-ui/app/components/eth-balance.js b/old-ui/app/components/eth-balance.js
index 4f538fd31..4458e6a9a 100644
--- a/old-ui/app/components/eth-balance.js
+++ b/old-ui/app/components/eth-balance.js
@@ -1,12 +1,18 @@
const Component = require('react').Component
const h = require('react-hyperscript')
+const connect = require('react-redux').connect
const inherits = require('util').inherits
const formatBalance = require('../util').formatBalance
const generateBalanceObject = require('../util').generateBalanceObject
const Tooltip = require('./tooltip.js')
const FiatValue = require('./fiat-value.js')
-module.exports = EthBalanceComponent
+module.exports = connect(mapStateToProps)(EthBalanceComponent)
+function mapStateToProps (state) {
+ return {
+ ticker: state.metamask.ticker,
+ }
+}
inherits(EthBalanceComponent, Component)
function EthBalanceComponent () {
@@ -16,9 +22,9 @@ function EthBalanceComponent () {
EthBalanceComponent.prototype.render = function () {
var props = this.props
let { value } = props
- const { style, width } = props
+ const { ticker, style, width } = props
var needsParse = this.props.needsParse !== undefined ? this.props.needsParse : true
- value = value ? formatBalance(value, 6, needsParse) : '...'
+ value = value ? formatBalance(value, 6, needsParse, ticker) : '...'
return (
diff --git a/old-ui/app/components/pending-tx.js b/old-ui/app/components/pending-tx.js
index c8132539c..35e81210e 100644
--- a/old-ui/app/components/pending-tx.js
+++ b/old-ui/app/components/pending-tx.js
@@ -1,4 +1,5 @@
const Component = require('react').Component
+const connect = require('react-redux').connect
const h = require('react-hyperscript')
const inherits = require('util').inherits
const actions = require('../../../ui/app/actions')
@@ -19,7 +20,9 @@ const BNInput = require('./bn-as-decimal-input')
const MIN_GAS_PRICE_BN = new BN('0')
const MIN_GAS_LIMIT_BN = new BN('21000')
-module.exports = PendingTx
+module.exports = connect()(PendingTx)
+
+
inherits(PendingTx, Component)
function PendingTx () {
Component.call(this)
@@ -445,7 +448,8 @@ PendingTx.prototype.onSubmit = function (event) {
const txMeta = this.gatherTxMeta()
const valid = this.checkValidity()
this.setState({ valid, submitting: true })
- if (valid && this.verifyGasParams()) {
+ const validGasParams = this.verifyGasParams()
+ if (valid && validGasParams) {
this.props.sendTransaction(txMeta, event)
} else {
this.props.dispatch(actions.displayWarning('Invalid Gas Parameters'))
@@ -488,8 +492,12 @@ PendingTx.prototype.verifyGasParams = function () {
)
}
-PendingTx.prototype._notZeroOrEmptyString = function (obj) {
- return obj !== '' && obj !== '0x0'
+PendingTx.prototype._notZeroOrEmptyString = function (value) {
+ // allow undefined values
+ if (value === undefined) return true
+ // Geth will return '0x', and ganache-core v2.2.1 will return '0x0'
+ const valueIsEmpty = !value || value === '0x' || value === '0x0'
+ return !valueIsEmpty
}
PendingTx.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) {
diff --git a/old-ui/app/config.js b/old-ui/app/config.js
index 392a6dba7..7a93887a5 100644
--- a/old-ui/app/config.js
+++ b/old-ui/app/config.js
@@ -68,7 +68,7 @@ ConfigScreen.prototype.render = function () {
currentProviderDisplay(metamaskState),
- h('div', { style: {display: 'flex'} }, [
+ h('div', { style: {display: 'block'} }, [
h('input#new_rpc', {
placeholder: 'New RPC URL',
style: {
@@ -81,7 +81,70 @@ ConfigScreen.prototype.render = function () {
if (event.key === 'Enter') {
var element = event.target
var newRpc = element.value
- rpcValidation(newRpc, state)
+ var chainid = document.querySelector('input#chainid')
+ var ticker = document.querySelector('input#ticker')
+ var nickname = document.querySelector('input#nickname')
+ rpcValidation(newRpc, chainid.value, ticker.value, nickname.value, state)
+ }
+ },
+ }),
+ h('br'),
+ h('input#chainid', {
+ placeholder: 'ChainId (optional)',
+ style: {
+ width: 'inherit',
+ flex: '1 0 auto',
+ height: '30px',
+ margin: '8px',
+ },
+ onKeyPress (event) {
+ if (event.key === 'Enter') {
+ var element = document.querySelector('input#new_rpc')
+ var newRpc = element.value
+ var chainid = document.querySelector('input#chainid')
+ var ticker = document.querySelector('input#ticker')
+ var nickname = document.querySelector('input#nickname')
+ rpcValidation(newRpc, chainid.value, ticker.value, nickname.value, state)
+ }
+ },
+ }),
+ h('br'),
+ h('input#ticker', {
+ placeholder: 'Symbol (optional)',
+ style: {
+ width: 'inherit',
+ flex: '1 0 auto',
+ height: '30px',
+ margin: '8px',
+ },
+ onKeyPress (event) {
+ if (event.key === 'Enter') {
+ var element = document.querySelector('input#new_rpc')
+ var newRpc = element.value
+ var chainid = document.querySelector('input#chainid')
+ var ticker = document.querySelector('input#ticker')
+ var nickname = document.querySelector('input#nickname')
+ rpcValidation(newRpc, chainid.value, ticker.value, nickname.value, state)
+ }
+ },
+ }),
+ h('br'),
+ h('input#nickname', {
+ placeholder: 'Nickname (optional)',
+ style: {
+ width: 'inherit',
+ flex: '1 0 auto',
+ height: '30px',
+ margin: '8px',
+ },
+ onKeyPress (event) {
+ if (event.key === 'Enter') {
+ var element = document.querySelector('input#new_rpc')
+ var newRpc = element.value
+ var chainid = document.querySelector('input#chainid')
+ var ticker = document.querySelector('input#ticker')
+ var nickname = document.querySelector('input#nickname')
+ rpcValidation(newRpc, chainid.value, ticker.value, nickname.value, state)
}
},
}),
@@ -93,7 +156,10 @@ ConfigScreen.prototype.render = function () {
event.preventDefault()
var element = document.querySelector('input#new_rpc')
var newRpc = element.value
- rpcValidation(newRpc, state)
+ var chainid = document.querySelector('input#chainid')
+ var ticker = document.querySelector('input#ticker')
+ var nickname = document.querySelector('input#nickname')
+ rpcValidation(newRpc, chainid.value, ticker.value, nickname.value, state)
},
}, 'Save'),
]),
@@ -189,9 +255,9 @@ ConfigScreen.prototype.render = function () {
)
}
-function rpcValidation (newRpc, state) {
+function rpcValidation (newRpc, chainid, ticker = 'ETH', nickname = '', state) {
if (validUrl.isWebUri(newRpc)) {
- state.dispatch(actions.setRpcTarget(newRpc))
+ state.dispatch(actions.setRpcTarget(newRpc, chainid, ticker, nickname))
} else {
var appendedRpc = `http://${newRpc}`
if (validUrl.isWebUri(appendedRpc)) {
diff --git a/old-ui/app/util.js b/old-ui/app/util.js
index 962832ce7..40e79b88c 100644
--- a/old-ui/app/util.js
+++ b/old-ui/app/util.js
@@ -102,7 +102,7 @@ function parseBalance (balance) {
// Takes wei hex, returns an object with three properties.
// Its "formatted" property is what we generally use to render values.
-function formatBalance (balance, decimalsToKeep, needsParse = true) {
+function formatBalance (balance, decimalsToKeep, needsParse = true, ticker = 'ETH') {
var parsed = needsParse ? parseBalance(balance) : balance.split('.')
var beforeDecimal = parsed[0]
var afterDecimal = parsed[1]
@@ -112,14 +112,14 @@ function formatBalance (balance, decimalsToKeep, needsParse = true) {
if (afterDecimal !== '0') {
var sigFigs = afterDecimal.match(/^0*(.{2})/) // default: grabs 2 most significant digits
if (sigFigs) { afterDecimal = sigFigs[0] }
- formatted = '0.' + afterDecimal + ' ETH'
+ formatted = '0.' + afterDecimal + ` ${ticker}`
}
} else {
- formatted = beforeDecimal + '.' + afterDecimal.slice(0, 3) + ' ETH'
+ formatted = beforeDecimal + '.' + afterDecimal.slice(0, 3) + ` ${ticker}`
}
} else {
afterDecimal += Array(decimalsToKeep).join('0')
- formatted = beforeDecimal + '.' + afterDecimal.slice(0, decimalsToKeep) + ' ETH'
+ formatted = beforeDecimal + '.' + afterDecimal.slice(0, decimalsToKeep) + ` ${ticker}`
}
return formatted
}
diff --git a/package-lock.json b/package-lock.json
index 09b66d261..43a3aac15 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -489,6 +489,16 @@
}
}
},
+ "@sentry/browser": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-4.2.3.tgz",
+ "integrity": "sha512-XvuIc1aclz4zuP2LamDuSy62/gl1mmNxzF+Ni5L8mcghBDq0urnOdkblVQgzqGoH8mc2QfjEctGa5djWxg3Bpg==",
+ "requires": {
+ "@sentry/core": "4.2.3",
+ "@sentry/types": "4.2.3",
+ "@sentry/utils": "4.2.3"
+ }
+ },
"@sentry/cli": {
"version": "1.30.3",
"resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-1.30.3.tgz",
@@ -531,6 +541,48 @@
}
}
},
+ "@sentry/core": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-4.2.3.tgz",
+ "integrity": "sha512-xo5rvksftnaEdnKbdokyfuqgMnuqw1DFp0lDboIFHlEBcQde/AdThEgLujJWmbVNI3Cg7g8/HvP65f7QBjKfOw==",
+ "requires": {
+ "@sentry/hub": "4.2.3",
+ "@sentry/minimal": "4.2.3",
+ "@sentry/types": "4.2.3",
+ "@sentry/utils": "4.2.3"
+ }
+ },
+ "@sentry/hub": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-4.2.3.tgz",
+ "integrity": "sha512-7Jc/wz3vybYm1RX2wk/4zAQS8fo3uxvXYBkRfpm3OmnGgTlwDEmJwtegeGWFqufxLl85brZ19V1KAdulmO206A==",
+ "requires": {
+ "@sentry/types": "4.2.3",
+ "@sentry/utils": "4.2.3"
+ }
+ },
+ "@sentry/minimal": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-4.2.3.tgz",
+ "integrity": "sha512-Hus7LUeJDGsYpT2RTe6bUjG7mHG9uQoyDmW6pYUMN2dhD+cP5cPoTIXO4yxokwgAeDa+GH2/UXoASWc4s2eA2w==",
+ "requires": {
+ "@sentry/hub": "4.2.3",
+ "@sentry/types": "4.2.3"
+ }
+ },
+ "@sentry/types": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-4.2.3.tgz",
+ "integrity": "sha512-Z7laXlLtLSEXcKzgcD2caWPMTM8sAvR86rssYM5uYb3azC5PO0aAvuhjokkdv1+Ke1Bg7lkaNZamiCSyaH/9xg=="
+ },
+ "@sentry/utils": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-4.2.3.tgz",
+ "integrity": "sha512-D6+M1081wCwGp8adWV3KFOxrxFmVyjMJ45x6/TnYvXdgDyc+t28oil21FHeKhwjld9eMqgQ5Tf1OOvos1MNBQg==",
+ "requires": {
+ "@sentry/types": "4.2.3"
+ }
+ },
"@sinonjs/formatio": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz",
@@ -6131,9 +6183,9 @@
}
},
"clone": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz",
- "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs="
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
},
"clone-buffer": {
"version": "1.0.0",
@@ -9570,9 +9622,9 @@
}
},
"eth-block-tracker": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-4.0.3.tgz",
- "integrity": "sha512-Uy+5hEvOT1/C6N1Lw/uQ10v03ArnNEQEkM0yhJQWwpd8Ymy3sw4jk75SE58s1spfOBBtnr8JaSAFioAFSeg6HA==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-4.1.0.tgz",
+ "integrity": "sha512-991xTy6CzYYbizkHmgRFFI9iGx1OCISve8sSLuOlt7/yD7VFH1Jd8mOmBqxaG5ywGkIXdwAR78nQ2WDReETzBg==",
"requires": {
"eth-json-rpc-infura": "^3.1.2",
"eth-query": "^2.1.0",
@@ -9604,7 +9656,7 @@
},
"eth-json-rpc-middleware": {
"version": "1.6.0",
- "resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz",
+ "resolved": "http://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz",
"integrity": "sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q==",
"requires": {
"async": "^2.5.0",
@@ -9643,12 +9695,12 @@
},
"node-fetch": {
"version": "2.1.2",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz",
+ "resolved": "http://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz",
"integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U="
},
"whatwg-fetch": {
"version": "2.0.4",
- "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
+ "resolved": "http://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
"integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng=="
}
}
@@ -9899,29 +9951,26 @@
}
},
"eth-json-rpc-middleware": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-3.1.3.tgz",
- "integrity": "sha512-glp/mCefhsqrgVOTTuYlHYiTL+9mMPfaZsuQv4vnRg3kqNigblS1nqARaMeVW9WOM8ssh9TqIFpuUr7JDgNmKQ==",
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-3.1.6.tgz",
+ "integrity": "sha512-yf17/rAM4ElKMul8oSvuK7JuYIYEFFdy2YGPo2EZbuOEv2Wq1bteMlppgqZ9NYHriXLAOWV+ojY9kWHGbcU4xA==",
"dev": true,
"requires": {
- "async": "^2.5.0",
"btoa": "^1.2.1",
"clone": "^2.1.1",
"eth-query": "^2.1.2",
"eth-sig-util": "^1.4.2",
- "eth-tx-summary": "^3.1.2",
+ "eth-tx-summary": "^3.2.3",
"ethereumjs-block": "^1.6.0",
"ethereumjs-tx": "^1.3.3",
"ethereumjs-util": "^5.1.2",
- "ethereumjs-vm": "^2.1.0",
+ "ethereumjs-vm": "^2.4.0",
"fetch-ponyfill": "^4.0.0",
- "json-rpc-engine": "^3.6.3",
+ "json-rpc-engine": "^3.8.0",
"json-rpc-error": "^2.0.0",
"json-stable-stringify": "^1.0.1",
"pify": "^3.0.0",
- "promise-to-callback": "^1.0.0",
- "safe-event-emitter": "^1.0.1",
- "tape": "^4.6.3"
+ "safe-event-emitter": "^1.0.1"
},
"dependencies": {
"eth-sig-util": {
@@ -9930,12 +9979,12 @@
"integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=",
"dev": true,
"requires": {
- "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7",
+ "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799",
"ethereumjs-util": "^5.1.1"
}
},
"ethereumjs-abi": {
- "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7",
+ "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799",
"from": "git+https://github.com/ethereumjs/ethereumjs-abi.git",
"dev": true,
"requires": {
@@ -9957,6 +10006,31 @@
"safe-buffer": "^5.1.1",
"secp256k1": "^3.0.1"
}
+ },
+ "ethereumjs-vm": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.4.0.tgz",
+ "integrity": "sha512-MJ4lCWa5c6LhahhhvoDKW+YGjK00ZQn0RHHLh4L+WaH1k6Qv7/q3uTluew6sJGNCZdlO0yYMDXYW9qyxLHKlgQ==",
+ "dev": true,
+ "requires": {
+ "async": "^2.1.2",
+ "async-eventemitter": "^0.2.2",
+ "ethereumjs-account": "^2.0.3",
+ "ethereumjs-block": "~1.7.0",
+ "ethereumjs-common": "~0.4.0",
+ "ethereumjs-util": "^5.2.0",
+ "fake-merkle-patricia-tree": "^1.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "merkle-patricia-tree": "^2.1.2",
+ "rustbn.js": "~0.2.0",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "rustbn.js": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz",
+ "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==",
+ "dev": true
}
}
},
@@ -10390,7 +10464,7 @@
"dependencies": {
"babelify": {
"version": "7.3.0",
- "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz",
+ "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz",
"integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=",
"requires": {
"babel-core": "^6.0.14",
@@ -10907,6 +10981,12 @@
}
}
},
+ "ethereumjs-common": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-0.4.1.tgz",
+ "integrity": "sha512-ywYGsOeGCsMNWso5Y4GhjWI24FJv9FK7+VyVKiQgXg8ZRDPXJ7F/kJ1CnjtkjTvDF4e0yqU+FWswlqR3bmZQ9Q==",
+ "dev": true
+ },
"ethereumjs-tx": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.3.tgz",
@@ -14249,14 +14329,354 @@
"dev": true
},
"glob-watcher": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-4.0.0.tgz",
- "integrity": "sha1-nmOo/25h6TLebMLK7OUHGm1zcyk=",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.1.tgz",
+ "integrity": "sha512-fK92r2COMC199WCyGUblrZKhjra3cyVMDiypDdqg1vsSDmexnbYivK1kNR4QItiNXLKmGlqan469ks67RtNa2g==",
"requires": {
"async-done": "^1.2.0",
- "chokidar": "^1.4.3",
+ "chokidar": "^2.0.0",
"just-debounce": "^1.0.0",
"object.defaults": "^1.1.0"
+ },
+ "dependencies": {
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ }
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "chokidar": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz",
+ "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==",
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.0",
+ "braces": "^2.3.0",
+ "fsevents": "^1.2.2",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.1",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "lodash.debounce": "^4.0.8",
+ "normalize-path": "^2.1.1",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.0.0",
+ "upath": "^1.0.5"
+ }
+ },
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+ "requires": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ }
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "requires": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
+ }
+ }
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "requires": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+ },
+ "is-glob": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
+ "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+ },
+ "kind-of": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ },
+ "dependencies": {
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ }
+ }
+ },
+ "upath": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz",
+ "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw=="
+ }
}
},
"glob2base": {
@@ -14381,10 +14801,10 @@
"dev": true
},
"gulp": {
- "version": "github:gulpjs/gulp#71c094a51c7972d26f557899ddecab0210ef3776",
- "from": "github:gulpjs/gulp#4.0",
+ "version": "github:gulpjs/gulp#55eb23a268dcc7340bb40808600fd4802848c06f",
+ "from": "github:gulpjs/gulp#v4.0.0",
"requires": {
- "glob-watcher": "^4.0.0",
+ "glob-watcher": "^5.0.0",
"gulp-cli": "^2.0.0",
"undertaker": "^1.0.0",
"vinyl-fs": "^3.0.0"
@@ -21494,9 +21914,9 @@
"dev": true
},
"mute-stdout": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.0.tgz",
- "integrity": "sha1-WzLqB+tDyd7WEwQ0z5JvRrKn/U0="
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz",
+ "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg=="
},
"mute-stream": {
"version": "0.0.7",
@@ -27090,11 +27510,6 @@
"eve-raphael": "0.5.0"
}
},
- "raven-js": {
- "version": "3.24.2",
- "resolved": "https://registry.npmjs.org/raven-js/-/raven-js-3.24.2.tgz",
- "integrity": "sha512-Dy/FHDxuo5pXywVf8Nrs5utB2juMATpkxWGqHjVbpFD3m8CaWYLvkB5SEXjWFUZ5GvUsrBVVQ+Dfcp0x6Z7SOg=="
- },
"raw-body": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz",
@@ -33471,9 +33886,9 @@
"optional": true
},
"v8flags": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.0.tgz",
- "integrity": "sha512-0m69VIK2dudEf2Ub0xwLQhZkDZu85OmiOpTw+UGDt56ibviYICHziM/3aE+oVg7IjGPp0c83w3eSVqa+lYZ9UQ==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz",
+ "integrity": "sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==",
"requires": {
"homedir-polyfill": "^1.0.1"
}
@@ -33700,9 +34115,12 @@
},
"dependencies": {
"convert-source-map": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz",
- "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU="
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz",
+ "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==",
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ }
}
}
},
diff --git a/package.json b/package.json
index c994acc2f..1164c6b4c 100644
--- a/package.json
+++ b/package.json
@@ -82,6 +82,7 @@
},
"dependencies": {
"@material-ui/core": "1.0.0",
+ "@sentry/browser": "^4.1.1",
"@zxing/library": "^0.8.0",
"abi-decoder": "^1.0.9",
"asmcrypto.js": "0.22.0",
@@ -97,7 +98,7 @@
"browserify-derequire": "^0.9.4",
"browserify-unibabel": "^3.0.0",
"classnames": "^2.2.5",
- "clone": "^2.1.1",
+ "clone": "^2.1.2",
"copy-to-clipboard": "^3.0.8",
"css-loader": "^0.28.11",
"currency-formatter": "^1.4.2",
@@ -112,7 +113,7 @@
"ensnare": "^1.0.0",
"eslint-plugin-react": "^7.4.0",
"eth-bin-to-ops": "^1.0.1",
- "eth-block-tracker": "^4.0.3",
+ "eth-block-tracker": "^4.1.0",
"eth-contract-metadata": "github:MetaMask/eth-contract-metadata#master",
"eth-ens-namehash": "^2.0.8",
"eth-hd-keyring": "^1.2.2",
@@ -143,7 +144,7 @@
"fast-levenshtein": "^2.0.6",
"file-loader": "^1.1.11",
"fuse.js": "^3.2.0",
- "gulp": "github:gulpjs/gulp#4.0",
+ "gulp": "github:gulpjs/gulp#v4.0.0",
"gulp-autoprefixer": "^5.0.0",
"gulp-debug": "^3.2.0",
"gulp-eslint": "^4.0.0",
@@ -186,7 +187,6 @@
"pumpify": "^1.3.4",
"qrcode-npm": "0.0.3",
"ramda": "^0.24.1",
- "raven-js": "^3.24.2",
"react": "^15.6.2",
"react-addons-css-transition-group": "^15.6.0",
"react-dom": "^15.6.2",
@@ -261,7 +261,7 @@
"eslint-plugin-json": "^1.2.0",
"eslint-plugin-mocha": "^5.0.0",
"eslint-plugin-react": "^7.4.0",
- "eth-json-rpc-middleware": "^3.1.3",
+ "eth-json-rpc-middleware": "^3.1.6",
"eth-keyring-controller": "^3.3.1",
"fetch-mock": "^6.5.2",
"file-loader": "^1.1.11",
diff --git a/test/data/mock-state.json b/test/data/mock-state.json
index 7e083c60e..8deff5531 100644
--- a/test/data/mock-state.json
+++ b/test/data/mock-state.json
@@ -111,7 +111,9 @@
"0x108cf70c7d384c552f42c07c41c0e1e46d77ea0d": 0.00039345803819379796,
"0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5": 0.00008189274407698049
},
+ "ticker": "ETH",
"currentCurrency": "usd",
+ "nativeCurrency": "ETH",
"conversionRate": 556.12,
"addressBook": [
{
@@ -1248,4 +1250,4 @@
"context": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc"
}
}
-} \ No newline at end of file
+}
diff --git a/test/e2e/beta/from-import-beta-ui.spec.js b/test/e2e/beta/from-import-beta-ui.spec.js
index b782a1c40..d2c3f8958 100644
--- a/test/e2e/beta/from-import-beta-ui.spec.js
+++ b/test/e2e/beta/from-import-beta-ui.spec.js
@@ -319,7 +319,7 @@ describe('Using MetaMask with an existing account', function () {
const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
assert.equal(txValues.length, 1)
- assert.equal(await txValues[0].getText(), '-1 ETH')
+ assert.ok(/-1\s*ETH/.test(await txValues[0].getText()))
})
})
diff --git a/test/e2e/beta/metamask-beta-ui.spec.js b/test/e2e/beta/metamask-beta-ui.spec.js
index f29f242c1..eaa7d18cd 100644
--- a/test/e2e/beta/metamask-beta-ui.spec.js
+++ b/test/e2e/beta/metamask-beta-ui.spec.js
@@ -371,7 +371,7 @@ describe('MetaMask', function () {
it('balance renders', async () => {
const balance = await findElement(driver, By.css('.balance-display .token-amount'))
- await driver.wait(until.elementTextMatches(balance, /100.+ETH/))
+ await driver.wait(until.elementTextMatches(balance, /100\s*ETH/))
await delay(regularDelayMs)
})
})
@@ -420,7 +420,7 @@ describe('MetaMask', function () {
if (process.env.SELENIUM_BROWSER !== 'firefox') {
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
- await driver.wait(until.elementTextMatches(txValues, /-1\sETH/), 10000)
+ await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
}
})
})
@@ -462,7 +462,7 @@ describe('MetaMask', function () {
assert.equal(transactions.length, 2)
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
- await driver.wait(until.elementTextMatches(txValues, /-3\sETH/), 10000)
+ await driver.wait(until.elementTextMatches(txValues, /-3\s*ETH/), 10000)
})
})
@@ -540,7 +540,7 @@ describe('MetaMask', function () {
await findElements(driver, By.css('.transaction-list-item'))
const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
- await driver.wait(until.elementTextMatches(txListValue, /-4\sETH/), 10000)
+ await driver.wait(until.elementTextMatches(txListValue, /-4\s*ETH/), 10000)
await txListValue.click()
await delay(regularDelayMs)
@@ -574,7 +574,7 @@ describe('MetaMask', function () {
}, 10000)
const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
- await driver.wait(until.elementTextMatches(txValues[0], /-4\sETH/), 10000)
+ await driver.wait(until.elementTextMatches(txValues[0], /-4\s*ETH/), 10000)
// const txAccounts = await findElements(driver, By.css('.tx-list-account'))
// const firstTxAddress = await txAccounts[0].getText()
@@ -606,7 +606,7 @@ describe('MetaMask', function () {
}, 10000)
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
- await driver.wait(until.elementTextMatches(txValues, /-0\sETH/), 10000)
+ await driver.wait(until.elementTextMatches(txValues, /-0\s*ETH/), 10000)
await closeAllWindowHandlesExcept(driver, [extension, dapp])
await driver.switchTo().window(extension)
@@ -616,9 +616,9 @@ describe('MetaMask', function () {
const balance = await findElement(driver, By.css('.transaction-view-balance__primary-balance'))
await delay(regularDelayMs)
if (process.env.SELENIUM_BROWSER !== 'firefox') {
- await driver.wait(until.elementTextMatches(balance, /^92.*ETH.*$/), 10000)
+ await driver.wait(until.elementTextMatches(balance, /^92.*\s*ETH.*$/), 10000)
const tokenAmount = await balance.getText()
- assert.ok(/^92.*ETH.*$/.test(tokenAmount))
+ assert.ok(/^92.*\s*ETH.*$/.test(tokenAmount))
await delay(regularDelayMs)
}
})
@@ -764,7 +764,7 @@ describe('MetaMask', function () {
// test cancelled on firefox until https://github.com/mozilla/geckodriver/issues/906 is resolved,
// or possibly until we use latest version of firefox in the tests
if (process.env.SELENIUM_BROWSER !== 'firefox') {
- await driver.wait(until.elementTextMatches(txValues[0], /-50\sTST/), 10000)
+ await driver.wait(until.elementTextMatches(txValues[0], /-50\s*TST/), 10000)
}
driver.wait(async () => {
@@ -798,7 +798,7 @@ describe('MetaMask', function () {
await findElements(driver, By.css('.transaction-list__pending-transactions'))
const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
- await driver.wait(until.elementTextMatches(txListValue, /-7\sTST/), 10000)
+ await driver.wait(until.elementTextMatches(txListValue, /-7\s*TST/), 10000)
await txListValue.click()
await delay(regularDelayMs)
@@ -851,7 +851,7 @@ describe('MetaMask', function () {
}, 10000)
const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
- await driver.wait(until.elementTextMatches(txValues[0], /-7\sTST/))
+ await driver.wait(until.elementTextMatches(txValues[0], /-7\s*TST/))
const txStatuses = await findElements(driver, By.css('.transaction-list-item__action'))
await driver.wait(until.elementTextMatches(txStatuses[0], /Sent\sToken/))
@@ -897,7 +897,7 @@ describe('MetaMask', function () {
const [txListItem] = await findElements(driver, By.css('.transaction-list-item'))
const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
- await driver.wait(until.elementTextMatches(txListValue, /-7\sTST/))
+ await driver.wait(until.elementTextMatches(txListValue, /-7\s*TST/))
await txListItem.click()
await delay(regularDelayMs)
})
@@ -974,7 +974,7 @@ describe('MetaMask', function () {
}, 10000)
const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
- await driver.wait(until.elementTextMatches(txValues[0], /-7\sTST/))
+ await driver.wait(until.elementTextMatches(txValues[0], /-7\s*TST/))
const txStatuses = await findElements(driver, By.css('.transaction-list-item__action'))
await driver.wait(until.elementTextMatches(txStatuses[0], /Approve/))
})
@@ -1027,7 +1027,7 @@ describe('MetaMask', function () {
it('renders the balance for the chosen token', async () => {
const balance = await findElement(driver, By.css('.transaction-view-balance__token-balance'))
- await driver.wait(until.elementTextMatches(balance, /0\sBAT/))
+ await driver.wait(until.elementTextMatches(balance, /0\s*BAT/))
await delay(regularDelayMs)
})
})
diff --git a/test/e2e/beta/run-drizzle.sh b/test/e2e/beta/run-drizzle.sh
index 7bfffd7e6..bfb7e6fdb 100755
--- a/test/e2e/beta/run-drizzle.sh
+++ b/test/e2e/beta/run-drizzle.sh
@@ -11,7 +11,7 @@ sleep 5
cd test/e2e/beta/
rm -rf drizzle-test
mkdir drizzle-test && cd drizzle-test
-npm install truffle
+sudo npm install -g truffle
truffle unbox drizzle
echo "Deploying contracts for Drizzle test..."
truffle compile && truffle migrate
diff --git a/test/integration/lib/currency-localization.js b/test/integration/lib/currency-localization.js
index 8d5acf5d0..f6b751ba2 100644
--- a/test/integration/lib/currency-localization.js
+++ b/test/integration/lib/currency-localization.js
@@ -25,5 +25,5 @@ async function runCurrencyLocalizationTest (assert, done) {
const txView = await queryAsync($, '.transaction-view')
const heroBalance = await findAsync($(txView), '.transaction-view-balance__balance')
const fiatAmount = await findAsync($(heroBalance), '.transaction-view-balance__secondary-balance')
- assert.equal(fiatAmount[0].textContent, '₱102,707.97 PHP')
+ assert.equal(fiatAmount[0].textContent, '₱102,707.97PHP')
}
diff --git a/test/integration/lib/send-new-ui.js b/test/integration/lib/send-new-ui.js
index e13016e68..271dd91cf 100644
--- a/test/integration/lib/send-new-ui.js
+++ b/test/integration/lib/send-new-ui.js
@@ -112,9 +112,9 @@ async function runSendFlowTest (assert, done) {
errorMessage = $('.send-v2__error')
assert.equal(errorMessage.length, 0, 'send should stop rendering amount error message after amount is corrected')
- await customizeGas(assert, 0, 21000, '0 ETH', '$0.00 USD')
- await customizeGas(assert, 1, 21000, '0.000021 ETH', '$0.03 USD')
- await customizeGas(assert, 500, 60000, '0.03 ETH', '$36.03 USD')
+ await customizeGas(assert, 0, 21000, '0ETH', '$0.00USD')
+ await customizeGas(assert, 1, 21000, '0.000021ETH', '$0.03USD')
+ await customizeGas(assert, 500, 60000, '0.03ETH', '$36.03USD')
const sendButton = await queryAsync($, 'button.btn-primary.btn--large.page-container__footer-button')
assert.equal(sendButton[0].textContent, 'Next', 'next button rendered')
diff --git a/test/unit/app/controllers/network-contoller-test.js b/test/unit/app/controllers/network-contoller-test.js
index 822311931..7959e6cc1 100644
--- a/test/unit/app/controllers/network-contoller-test.js
+++ b/test/unit/app/controllers/network-contoller-test.js
@@ -47,7 +47,7 @@ describe('# Network Controller', function () {
describe('#setNetworkState', function () {
it('should update the network', function () {
- networkController.setNetworkState(1)
+ networkController.setNetworkState(1, 'rpc')
const networkState = networkController.getNetworkState()
assert.equal(networkState, 1, 'network is 1')
})
diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js
index b5ccf3fb5..c64c47ae9 100644
--- a/test/unit/app/controllers/preferences-controller-test.js
+++ b/test/unit/app/controllers/preferences-controller-test.js
@@ -375,6 +375,11 @@ describe('preferences controller', function () {
await preferencesController.requestWatchAsset(req, res, asy.next, asy.end)
sandbox.assert.called(stubEnd)
sandbox.assert.notCalled(stubNext)
+ req.method = 'wallet_watchAsset'
+ req.params.type = 'someasset'
+ await preferencesController.requestWatchAsset(req, res, asy.next, asy.end)
+ sandbox.assert.calledTwice(stubEnd)
+ sandbox.assert.notCalled(stubNext)
})
it('should through error if method is supported but asset type is not', async function () {
req.method = 'metamask_watchAsset'
@@ -479,5 +484,24 @@ describe('preferences controller', function () {
assert.equal(preferencesController.store.getState().seedWords, 'foo bar baz')
})
})
+
+ describe('on updateFrequentRpcList', function () {
+ it('should add custom RPC url to state', function () {
+ preferencesController.addToFrequentRpcList('rpc_url', 1)
+ preferencesController.addToFrequentRpcList('http://localhost:8545', 1)
+ assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }] )
+ preferencesController.addToFrequentRpcList('rpc_url', 1)
+ assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }] )
+ })
+
+ it('should remove custom RPC url from state', function () {
+ preferencesController.addToFrequentRpcList('rpc_url', 1)
+ assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }] )
+ preferencesController.removeFromFrequentRpcList('other_rpc_url')
+ preferencesController.removeFromFrequentRpcList('http://localhost:8545')
+ preferencesController.removeFromFrequentRpcList('rpc_url')
+ assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [])
+ })
+ })
})
diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js
index 748a58b32..df7d2ee8f 100644
--- a/test/unit/ui/app/actions.spec.js
+++ b/test/unit/ui/app/actions.spec.js
@@ -1133,7 +1133,7 @@ describe('Actions', () => {
{ type: 'DISPLAY_WARNING', value: 'Had a problem changing networks!' },
]
- setRpcTargetSpy.callsFake((newRpc, callback) => {
+ setRpcTargetSpy.callsFake((newRpc, chainId, ticker, nickname, callback) => {
callback(new Error('error'))
})
diff --git a/ui/app/actions.js b/ui/app/actions.js
index f8a375e2f..a8b9189e9 100644
--- a/ui/app/actions.js
+++ b/ui/app/actions.js
@@ -309,7 +309,7 @@ var actions = {
setPreference,
updatePreferences,
UPDATE_PREFERENCES: 'UPDATE_PREFERENCES',
- setUseETHAsPrimaryCurrencyPreference,
+ setUseNativeCurrencyAsPrimaryCurrencyPreference,
setMouseUserState,
SET_MOUSE_USER_STATE: 'SET_MOUSE_USER_STATE',
@@ -1874,10 +1874,10 @@ function updateProviderType (type) {
}
}
-function setRpcTarget (newRpc) {
+function setRpcTarget (newRpc, chainId, ticker = 'ETH', nickname = '') {
return (dispatch) => {
- log.debug(`background.setRpcTarget: ${newRpc}`)
- background.setCustomRpc(newRpc, (err, result) => {
+ log.debug(`background.setRpcTarget: ${newRpc} ${chainId} ${ticker} ${nickname}`)
+ background.setCustomRpc(newRpc, chainId, ticker, nickname, (err, result) => {
if (err) {
log.error(err)
return dispatch(actions.displayWarning('Had a problem changing networks!'))
@@ -2330,8 +2330,8 @@ function updatePreferences (value) {
}
}
-function setUseETHAsPrimaryCurrencyPreference (value) {
- return setPreference('useETHAsPrimaryCurrency', value)
+function setUseNativeCurrencyAsPrimaryCurrencyPreference (value) {
+ return setPreference('useNativeCurrencyAsPrimaryCurrency', value)
}
function setNetworkNonce (networkNonce) {
diff --git a/ui/app/app.js b/ui/app/app.js
index aeb3d05ee..b3aff1f39 100644
--- a/ui/app/app.js
+++ b/ui/app/app.js
@@ -101,7 +101,7 @@ class App extends Component {
network,
isMouseUser,
provider,
- frequentRpcList,
+ frequentRpcListDetail,
currentView,
setMouseUserState,
sidebar,
@@ -147,7 +147,7 @@ class App extends Component {
// network dropdown
h(NetworkDropdown, {
provider,
- frequentRpcList,
+ frequentRpcListDetail,
}, []),
h(AccountMenu),
@@ -230,7 +230,7 @@ App.propTypes = {
alertMessage: PropTypes.string,
network: PropTypes.string,
provider: PropTypes.object,
- frequentRpcList: PropTypes.array,
+ frequentRpcListDetail: PropTypes.array,
currentView: PropTypes.object,
sidebar: PropTypes.object,
alertOpen: PropTypes.bool,
@@ -322,7 +322,7 @@ function mapStateToProps (state) {
forgottenPassword: state.appState.forgottenPassword,
nextUnreadNotice,
lostAccounts,
- frequentRpcList: state.metamask.frequentRpcList || [],
+ frequentRpcListDetail: state.metamask.frequentRpcListDetail || [],
currentCurrency: state.metamask.currentCurrency,
isMouseUser: state.appState.isMouseUser,
betaUI: state.metamask.featureFlags.betaUI,
diff --git a/ui/app/components/account-dropdowns.js b/ui/app/components/account-dropdowns.js
index 043008a36..06376e48b 100644
--- a/ui/app/components/account-dropdowns.js
+++ b/ui/app/components/account-dropdowns.js
@@ -6,10 +6,11 @@ const genAccountLink = require('etherscan-link').createAccountLink
const connect = require('react-redux').connect
const Dropdown = require('./dropdown').Dropdown
const DropdownMenuItem = require('./dropdown').DropdownMenuItem
-const Identicon = require('./identicon')
const copyToClipboard = require('copy-to-clipboard')
const { checksumAddress } = require('../util')
+import Identicon from './identicon'
+
class AccountDropdowns extends Component {
constructor (props) {
super(props)
diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js
index c9c5b60e1..94eae8d07 100644
--- a/ui/app/components/account-menu/index.js
+++ b/ui/app/components/account-menu/index.js
@@ -7,10 +7,10 @@ const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const actions = require('../../actions')
const { Menu, Item, Divider, CloseArea } = require('../dropdowns/components/menu')
-const Identicon = require('../identicon')
const { ENVIRONMENT_TYPE_POPUP } = require('../../../../app/scripts/lib/enums')
const { getEnvironmentType } = require('../../../../app/scripts/lib/util')
const Tooltip = require('../tooltip')
+import Identicon from '../identicon'
import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display'
import { PRIMARY } from '../../constants/common'
diff --git a/ui/app/components/account-panel.js b/ui/app/components/account-panel.js
index abaaf8163..a379ed3ac 100644
--- a/ui/app/components/account-panel.js
+++ b/ui/app/components/account-panel.js
@@ -1,7 +1,7 @@
const inherits = require('util').inherits
const Component = require('react').Component
const h = require('react-hyperscript')
-const Identicon = require('./identicon')
+import Identicon from './identicon'
const formatBalance = require('../util').formatBalance
const addressSummary = require('../util').addressSummary
diff --git a/ui/app/components/app-header/app-header.component.js b/ui/app/components/app-header/app-header.component.js
index b8b002dcc..c82dc1de9 100644
--- a/ui/app/components/app-header/app-header.component.js
+++ b/ui/app/components/app-header/app-header.component.js
@@ -2,13 +2,13 @@ import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import { matchPath } from 'react-router-dom'
+import Identicon from '../identicon'
const {
ENVIRONMENT_TYPE_NOTIFICATION,
ENVIRONMENT_TYPE_POPUP,
} = require('../../../../app/scripts/lib/enums')
const { DEFAULT_ROUTE, INITIALIZE_ROUTE, CONFIRM_TRANSACTION_ROUTE } = require('../../routes')
-const Identicon = require('../identicon')
const NetworkIndicator = require('../network')
export default class AppHeader extends PureComponent {
diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js
index e1fcf08e0..0f8514c81 100644
--- a/ui/app/components/balance-component.js
+++ b/ui/app/components/balance-component.js
@@ -2,11 +2,11 @@ const Component = require('react').Component
const connect = require('react-redux').connect
const h = require('react-hyperscript')
const inherits = require('util').inherits
-const TokenBalance = require('./token-balance')
-const Identicon = require('./identicon')
+import TokenBalance from './token-balance'
+import Identicon from './identicon'
import UserPreferencedCurrencyDisplay from './user-preferenced-currency-display'
import { PRIMARY, SECONDARY } from '../constants/common'
-const { getAssetImages, conversionRateSelector, getCurrentCurrency} = require('../selectors')
+const { getNativeCurrency, getAssetImages, conversionRateSelector, getCurrentCurrency} = require('../selectors')
const { formatBalance } = require('../util')
@@ -21,6 +21,7 @@ function mapStateToProps (state) {
return {
account,
network,
+ nativeCurrency: getNativeCurrency(state),
conversionRate: conversionRateSelector(state),
currentCurrency: getCurrentCurrency(state),
assetImages: getAssetImages(state),
@@ -66,10 +67,10 @@ BalanceComponent.prototype.renderTokenBalance = function () {
BalanceComponent.prototype.renderBalance = function () {
const props = this.props
- const { account } = props
+ const { account, nativeCurrency } = props
const balanceValue = account && account.balance
const needsParse = 'needsParse' in props ? props.needsParse : true
- const formattedBalance = balanceValue ? formatBalance(balanceValue, 6, needsParse) : '...'
+ const formattedBalance = balanceValue ? formatBalance(balanceValue, 6, needsParse, nativeCurrency) : '...'
const showFiat = 'showFiat' in props ? props.showFiat : true
if (formattedBalance === 'None' || formattedBalance === '...') {
@@ -81,11 +82,12 @@ BalanceComponent.prototype.renderBalance = function () {
}
return h('div.flex-column.balance-display', {}, [
- h('div.token-amount', {}, h(UserPreferencedCurrencyDisplay, {
+ h(UserPreferencedCurrencyDisplay, {
+ className: 'token-amount',
value: balanceValue,
type: PRIMARY,
ethNumberOfDecimals: 3,
- })),
+ }),
showFiat && h(UserPreferencedCurrencyDisplay, {
value: balanceValue,
diff --git a/ui/app/components/currency-display/currency-display.component.js b/ui/app/components/currency-display/currency-display.component.js
index 5f5717be3..2d7413b57 100644
--- a/ui/app/components/currency-display/currency-display.component.js
+++ b/ui/app/components/currency-display/currency-display.component.js
@@ -1,7 +1,7 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
-import { ETH, GWEI } from '../../constants/common'
+import { GWEI } from '../../constants/common'
export default class CurrencyDisplay extends PureComponent {
static propTypes = {
@@ -10,8 +10,9 @@ export default class CurrencyDisplay extends PureComponent {
prefix: PropTypes.string,
prefixComponent: PropTypes.node,
style: PropTypes.object,
+ suffix: PropTypes.string,
// Used in container
- currency: PropTypes.oneOf([ETH]),
+ currency: PropTypes.string,
denomination: PropTypes.oneOf([GWEI]),
value: PropTypes.string,
numberOfDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
@@ -19,17 +20,25 @@ export default class CurrencyDisplay extends PureComponent {
}
render () {
- const { className, displayValue, prefix, prefixComponent, style } = this.props
+ const { className, displayValue, prefix, prefixComponent, style, suffix } = this.props
const text = `${prefix || ''}${displayValue}`
+ const title = `${text} ${suffix}`
return (
<div
className={classnames('currency-display-component', className)}
style={style}
- title={text}
+ title={title}
>
{ prefixComponent}
<span className="currency-display-component__text">{ text }</span>
+ {
+ suffix && (
+ <span className="currency-display-component__suffix">
+ { suffix }
+ </span>
+ )
+ }
</div>
)
}
diff --git a/ui/app/components/currency-display/currency-display.container.js b/ui/app/components/currency-display/currency-display.container.js
index b387229b5..6ddf07172 100644
--- a/ui/app/components/currency-display/currency-display.container.js
+++ b/ui/app/components/currency-display/currency-display.container.js
@@ -3,16 +3,17 @@ import CurrencyDisplay from './currency-display.component'
import { getValueFromWeiHex, formatCurrency } from '../../helpers/confirm-transaction/util'
const mapStateToProps = state => {
- const { metamask: { currentCurrency, conversionRate } } = state
+ const { metamask: { nativeCurrency, currentCurrency, conversionRate } } = state
return {
currentCurrency,
conversionRate,
+ nativeCurrency,
}
}
const mergeProps = (stateProps, dispatchProps, ownProps) => {
- const { currentCurrency, conversionRate, ...restStateProps } = stateProps
+ const { nativeCurrency, currentCurrency, conversionRate, ...restStateProps } = stateProps
const {
value,
numberOfDecimals = 2,
@@ -24,16 +25,17 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
const toCurrency = currency || currentCurrency
const convertedValue = getValueFromWeiHex({
- value, toCurrency, conversionRate, numberOfDecimals, toDenomination: denomination,
+ value, fromCurrency: nativeCurrency, toCurrency, conversionRate, numberOfDecimals, toDenomination: denomination,
})
- const formattedValue = formatCurrency(convertedValue, toCurrency)
- const displayValue = hideLabel ? formattedValue : `${formattedValue} ${toCurrency.toUpperCase()}`
+ const displayValue = formatCurrency(convertedValue, toCurrency)
+ const suffix = hideLabel ? undefined : toCurrency.toUpperCase()
return {
...restStateProps,
...dispatchProps,
...restOwnProps,
displayValue,
+ suffix,
}
}
diff --git a/ui/app/components/currency-display/index.scss b/ui/app/components/currency-display/index.scss
index 8c0196102..313c932b8 100644
--- a/ui/app/components/currency-display/index.scss
+++ b/ui/app/components/currency-display/index.scss
@@ -7,4 +7,8 @@
overflow: hidden;
text-overflow: ellipsis;
}
+
+ &__suffix {
+ padding-left: 4px;
+ }
}
diff --git a/ui/app/components/currency-display/tests/currency-display.container.test.js b/ui/app/components/currency-display/tests/currency-display.container.test.js
index b9f98c543..0c886af50 100644
--- a/ui/app/components/currency-display/tests/currency-display.container.test.js
+++ b/ui/app/components/currency-display/tests/currency-display.container.test.js
@@ -20,12 +20,14 @@ describe('CurrencyDisplay container', () => {
metamask: {
conversionRate: 280.45,
currentCurrency: 'usd',
+ nativeCurrency: 'ETH',
},
}
assert.deepEqual(mapStateToProps(mockState), {
conversionRate: 280.45,
currentCurrency: 'usd',
+ nativeCurrency: 'ETH',
})
})
})
@@ -35,6 +37,7 @@ describe('CurrencyDisplay container', () => {
const mockStateProps = {
conversionRate: 280.45,
currentCurrency: 'usd',
+ nativeCurrency: 'ETH',
}
const tests = [
@@ -43,71 +46,93 @@ describe('CurrencyDisplay container', () => {
value: '0x2386f26fc10000',
numberOfDecimals: 2,
currency: 'usd',
+ nativeCurrency: 'ETH',
},
result: {
- displayValue: '$2.80 USD',
+ displayValue: '$2.80',
+ suffix: 'USD',
+ nativeCurrency: 'ETH',
},
},
{
props: {
value: '0x2386f26fc10000',
+ currency: 'usd',
+ nativeCurrency: 'ETH',
},
result: {
- displayValue: '$2.80 USD',
+ displayValue: '$2.80',
+ suffix: 'USD',
+ nativeCurrency: 'ETH',
},
},
{
props: {
value: '0x1193461d01595930',
currency: 'ETH',
+ nativeCurrency: 'ETH',
numberOfDecimals: 3,
},
result: {
- displayValue: '1.266 ETH',
+ displayValue: '1.266',
+ suffix: 'ETH',
+ nativeCurrency: 'ETH',
},
},
{
props: {
value: '0x1193461d01595930',
currency: 'ETH',
+ nativeCurrency: 'ETH',
numberOfDecimals: 3,
hideLabel: true,
},
result: {
+ nativeCurrency: 'ETH',
displayValue: '1.266',
+ suffix: undefined,
},
},
{
props: {
value: '0x3b9aca00',
currency: 'ETH',
+ nativeCurrency: 'ETH',
denomination: 'GWEI',
hideLabel: true,
},
result: {
+ nativeCurrency: 'ETH',
displayValue: '1',
+ suffix: undefined,
},
},
{
props: {
value: '0x3b9aca00',
currency: 'ETH',
+ nativeCurrency: 'ETH',
denomination: 'WEI',
hideLabel: true,
},
result: {
+ nativeCurrency: 'ETH',
displayValue: '1000000000',
+ suffix: undefined,
},
},
{
props: {
value: '0x3b9aca00',
currency: 'ETH',
+ nativeCurrency: 'ETH',
numberOfDecimals: 100,
hideLabel: true,
},
result: {
+ nativeCurrency: 'ETH',
displayValue: '1e-9',
+ suffix: undefined,
},
},
]
diff --git a/ui/app/components/currency-input/currency-input.component.js b/ui/app/components/currency-input/currency-input.component.js
index 54cd0e1ac..0761a75c5 100644
--- a/ui/app/components/currency-input/currency-input.component.js
+++ b/ui/app/components/currency-input/currency-input.component.js
@@ -14,6 +14,7 @@ export default class CurrencyInput extends PureComponent {
static propTypes = {
conversionRate: PropTypes.number,
currentCurrency: PropTypes.string,
+ nativeCurrency: PropTypes.string,
onChange: PropTypes.func,
onBlur: PropTypes.func,
suffix: PropTypes.string,
@@ -77,13 +78,13 @@ export default class CurrencyInput extends PureComponent {
}
renderConversionComponent () {
- const { useFiat, currentCurrency } = this.props
+ const { useFiat, currentCurrency, nativeCurrency } = this.props
const { hexValue } = this.state
let currency, numberOfDecimals
if (useFiat) {
// Display ETH
- currency = ETH
+ currency = nativeCurrency || ETH
numberOfDecimals = 6
} else {
// Display Fiat
diff --git a/ui/app/components/currency-input/currency-input.container.js b/ui/app/components/currency-input/currency-input.container.js
index 18e5533de..1d1ed7b41 100644
--- a/ui/app/components/currency-input/currency-input.container.js
+++ b/ui/app/components/currency-input/currency-input.container.js
@@ -3,18 +3,19 @@ import CurrencyInput from './currency-input.component'
import { ETH } from '../../constants/common'
const mapStateToProps = state => {
- const { metamask: { currentCurrency, conversionRate } } = state
+ const { metamask: { nativeCurrency, currentCurrency, conversionRate } } = state
return {
+ nativeCurrency,
currentCurrency,
conversionRate,
}
}
const mergeProps = (stateProps, dispatchProps, ownProps) => {
- const { currentCurrency } = stateProps
+ const { nativeCurrency, currentCurrency } = stateProps
const { useFiat } = ownProps
- const suffix = useFiat ? currentCurrency.toUpperCase() : ETH
+ const suffix = useFiat ? currentCurrency.toUpperCase() : nativeCurrency || ETH
return {
...stateProps,
diff --git a/ui/app/components/currency-input/tests/currency-input.component.test.js b/ui/app/components/currency-input/tests/currency-input.component.test.js
index 8de0ef863..a33889f94 100644
--- a/ui/app/components/currency-input/tests/currency-input.component.test.js
+++ b/ui/app/components/currency-input/tests/currency-input.component.test.js
@@ -22,6 +22,7 @@ describe('CurrencyInput Component', () => {
it('should render properly with a suffix', () => {
const mockStore = {
metamask: {
+ nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
},
@@ -32,6 +33,7 @@ describe('CurrencyInput Component', () => {
<Provider store={store}>
<CurrencyInput
suffix="ETH"
+ nativeCurrency="ETH"
/>
</Provider>
)
@@ -45,6 +47,7 @@ describe('CurrencyInput Component', () => {
it('should render properly with an ETH value', () => {
const mockStore = {
metamask: {
+ nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
},
@@ -56,6 +59,7 @@ describe('CurrencyInput Component', () => {
<CurrencyInput
value="de0b6b3a7640000"
suffix="ETH"
+ nativeCurrency="ETH"
currentCurrency="usd"
conversionRate={231.06}
/>
@@ -69,12 +73,13 @@ describe('CurrencyInput Component', () => {
assert.equal(wrapper.find('.unit-input__suffix').length, 1)
assert.equal(wrapper.find('.unit-input__suffix').text(), 'ETH')
assert.equal(wrapper.find('.unit-input__input').props().value, '1')
- assert.equal(wrapper.find('.currency-display-component').text(), '$231.06 USD')
+ assert.equal(wrapper.find('.currency-display-component').text(), '$231.06USD')
})
it('should render properly with a fiat value', () => {
const mockStore = {
metamask: {
+ nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
},
@@ -87,6 +92,7 @@ describe('CurrencyInput Component', () => {
value="f602f2234d0ea"
suffix="USD"
useFiat
+ nativeCurrency="ETH"
currentCurrency="usd"
conversionRate={231.06}
/>
@@ -100,7 +106,7 @@ describe('CurrencyInput Component', () => {
assert.equal(wrapper.find('.unit-input__suffix').length, 1)
assert.equal(wrapper.find('.unit-input__suffix').text(), 'USD')
assert.equal(wrapper.find('.unit-input__input').props().value, '1')
- assert.equal(wrapper.find('.currency-display-component').text(), '0.004328 ETH')
+ assert.equal(wrapper.find('.currency-display-component').text(), '0.004328ETH')
})
})
@@ -116,6 +122,7 @@ describe('CurrencyInput Component', () => {
it('should call onChange and onBlur on input changes with the hex value for ETH', () => {
const mockStore = {
metamask: {
+ nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
},
@@ -127,6 +134,7 @@ describe('CurrencyInput Component', () => {
onChange={handleChangeSpy}
onBlur={handleBlurSpy}
suffix="ETH"
+ nativeCurrency="ETH"
currentCurrency="usd"
conversionRate={231.06}
/>
@@ -140,14 +148,14 @@ describe('CurrencyInput Component', () => {
const currencyInputInstance = wrapper.find(CurrencyInput).at(0).instance()
assert.equal(currencyInputInstance.state.decimalValue, 0)
assert.equal(currencyInputInstance.state.hexValue, undefined)
- assert.equal(wrapper.find('.currency-display-component').text(), '$0.00 USD')
+ assert.equal(wrapper.find('.currency-display-component').text(), '$0.00USD')
const input = wrapper.find('input')
assert.equal(input.props().value, 0)
input.simulate('change', { target: { value: 1 } })
assert.equal(handleChangeSpy.callCount, 1)
assert.ok(handleChangeSpy.calledWith('de0b6b3a7640000'))
- assert.equal(wrapper.find('.currency-display-component').text(), '$231.06 USD')
+ assert.equal(wrapper.find('.currency-display-component').text(), '$231.06USD')
assert.equal(currencyInputInstance.state.decimalValue, 1)
assert.equal(currencyInputInstance.state.hexValue, 'de0b6b3a7640000')
@@ -160,6 +168,7 @@ describe('CurrencyInput Component', () => {
it('should call onChange and onBlur on input changes with the hex value for fiat', () => {
const mockStore = {
metamask: {
+ nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
},
@@ -171,6 +180,7 @@ describe('CurrencyInput Component', () => {
onChange={handleChangeSpy}
onBlur={handleBlurSpy}
suffix="USD"
+ nativeCurrency="ETH"
currentCurrency="usd"
conversionRate={231.06}
useFiat
@@ -185,14 +195,14 @@ describe('CurrencyInput Component', () => {
const currencyInputInstance = wrapper.find(CurrencyInput).at(0).instance()
assert.equal(currencyInputInstance.state.decimalValue, 0)
assert.equal(currencyInputInstance.state.hexValue, undefined)
- assert.equal(wrapper.find('.currency-display-component').text(), '0 ETH')
+ assert.equal(wrapper.find('.currency-display-component').text(), '0ETH')
const input = wrapper.find('input')
assert.equal(input.props().value, 0)
input.simulate('change', { target: { value: 1 } })
assert.equal(handleChangeSpy.callCount, 1)
assert.ok(handleChangeSpy.calledWith('f602f2234d0ea'))
- assert.equal(wrapper.find('.currency-display-component').text(), '0.004328 ETH')
+ assert.equal(wrapper.find('.currency-display-component').text(), '0.004328ETH')
assert.equal(currencyInputInstance.state.decimalValue, 1)
assert.equal(currencyInputInstance.state.hexValue, 'f602f2234d0ea')
@@ -205,6 +215,7 @@ describe('CurrencyInput Component', () => {
it('should change the state and pass in a new decimalValue when props.value changes', () => {
const mockStore = {
metamask: {
+ nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
},
@@ -216,6 +227,7 @@ describe('CurrencyInput Component', () => {
onChange={handleChangeSpy}
onBlur={handleBlurSpy}
suffix="USD"
+ nativeCurrency="ETH"
currentCurrency="usd"
conversionRate={231.06}
useFiat
diff --git a/ui/app/components/currency-input/tests/currency-input.container.test.js b/ui/app/components/currency-input/tests/currency-input.container.test.js
index e77945e4d..5d72958e6 100644
--- a/ui/app/components/currency-input/tests/currency-input.container.test.js
+++ b/ui/app/components/currency-input/tests/currency-input.container.test.js
@@ -20,12 +20,14 @@ describe('CurrencyInput container', () => {
metamask: {
conversionRate: 280.45,
currentCurrency: 'usd',
+ nativeCurrency: 'ETH',
},
}
assert.deepEqual(mapStateToProps(mockState), {
conversionRate: 280.45,
currentCurrency: 'usd',
+ nativeCurrency: 'ETH',
})
})
})
@@ -35,12 +37,14 @@ describe('CurrencyInput container', () => {
const mockStateProps = {
conversionRate: 280.45,
currentCurrency: 'usd',
+ nativeCurrency: 'ETH',
}
const mockDispatchProps = {}
assert.deepEqual(mergeProps(mockStateProps, mockDispatchProps, { useFiat: true }), {
conversionRate: 280.45,
currentCurrency: 'usd',
+ nativeCurrency: 'ETH',
useFiat: true,
suffix: 'USD',
})
@@ -48,6 +52,7 @@ describe('CurrencyInput container', () => {
assert.deepEqual(mergeProps(mockStateProps, mockDispatchProps, {}), {
conversionRate: 280.45,
currentCurrency: 'usd',
+ nativeCurrency: 'ETH',
suffix: 'ETH',
})
})
diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js
index b497f5c09..e6b3e0c0c 100644
--- a/ui/app/components/dropdowns/components/account-dropdowns.js
+++ b/ui/app/components/dropdowns/components/account-dropdowns.js
@@ -6,7 +6,7 @@ const genAccountLink = require('../../../../lib/account-link.js')
const connect = require('react-redux').connect
const Dropdown = require('./dropdown').Dropdown
const DropdownMenuItem = require('./dropdown').DropdownMenuItem
-const Identicon = require('../../identicon')
+import Identicon from '../../identicon'
const { checksumAddress } = require('../../../util')
const copyToClipboard = require('copy-to-clipboard')
const { formatBalance } = require('../../../util')
@@ -26,14 +26,14 @@ class AccountDropdowns extends Component {
}
renderAccounts () {
- const { identities, accounts, selected, menuItemStyles, actions, keyrings } = this.props
+ const { identities, accounts, selected, menuItemStyles, actions, keyrings, ticker } = this.props
return Object.keys(identities).map((key, index) => {
const identity = identities[key]
const isSelected = identity.address === selected
const balanceValue = accounts[key].balance
- const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...'
+ const formattedBalance = balanceValue ? formatBalance(balanceValue, 6, true, ticker) : '...'
const simpleAddress = identity.address.substring(2).toLowerCase()
const keyring = keyrings.find((kr) => {
@@ -421,6 +421,7 @@ AccountDropdowns.propTypes = {
network: PropTypes.number,
// actions.showExportPrivateKeyModal: ,
style: PropTypes.object,
+ ticker: PropTypes.string,
enableAccountsSelector: PropTypes.bool,
enableAccountOption: PropTypes.bool,
enableAccountOptions: PropTypes.bool,
@@ -458,6 +459,7 @@ const mapDispatchToProps = (dispatch) => {
function mapStateToProps (state) {
return {
+ ticker: state.metamask.ticker,
keyrings: state.metamask.keyrings,
sidebarOpen: state.appState.sidebar.isOpen,
}
diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js
index b252b25d9..d4cc695a6 100644
--- a/ui/app/components/dropdowns/network-dropdown.js
+++ b/ui/app/components/dropdowns/network-dropdown.js
@@ -24,8 +24,9 @@ const notToggleElementClassnames = [
function mapStateToProps (state) {
return {
provider: state.metamask.provider,
- frequentRpcList: state.metamask.frequentRpcList || [],
+ frequentRpcListDetail: state.metamask.frequentRpcListDetail || [],
networkDropdownOpen: state.appState.networkDropdownOpen,
+ network: state.metamask.network,
}
}
@@ -40,8 +41,8 @@ function mapDispatchToProps (dispatch) {
setDefaultRpcTarget: type => {
dispatch(actions.setDefaultRpcTarget(type))
},
- setRpcTarget: (target) => {
- dispatch(actions.setRpcTarget(target))
+ setRpcTarget: (target, network, ticker, nickname) => {
+ dispatch(actions.setRpcTarget(target, network, ticker, nickname))
},
delRpcTarget: (target) => {
dispatch(actions.delRpcTarget(target))
@@ -71,7 +72,7 @@ module.exports = compose(
NetworkDropdown.prototype.render = function () {
const props = this.props
const { provider: { type: providerType, rpcTarget: activeNetwork } } = props
- const rpcList = props.frequentRpcList
+ const rpcListDetail = props.frequentRpcListDetail
const isOpen = this.props.networkDropdownOpen
const dropdownMenuItemStyle = {
fontSize: '16px',
@@ -225,7 +226,7 @@ NetworkDropdown.prototype.render = function () {
),
this.renderCustomOption(props.provider),
- this.renderCommonRpc(rpcList, props.provider),
+ this.renderCommonRpc(rpcListDetail, props.provider),
h(
DropdownMenuItem,
@@ -267,28 +268,33 @@ NetworkDropdown.prototype.getNetworkName = function () {
} else if (providerName === 'rinkeby') {
name = this.context.t('rinkeby')
} else {
- name = this.context.t('unknownNetwork')
+ name = provider.nickname || this.context.t('unknownNetwork')
}
return name
}
-NetworkDropdown.prototype.renderCommonRpc = function (rpcList, provider) {
+NetworkDropdown.prototype.renderCommonRpc = function (rpcListDetail, provider) {
const props = this.props
- const reversedRpcList = rpcList.slice().reverse()
+ const reversedRpcListDetail = rpcListDetail.slice().reverse()
+ const network = props.network
- return reversedRpcList.map((rpc) => {
+ return reversedRpcListDetail.map((entry) => {
+ const rpc = entry.rpcUrl
+ const ticker = entry.ticker || 'ETH'
+ const nickname = entry.nickname || ''
const currentRpcTarget = provider.type === 'rpc' && rpc === provider.rpcTarget
if ((rpc === 'http://localhost:8545') || currentRpcTarget) {
return null
} else {
+ const chainId = entry.chainId || network
return h(
DropdownMenuItem,
{
key: `common${rpc}`,
closeMenu: () => this.props.hideNetworkDropdown(),
- onClick: () => props.setRpcTarget(rpc),
+ onClick: () => props.setRpcTarget(rpc, chainId, ticker, nickname),
style: {
fontSize: '16px',
lineHeight: '20px',
@@ -302,7 +308,7 @@ NetworkDropdown.prototype.renderCommonRpc = function (rpcList, provider) {
style: {
color: currentRpcTarget ? '#ffffff' : '#9b9b9b',
},
- }, rpc),
+ }, nickname || rpc),
h('i.fa.fa-times.delete',
{
onClick: (e) => {
@@ -317,8 +323,9 @@ NetworkDropdown.prototype.renderCommonRpc = function (rpcList, provider) {
}
NetworkDropdown.prototype.renderCustomOption = function (provider) {
- const { rpcTarget, type } = provider
+ const { rpcTarget, type, ticker, nickname } = provider
const props = this.props
+ const network = props.network
if (type !== 'rpc') return null
@@ -332,7 +339,7 @@ NetworkDropdown.prototype.renderCustomOption = function (provider) {
DropdownMenuItem,
{
key: rpcTarget,
- onClick: () => props.setRpcTarget(rpcTarget),
+ onClick: () => props.setRpcTarget(rpcTarget, network, ticker, nickname),
closeMenu: () => this.props.hideNetworkDropdown(),
style: {
fontSize: '16px',
@@ -347,7 +354,7 @@ NetworkDropdown.prototype.renderCustomOption = function (provider) {
style: {
color: '#ffffff',
},
- }, rpcTarget),
+ }, nickname || rpcTarget),
]
)
}
diff --git a/ui/app/components/dropdowns/tests/network-dropdown.test.js b/ui/app/components/dropdowns/tests/network-dropdown.test.js
index 699b54605..88ad56851 100644
--- a/ui/app/components/dropdowns/tests/network-dropdown.test.js
+++ b/ui/app/components/dropdowns/tests/network-dropdown.test.js
@@ -45,8 +45,8 @@ describe('Network Dropdown', () => {
provider: {
'type': 'test',
},
- frequentRpcList: [
- 'http://localhost:7545',
+ frequentRpcListDetail: [
+ { rpcUrl: 'http://localhost:7545' },
],
},
appState: {
diff --git a/ui/app/components/eth-balance.js b/ui/app/components/eth-balance.js
index c3d084bdc..2f6395a2d 100644
--- a/ui/app/components/eth-balance.js
+++ b/ui/app/components/eth-balance.js
@@ -1,5 +1,6 @@
const { Component } = require('react')
const h = require('react-hyperscript')
+const connect = require('react-redux').connect
const { inherits } = require('util')
const {
formatBalance,
@@ -8,7 +9,12 @@ const {
const Tooltip = require('./tooltip.js')
const FiatValue = require('./fiat-value.js')
-module.exports = EthBalanceComponent
+module.exports = connect(mapStateToProps)(EthBalanceComponent)
+function mapStateToProps (state) {
+ return {
+ ticker: state.metamask.ticker,
+ }
+}
inherits(EthBalanceComponent, Component)
function EthBalanceComponent () {
@@ -17,9 +23,9 @@ function EthBalanceComponent () {
EthBalanceComponent.prototype.render = function () {
const props = this.props
- const { value, style, width, needsParse = true } = props
+ const { ticker, value, style, width, needsParse = true } = props
- const formattedValue = value ? formatBalance(value, 6, needsParse) : '...'
+ const formattedValue = value ? formatBalance(value, 6, needsParse, ticker) : '...'
return (
diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js
deleted file mode 100644
index 7bd921892..000000000
--- a/ui/app/components/identicon.js
+++ /dev/null
@@ -1,124 +0,0 @@
-const Component = require('react').Component
-const h = require('react-hyperscript')
-const inherits = require('util').inherits
-const connect = require('react-redux').connect
-const isNode = require('detect-node')
-const findDOMNode = require('react-dom').findDOMNode
-const jazzicon = require('jazzicon')
-const iconFactoryGen = require('../../lib/icon-factory')
-const iconFactory = iconFactoryGen(jazzicon)
-const { toDataUrl } = require('../../lib/blockies')
-
-module.exports = connect(mapStateToProps)(IdenticonComponent)
-
-inherits(IdenticonComponent, Component)
-function IdenticonComponent () {
- Component.call(this)
-
- this.defaultDiameter = 46
-}
-
-function mapStateToProps (state) {
- return {
- useBlockie: state.metamask.useBlockie,
- }
-}
-
-IdenticonComponent.prototype.render = function () {
- var props = this.props
- const { className = '', address, image } = props
- var diameter = props.diameter || this.defaultDiameter
- const style = {
- height: diameter,
- width: diameter,
- borderRadius: diameter / 2,
- }
- if (image) {
- return h('img', {
- className: `${className} identicon`,
- src: image,
- style: {
- ...style,
- },
- })
- } else if (address) {
- return h('div', {
- className: `${className} identicon`,
- key: 'identicon-' + address,
- style: {
- display: 'flex',
- flexShrink: 0,
- alignItems: 'center',
- justifyContent: 'center',
- ...style,
- overflow: 'hidden',
- },
- })
- } else {
- return h('img.balance-icon', {
- className,
- src: './images/eth_logo.svg',
- style: {
- ...style,
- },
- })
- }
-}
-
-IdenticonComponent.prototype.componentDidMount = function () {
- var props = this.props
- const { address, useBlockie } = props
-
- if (!address) return
-
- if (!isNode) {
- // eslint-disable-next-line react/no-find-dom-node
- var container = findDOMNode(this)
-
- const diameter = props.diameter || this.defaultDiameter
-
- if (useBlockie) {
- _generateBlockie(container, address, diameter)
- } else {
- _generateJazzicon(container, address, diameter)
- }
- }
-}
-
-IdenticonComponent.prototype.componentDidUpdate = function () {
- var props = this.props
- const { address, useBlockie } = props
-
- if (!address) return
-
- if (!isNode) {
- // eslint-disable-next-line react/no-find-dom-node
- var container = findDOMNode(this)
-
- var children = container.children
- for (var i = 0; i < children.length; i++) {
- container.removeChild(children[i])
- }
-
- const diameter = props.diameter || this.defaultDiameter
-
- if (useBlockie) {
- _generateBlockie(container, address, diameter)
- } else {
- _generateJazzicon(container, address, diameter)
- }
- }
-}
-
-function _generateBlockie (container, address, diameter) {
- const img = new Image()
- img.src = toDataUrl(address)
- img.height = diameter
- img.width = diameter
- container.appendChild(img)
-}
-
-function _generateJazzicon (container, address, diameter) {
- const img = iconFactory.iconForAddress(address, diameter)
- container.appendChild(img)
-}
diff --git a/ui/app/components/identicon/identicon.component.js b/ui/app/components/identicon/identicon.component.js
new file mode 100644
index 000000000..b892e5ae5
--- /dev/null
+++ b/ui/app/components/identicon/identicon.component.js
@@ -0,0 +1,99 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import classnames from 'classnames'
+import { toDataUrl } from '../../../lib/blockies'
+import contractMap from 'eth-contract-metadata'
+import { checksumAddress } from '../../../app/util'
+import Jazzicon from '../jazzicon'
+
+const getStyles = diameter => (
+ {
+ height: diameter,
+ width: diameter,
+ borderRadius: diameter / 2,
+ }
+)
+
+export default class Identicon extends PureComponent {
+ static propTypes = {
+ address: PropTypes.string,
+ className: PropTypes.string,
+ diameter: PropTypes.number,
+ image: PropTypes.string,
+ useBlockie: PropTypes.bool,
+ }
+
+ static defaultProps = {
+ diameter: 46,
+ }
+
+ renderImage () {
+ const { className, diameter, image } = this.props
+
+ return (
+ <img
+ className={classnames('identicon', className)}
+ src={image}
+ style={getStyles(diameter)}
+ />
+ )
+ }
+
+ renderJazzicon () {
+ const { address, className, diameter } = this.props
+
+ return (
+ <Jazzicon
+ address={address}
+ diameter={diameter}
+ className={classnames('identicon', className)}
+ style={getStyles(diameter)}
+ />
+ )
+ }
+
+ renderBlockie () {
+ const { address, className, diameter } = this.props
+
+ return (
+ <div
+ className={classnames('identicon', className)}
+ style={getStyles(diameter)}
+ >
+ <img
+ src={toDataUrl(address)}
+ height={diameter}
+ width={diameter}
+ />
+ </div>
+ )
+ }
+
+ render () {
+ const { className, address, image, diameter, useBlockie } = this.props
+
+ if (image) {
+ return this.renderImage()
+ }
+
+ if (address) {
+ const checksummedAddress = checksumAddress(address)
+
+ if (contractMap[checksummedAddress] && contractMap[checksummedAddress].logo) {
+ return this.renderJazzicon()
+ }
+
+ return useBlockie
+ ? this.renderBlockie()
+ : this.renderJazzicon()
+ }
+
+ return (
+ <img
+ className={classnames('balance-icon', className)}
+ src="./images/eth_logo.svg"
+ style={getStyles(diameter)}
+ />
+ )
+ }
+}
diff --git a/ui/app/components/identicon/identicon.container.js b/ui/app/components/identicon/identicon.container.js
new file mode 100644
index 000000000..bc49bc18e
--- /dev/null
+++ b/ui/app/components/identicon/identicon.container.js
@@ -0,0 +1,12 @@
+import { connect } from 'react-redux'
+import Identicon from './identicon.component'
+
+const mapStateToProps = state => {
+ const { metamask: { useBlockie } } = state
+
+ return {
+ useBlockie,
+ }
+}
+
+export default connect(mapStateToProps)(Identicon)
diff --git a/ui/app/components/identicon/index.js b/ui/app/components/identicon/index.js
new file mode 100644
index 000000000..799c886f2
--- /dev/null
+++ b/ui/app/components/identicon/index.js
@@ -0,0 +1 @@
+export { default } from './identicon.container'
diff --git a/ui/app/components/identicon/index.scss b/ui/app/components/identicon/index.scss
new file mode 100644
index 000000000..657afc48f
--- /dev/null
+++ b/ui/app/components/identicon/index.scss
@@ -0,0 +1,7 @@
+.identicon {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+}
diff --git a/test/unit/ui/app/components/identicon.spec.js b/ui/app/components/identicon/tests/identicon.component.test.js
index a2f8d8246..2944818f5 100644
--- a/test/unit/ui/app/components/identicon.spec.js
+++ b/ui/app/components/identicon/tests/identicon.component.test.js
@@ -3,11 +3,9 @@ import assert from 'assert'
import thunk from 'redux-thunk'
import configureMockStore from 'redux-mock-store'
import { mount } from 'enzyme'
+import Identicon from '../identicon.component'
-import IdenticonComponent from '../../../../../ui/app/components/identicon'
-
-describe('Identicon Component', () => {
-
+describe('Identicon', () => {
const state = {
metamask: {
useBlockie: false,
@@ -19,18 +17,35 @@ describe('Identicon Component', () => {
const store = mockStore(state)
it('renders default eth_logo identicon with no props', () => {
- const wrapper = mount(<IdenticonComponent store={store}/>)
+ const wrapper = mount(
+ <Identicon store={store}/>
+ )
+
assert.equal(wrapper.find('img.balance-icon').prop('src'), './images/eth_logo.svg')
})
it('renders custom image and add className props', () => {
- const wrapper = mount(<IdenticonComponent store={store} className={'test-image'} image={'test-image'} />)
- assert.equal(wrapper.find('img.test-image').prop('className'), 'test-image identicon')
+ const wrapper = mount(
+ <Identicon
+ store={store}
+ className="test-image"
+ image="test-image"
+ />
+ )
+
+ assert.equal(wrapper.find('img.test-image').prop('className'), 'identicon test-image')
assert.equal(wrapper.find('img.test-image').prop('src'), 'test-image')
})
it('renders div with address prop', () => {
- const wrapper = mount(<IdenticonComponent store={store} className={'test-address'} address={'0xTest'} />)
- assert.equal(wrapper.find('div.test-address').prop('className'), 'test-address identicon')
+ const wrapper = mount(
+ <Identicon
+ store={store}
+ className="test-address"
+ address="0xTest"
+ />
+ )
+
+ assert.equal(wrapper.find('div.test-address').prop('className'), 'identicon test-address')
})
})
diff --git a/ui/app/components/index.scss b/ui/app/components/index.scss
index beffdb221..72de6cb93 100644
--- a/ui/app/components/index.scss
+++ b/ui/app/components/index.scss
@@ -16,6 +16,8 @@
@import './export-text-container/index';
+@import './identicon/index';
+
@import './info-box/index';
@import './menu-bar/index';
diff --git a/ui/app/components/jazzicon/index.js b/ui/app/components/jazzicon/index.js
new file mode 100644
index 000000000..bea900ab9
--- /dev/null
+++ b/ui/app/components/jazzicon/index.js
@@ -0,0 +1 @@
+export { default } from './jazzicon.component'
diff --git a/ui/app/components/jazzicon/jazzicon.component.js b/ui/app/components/jazzicon/jazzicon.component.js
new file mode 100644
index 000000000..fcb1c59b1
--- /dev/null
+++ b/ui/app/components/jazzicon/jazzicon.component.js
@@ -0,0 +1,69 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import isNode from 'detect-node'
+import { findDOMNode } from 'react-dom'
+import jazzicon from 'jazzicon'
+import iconFactoryGenerator from '../../../lib/icon-factory'
+const iconFactory = iconFactoryGenerator(jazzicon)
+
+/**
+ * Wrapper around the jazzicon library to return a React component, as the library returns an
+ * HTMLDivElement which needs to be appended.
+ */
+export default class Jazzicon extends PureComponent {
+ static propTypes = {
+ address: PropTypes.string.isRequired,
+ className: PropTypes.string,
+ diameter: PropTypes.number,
+ style: PropTypes.object,
+ }
+
+ static defaultProps = {
+ diameter: 46,
+ }
+
+ componentDidMount () {
+ if (!isNode) {
+ this.appendJazzicon()
+ }
+ }
+
+ componentDidUpdate (prevProps) {
+ const { address: prevAddress } = prevProps
+ const { address } = this.props
+
+ if (!isNode && address !== prevAddress) {
+ this.removeExistingChildren()
+ this.appendJazzicon()
+ }
+ }
+
+ removeExistingChildren () {
+ // eslint-disable-next-line react/no-find-dom-node
+ const container = findDOMNode(this)
+ const { children } = container
+
+ for (let i = 0; i < children.length; i++) {
+ container.removeChild(children[i])
+ }
+ }
+
+ appendJazzicon () {
+ // eslint-disable-next-line react/no-find-dom-node
+ const container = findDOMNode(this)
+ const { address, diameter } = this.props
+ const image = iconFactory.iconForAddress(address, diameter)
+ container.appendChild(image)
+ }
+
+ render () {
+ const { className, style } = this.props
+
+ return (
+ <div
+ className={className}
+ style={style}
+ />
+ )
+ }
+}
diff --git a/ui/app/components/modals/account-modal-container.js b/ui/app/components/modals/account-modal-container.js
index aa0593df8..2a6c655e1 100644
--- a/ui/app/components/modals/account-modal-container.js
+++ b/ui/app/components/modals/account-modal-container.js
@@ -5,7 +5,7 @@ const inherits = require('util').inherits
const connect = require('react-redux').connect
const actions = require('../../actions')
const { getSelectedIdentity } = require('../../selectors')
-const Identicon = require('../identicon')
+import Identicon from '../identicon'
function mapStateToProps (state, ownProps) {
return {
diff --git a/ui/app/components/modals/hide-token-confirmation-modal.js b/ui/app/components/modals/hide-token-confirmation-modal.js
index fb38516d3..43f3009a5 100644
--- a/ui/app/components/modals/hide-token-confirmation-modal.js
+++ b/ui/app/components/modals/hide-token-confirmation-modal.js
@@ -4,7 +4,7 @@ const h = require('react-hyperscript')
const inherits = require('util').inherits
const connect = require('react-redux').connect
const actions = require('../../actions')
-const Identicon = require('../identicon')
+import Identicon from '../identicon'
function mapStateToProps (state) {
return {
diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js
index 15ca9deaa..338229a28 100644
--- a/ui/app/components/modals/modal.js
+++ b/ui/app/components/modals/modal.js
@@ -27,7 +27,6 @@ import TransactionConfirmed from './transaction-confirmed'
import ConfirmCustomizeGasModal from './customize-gas'
import CancelTransaction from './cancel-transaction'
import WelcomeBeta from './welcome-beta'
-import TransactionDetails from './transaction-details'
import RejectTransactions from './reject-transactions'
const modalContainerBaseStyle = {
@@ -366,19 +365,6 @@ const MODALS = {
},
},
- TRANSACTION_DETAILS: {
- contents: h(TransactionDetails),
- mobileModalStyle: {
- ...modalContainerMobileStyle,
- },
- laptopModalStyle: {
- ...modalContainerLaptopStyle,
- },
- contentStyle: {
- borderRadius: '8px',
- },
- },
-
REJECT_TRANSACTIONS: {
contents: h(RejectTransactions),
mobileModalStyle: {
diff --git a/ui/app/components/modals/transaction-details/index.js b/ui/app/components/modals/transaction-details/index.js
deleted file mode 100644
index 1fc42c662..000000000
--- a/ui/app/components/modals/transaction-details/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './transaction-details.container'
diff --git a/ui/app/components/modals/transaction-details/transaction-details.component.js b/ui/app/components/modals/transaction-details/transaction-details.component.js
deleted file mode 100644
index f2fec3409..000000000
--- a/ui/app/components/modals/transaction-details/transaction-details.component.js
+++ /dev/null
@@ -1,54 +0,0 @@
-import React, { PureComponent } from 'react'
-import PropTypes from 'prop-types'
-import Modal from '../../modal'
-import TransactionListItemDetails from '../../transaction-list-item-details'
-import { hexToDecimal } from '../../../helpers/conversions.util'
-
-export default class TransactionConfirmed extends PureComponent {
- static contextTypes = {
- t: PropTypes.func,
- }
-
- static propTypes = {
- hideModal: PropTypes.func,
- transaction: PropTypes.object,
- onRetry: PropTypes.func,
- showRetry: PropTypes.bool,
- onCancel: PropTypes.func,
- showCancel: PropTypes.bool,
- }
-
- handleSubmit = () => {
- this.props.hideModal()
- }
-
- handleRetry = () => {
- const { onRetry, hideModal } = this.props
-
- Promise.resolve(onRetry()).then(() => hideModal())
- }
-
- render () {
- const { t } = this.context
- const { transaction, showRetry, onCancel, showCancel } = this.props
- const { txParams: { nonce } = {} } = transaction
- const decimalNonce = nonce && hexToDecimal(nonce)
-
- return (
- <Modal
- onSubmit={this.handleSubmit}
- onClose={this.handleSubmit}
- submitText={t('ok')}
- headerText={t('transactionWithNonce', [`#${decimalNonce}`])}
- >
- <TransactionListItemDetails
- transaction={transaction}
- onRetry={this.handleRetry}
- showRetry={showRetry}
- onCancel={() => onCancel()}
- showCancel={showCancel}
- />
- </Modal>
- )
- }
-}
diff --git a/ui/app/components/modals/transaction-details/transaction-details.container.js b/ui/app/components/modals/transaction-details/transaction-details.container.js
deleted file mode 100644
index f212920bb..000000000
--- a/ui/app/components/modals/transaction-details/transaction-details.container.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import TransactionDetails from './transaction-details.component'
-import withModalProps from '../../../higher-order-components/with-modal-props'
-
-export default withModalProps(TransactionDetails)
diff --git a/ui/app/components/network-display/network-display.component.js b/ui/app/components/network-display/network-display.component.js
index 38626af20..82f9ff9c3 100644
--- a/ui/app/components/network-display/network-display.component.js
+++ b/ui/app/components/network-display/network-display.component.js
@@ -41,7 +41,7 @@ export default class NetworkDisplay extends Component {
}
render () {
- const { network, provider: { type } } = this.props
+ const { network, provider: { type, nickname } } = this.props
const networkClass = networkToClassHash[network]
return (
@@ -61,7 +61,7 @@ export default class NetworkDisplay extends Component {
/>
}
<div className="network-display__name">
- { this.context.t(type) }
+ { type === 'rpc' && nickname ? nickname : this.context.t(type) }
</div>
</div>
)
diff --git a/ui/app/components/network.js b/ui/app/components/network.js
index 83297c4f2..611aadb7b 100644
--- a/ui/app/components/network.js
+++ b/ui/app/components/network.js
@@ -23,9 +23,10 @@ Network.prototype.render = function () {
const props = this.props
const context = this.context
const networkNumber = props.network
- let providerName
+ let providerName, providerNick
try {
providerName = props.provider.type
+ providerNick = props.provider.nickname || ''
} catch (e) {
providerName = null
}
@@ -131,7 +132,7 @@ Network.prototype.render = function () {
},
}),
- h('.network-name', context.t('privateNetwork')),
+ h('.network-name', providerNick || context.t('privateNetwork')),
h('i.fa.fa-chevron-down.fa-lg.network-caret'),
])
}
diff --git a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js
index c92867afe..7d01aaffb 100644
--- a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js
+++ b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js
@@ -136,7 +136,7 @@ export default class ConfirmTransactionBase extends Component {
if (simulationFails) {
return {
valid: true,
- errorKey: TRANSACTION_ERROR_KEY,
+ errorKey: simulationFails.errorKey ? simulationFails.errorKey : TRANSACTION_ERROR_KEY,
}
}
diff --git a/ui/app/components/pages/settings/settings-tab/index.scss b/ui/app/components/pages/settings/settings-tab/index.scss
index 3bf840c86..ef32b0e4c 100644
--- a/ui/app/components/pages/settings/settings-tab/index.scss
+++ b/ui/app/components/pages/settings/settings-tab/index.scss
@@ -5,12 +5,9 @@
color: $crimson;
}
- &__rpc-save-button {
- align-self: flex-end;
- padding: 5px;
- text-transform: uppercase;
- color: $dusty-gray;
- cursor: pointer;
+ &__advanced-link {
+ color: $curious-blue;
+ padding-left: 5px;
}
&__rpc-save-button {
@@ -19,6 +16,9 @@
text-transform: uppercase;
color: $dusty-gray;
cursor: pointer;
+ width: 25%;
+ min-width: 80px;
+ height: 33px;
}
&__button--red {
diff --git a/ui/app/components/pages/settings/settings-tab/settings-tab.component.js b/ui/app/components/pages/settings/settings-tab/settings-tab.component.js
index a9e2a723e..cd81491a8 100644
--- a/ui/app/components/pages/settings/settings-tab/settings-tab.component.js
+++ b/ui/app/components/pages/settings/settings-tab/settings-tab.component.js
@@ -55,12 +55,17 @@ export default class SettingsTab extends PureComponent {
sendHexData: PropTypes.bool,
currentCurrency: PropTypes.string,
conversionDate: PropTypes.number,
- useETHAsPrimaryCurrency: PropTypes.bool,
- setUseETHAsPrimaryCurrencyPreference: PropTypes.func,
+ nativeCurrency: PropTypes.string,
+ useNativeCurrencyAsPrimaryCurrency: PropTypes.bool,
+ setUseNativeCurrencyAsPrimaryCurrencyPreference: PropTypes.func,
}
state = {
newRpc: '',
+ chainId: '',
+ showOptions: false,
+ ticker: '',
+ nickname: '',
}
renderCurrentConversion () {
@@ -121,37 +126,98 @@ export default class SettingsTab extends PureComponent {
renderNewRpcUrl () {
const { t } = this.context
- const { newRpc } = this.state
+ const { newRpc, chainId, ticker, nickname } = this.state
return (
<div className="settings-page__content-row">
<div className="settings-page__content-item">
- <span>{ t('newRPC') }</span>
+ <span>{ t('newNetwork') }</span>
</div>
<div className="settings-page__content-item">
<div className="settings-page__content-item-col">
<TextField
type="text"
id="new-rpc"
- placeholder={t('newRPC')}
+ placeholder={t('rpcURL')}
value={newRpc}
onChange={e => this.setState({ newRpc: e.target.value })}
onKeyPress={e => {
if (e.key === 'Enter') {
- this.validateRpc(newRpc)
+ this.validateRpc(newRpc, chainId, ticker, nickname)
}
}}
fullWidth
- margin="none"
+ margin="dense"
/>
- <div
- className="settings-tab__rpc-save-button"
- onClick={e => {
- e.preventDefault()
- this.validateRpc(newRpc)
+ <TextField
+ type="text"
+ id="chainid"
+ placeholder={t('optionalChainId')}
+ value={chainId}
+ onChange={e => this.setState({ chainId: e.target.value })}
+ onKeyPress={e => {
+ if (e.key === 'Enter') {
+ this.validateRpc(newRpc, chainId, ticker, nickname)
+ }
}}
- >
- { t('save') }
+ style={{
+ display: this.state.showOptions ? null : 'none',
+ }}
+ fullWidth
+ margin="dense"
+ />
+ <TextField
+ type="text"
+ id="ticker"
+ placeholder={t('optionalSymbol')}
+ value={ticker}
+ onChange={e => this.setState({ ticker: e.target.value })}
+ onKeyPress={e => {
+ if (e.key === 'Enter') {
+ this.validateRpc(newRpc, chainId, ticker, nickname)
+ }
+ }}
+ style={{
+ display: this.state.showOptions ? null : 'none',
+ }}
+ fullWidth
+ margin="dense"
+ />
+ <TextField
+ type="text"
+ id="nickname"
+ placeholder={t('optionalNickname')}
+ value={nickname}
+ onChange={e => this.setState({ nickname: e.target.value })}
+ onKeyPress={e => {
+ if (e.key === 'Enter') {
+ this.validateRpc(newRpc, chainId, ticker, nickname)
+ }
+ }}
+ style={{
+ display: this.state.showOptions ? null : 'none',
+ }}
+ fullWidth
+ margin="dense"
+ />
+ <div className="flex-row flex-align-center space-between">
+ <span className="settings-tab__advanced-link"
+ onClick={e => {
+ e.preventDefault()
+ this.setState({ showOptions: !this.state.showOptions })
+ }}
+ >
+ { t(this.state.showOptions ? 'hideAdvancedOptions' : 'showAdvancedOptions') }
+ </span>
+ <button
+ className="button btn-primary settings-tab__rpc-save-button"
+ onClick={e => {
+ e.preventDefault()
+ this.validateRpc(newRpc, chainId, ticker, nickname)
+ }}
+ >
+ { t('save') }
+ </button>
</div>
</div>
</div>
@@ -159,11 +225,11 @@ export default class SettingsTab extends PureComponent {
)
}
- validateRpc (newRpc) {
+ validateRpc (newRpc, chainId, ticker = 'ETH', nickname) {
const { setRpcTarget, displayWarning } = this.props
if (validUrl.isWebUri(newRpc)) {
- setRpcTarget(newRpc)
+ setRpcTarget(newRpc, chainId, ticker, nickname)
} else {
const appendedRpc = `http://${newRpc}`
@@ -341,9 +407,13 @@ export default class SettingsTab extends PureComponent {
)
}
- renderUseEthAsPrimaryCurrency () {
+ renderUsePrimaryCurrencyOptions () {
const { t } = this.context
- const { useETHAsPrimaryCurrency, setUseETHAsPrimaryCurrencyPreference } = this.props
+ const {
+ nativeCurrency,
+ setUseNativeCurrencyAsPrimaryCurrencyPreference,
+ useNativeCurrencyAsPrimaryCurrency,
+ } = this.props
return (
<div className="settings-page__content-row">
@@ -359,23 +429,23 @@ export default class SettingsTab extends PureComponent {
<div className="settings-tab__radio-button">
<input
type="radio"
- id="eth-primary-currency"
- onChange={() => setUseETHAsPrimaryCurrencyPreference(true)}
- checked={Boolean(useETHAsPrimaryCurrency)}
+ id="native-primary-currency"
+ onChange={() => setUseNativeCurrencyAsPrimaryCurrencyPreference(true)}
+ checked={Boolean(useNativeCurrencyAsPrimaryCurrency)}
/>
<label
- htmlFor="eth-primary-currency"
+ htmlFor="native-primary-currency"
className="settings-tab__radio-label"
>
- { t('eth') }
+ { nativeCurrency }
</label>
</div>
<div className="settings-tab__radio-button">
<input
type="radio"
id="fiat-primary-currency"
- onChange={() => setUseETHAsPrimaryCurrencyPreference(false)}
- checked={!useETHAsPrimaryCurrency}
+ onChange={() => setUseNativeCurrencyAsPrimaryCurrencyPreference(false)}
+ checked={!useNativeCurrencyAsPrimaryCurrency}
/>
<label
htmlFor="fiat-primary-currency"
@@ -398,7 +468,7 @@ export default class SettingsTab extends PureComponent {
<div className="settings-page__content">
{ warning && <div className="settings-tab__error">{ warning }</div> }
{ this.renderCurrentConversion() }
- { this.renderUseEthAsPrimaryCurrency() }
+ { this.renderUsePrimaryCurrencyOptions() }
{ this.renderCurrentLocale() }
{ this.renderNewRpcUrl() }
{ this.renderStateLogs() }
diff --git a/ui/app/components/pages/settings/settings-tab/settings-tab.container.js b/ui/app/components/pages/settings/settings-tab/settings-tab.container.js
index de30f309c..f4110207e 100644
--- a/ui/app/components/pages/settings/settings-tab/settings-tab.container.js
+++ b/ui/app/components/pages/settings/settings-tab/settings-tab.container.js
@@ -11,7 +11,7 @@ import {
updateCurrentLocale,
setFeatureFlag,
showModal,
- setUseETHAsPrimaryCurrencyPreference,
+ setUseNativeCurrencyAsPrimaryCurrencyPreference,
} from '../../../../actions'
import { preferencesSelector } from '../../../../selectors'
@@ -20,13 +20,14 @@ const mapStateToProps = state => {
const {
currentCurrency,
conversionDate,
+ nativeCurrency,
useBlockie,
featureFlags: { sendHexData } = {},
provider = {},
isMascara,
currentLocale,
} = metamask
- const { useETHAsPrimaryCurrency } = preferencesSelector(state)
+ const { useNativeCurrencyAsPrimaryCurrency } = preferencesSelector(state)
return {
warning,
@@ -34,17 +35,18 @@ const mapStateToProps = state => {
currentLocale,
currentCurrency,
conversionDate,
+ nativeCurrency,
useBlockie,
sendHexData,
provider,
- useETHAsPrimaryCurrency,
+ useNativeCurrencyAsPrimaryCurrency,
}
}
const mapDispatchToProps = dispatch => {
return {
setCurrentCurrency: currency => dispatch(setCurrentCurrency(currency)),
- setRpcTarget: newRpc => dispatch(setRpcTarget(newRpc)),
+ setRpcTarget: (newRpc, chainId, ticker, nickname) => dispatch(setRpcTarget(newRpc, chainId, ticker, nickname)),
displayWarning: warning => dispatch(displayWarning(warning)),
revealSeedConfirmation: () => dispatch(revealSeedConfirmation()),
setUseBlockie: value => dispatch(setUseBlockie(value)),
@@ -54,8 +56,8 @@ const mapDispatchToProps = dispatch => {
},
setHexDataFeatureFlag: shouldShow => dispatch(setFeatureFlag('sendHexData', shouldShow)),
showResetAccountConfirmationModal: () => dispatch(showModal({ name: 'CONFIRM_RESET_ACCOUNT' })),
- setUseETHAsPrimaryCurrencyPreference: value => {
- return dispatch(setUseETHAsPrimaryCurrencyPreference(value))
+ setUseNativeCurrencyAsPrimaryCurrencyPreference: value => {
+ return dispatch(setUseNativeCurrencyAsPrimaryCurrencyPreference(value))
},
}
}
diff --git a/ui/app/components/send/account-list-item/account-list-item.container.js b/ui/app/components/send/account-list-item/account-list-item.container.js
index 4b4519288..f8e73d923 100644
--- a/ui/app/components/send/account-list-item/account-list-item.container.js
+++ b/ui/app/components/send/account-list-item/account-list-item.container.js
@@ -2,6 +2,7 @@ import { connect } from 'react-redux'
import {
getConversionRate,
getCurrentCurrency,
+ getNativeCurrency,
} from '../send.selectors.js'
import AccountListItem from './account-list-item.component'
@@ -11,5 +12,6 @@ function mapStateToProps (state) {
return {
conversionRate: getConversionRate(state),
currentCurrency: getCurrentCurrency(state),
+ nativeCurrency: getNativeCurrency(state),
}
}
diff --git a/ui/app/components/send/account-list-item/tests/account-list-item-component.test.js b/ui/app/components/send/account-list-item/tests/account-list-item-component.test.js
index f88c0dbd0..6ffc0b1c6 100644
--- a/ui/app/components/send/account-list-item/tests/account-list-item-component.test.js
+++ b/ui/app/components/send/account-list-item/tests/account-list-item-component.test.js
@@ -28,6 +28,7 @@ describe('AccountListItem Component', function () {
className={'mockClassName'}
conversionRate={4}
currentCurrency={'mockCurrentyCurrency'}
+ nativeCurrency={'ETH'}
displayAddress={false}
displayBalance={false}
handleClick={propsMethodSpies.handleClick}
diff --git a/ui/app/components/send/account-list-item/tests/account-list-item-container.test.js b/ui/app/components/send/account-list-item/tests/account-list-item-container.test.js
index af0859117..7c2f5fcb2 100644
--- a/ui/app/components/send/account-list-item/tests/account-list-item-container.test.js
+++ b/ui/app/components/send/account-list-item/tests/account-list-item-container.test.js
@@ -13,6 +13,7 @@ proxyquire('../account-list-item.container.js', {
'../send.selectors.js': {
getConversionRate: (s) => `mockConversionRate:${s}`,
getCurrentCurrency: (s) => `mockCurrentCurrency:${s}`,
+ getNativeCurrency: (s) => `mockNativeCurrency:${s}`,
},
})
@@ -24,6 +25,7 @@ describe('account-list-item container', () => {
assert.deepEqual(mapStateToProps('mockState'), {
conversionRate: 'mockConversionRate:mockState',
currentCurrency: 'mockCurrentCurrency:mockState',
+ nativeCurrency: 'mockNativeCurrency:mockState',
})
})
diff --git a/ui/app/components/send/send-content/send-amount-row/tests/send-amount-row-component.test.js b/ui/app/components/send/send-content/send-amount-row/tests/send-amount-row-component.test.js
index e63db4a2d..56e80cb83 100644
--- a/ui/app/components/send/send-content/send-amount-row/tests/send-amount-row-component.test.js
+++ b/ui/app/components/send/send-content/send-amount-row/tests/send-amount-row-component.test.js
@@ -151,7 +151,6 @@ describe('SendAmountRow Component', function () {
})
it('should render a UserPreferencedTokenInput as the second child of the SendRowWrapper', () => {
- console.log('HI', wrapper.find(SendRowWrapper).childAt(1))
assert(wrapper.find(SendRowWrapper).childAt(1).is(UserPreferencedTokenInput))
})
diff --git a/ui/app/components/send/send.selectors.js b/ui/app/components/send/send.selectors.js
index 22e379693..eb22a08b7 100644
--- a/ui/app/components/send/send.selectors.js
+++ b/ui/app/components/send/send.selectors.js
@@ -19,6 +19,7 @@ const selectors = {
getCurrentNetwork,
getCurrentViewContext,
getForceGasMin,
+ getNativeCurrency,
getGasLimit,
getGasPrice,
getGasPriceFromRecentBlocks,
@@ -111,6 +112,10 @@ function getCurrentCurrency (state) {
return state.metamask.currentCurrency
}
+function getNativeCurrency (state) {
+ return state.metamask.nativeCurrency
+}
+
function getCurrentNetwork (state) {
return state.metamask.network
}
diff --git a/ui/app/components/send/send.utils.js b/ui/app/components/send/send.utils.js
index a18a9e4b3..eb1667c63 100644
--- a/ui/app/components/send/send.utils.js
+++ b/ui/app/components/send/send.utils.js
@@ -215,7 +215,9 @@ async function estimateGas ({
// if recipient has no code, gas is 21k max:
if (!selectedToken && !data) {
const code = Boolean(to) && await global.eth.getCode(to)
- if (!code || code === '0x') {
+ // Geth will return '0x', and ganache-core v2.2.1 will return '0x0'
+ const codeIsEmpty = !code || code === '0x' || code === '0x0'
+ if (codeIsEmpty) {
return SIMPLE_GAS_COST
}
} else if (selectedToken && !to) {
diff --git a/ui/app/components/send/tests/send-selectors-test-data.js b/ui/app/components/send/tests/send-selectors-test-data.js
index 8b939dadb..30a2666cf 100644
--- a/ui/app/components/send/tests/send-selectors-test-data.js
+++ b/ui/app/components/send/tests/send-selectors-test-data.js
@@ -26,6 +26,7 @@ module.exports = {
'currentCurrency': 'USD',
'conversionRate': 1200.88200327,
'conversionDate': 1489013762,
+ 'nativeCurrency': 'ETH',
'noActiveNotices': true,
'frequentRpcList': [],
'network': '3',
diff --git a/ui/app/components/send/tests/send-selectors.test.js b/ui/app/components/send/tests/send-selectors.test.js
index 1a47cd209..e7e901f0d 100644
--- a/ui/app/components/send/tests/send-selectors.test.js
+++ b/ui/app/components/send/tests/send-selectors.test.js
@@ -12,6 +12,7 @@ const {
getCurrentCurrency,
getCurrentNetwork,
getCurrentViewContext,
+ getNativeCurrency,
getForceGasMin,
getGasLimit,
getGasPrice,
@@ -178,6 +179,15 @@ describe('send selectors', () => {
})
})
+ describe('getNativeCurrency()', () => {
+ it('should return the ticker symbol of the selected network', () => {
+ assert.equal(
+ getNativeCurrency(mockState),
+ 'ETH'
+ )
+ })
+ })
+
describe('getCurrentNetwork()', () => {
it('should return the id of the currently selected network', () => {
assert.equal(
diff --git a/ui/app/components/shift-list-item.js b/ui/app/components/shift-list-item.js
index b87bf959e..0461b615a 100644
--- a/ui/app/components/shift-list-item.js
+++ b/ui/app/components/shift-list-item.js
@@ -52,12 +52,12 @@ ShiftListItem.prototype.render = function () {
},
}, [
h('img', {
- src: 'https://info.shapeshift.io/sites/default/files/logo.png',
+ src: 'https://shapeshift.io/logo.png',
style: {
height: '35px',
width: '132px',
position: 'absolute',
- clip: 'rect(0px,23px,34px,0px)',
+ clip: 'rect(0px,30px,34px,0px)',
},
}),
]),
@@ -132,7 +132,6 @@ ShiftListItem.prototype.renderInfo = function () {
case 'no_deposits':
return h('.flex-column', {
style: {
- width: '200px',
overflow: 'hidden',
},
}, [
diff --git a/ui/app/components/signature-request.js b/ui/app/components/signature-request.js
index d76eb5ef8..85af3b00b 100644
--- a/ui/app/components/signature-request.js
+++ b/ui/app/components/signature-request.js
@@ -2,7 +2,7 @@ const Component = require('react').Component
const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const inherits = require('util').inherits
-const Identicon = require('./identicon')
+import Identicon from './identicon'
const connect = require('react-redux').connect
const ethUtil = require('ethereumjs-util')
const classnames = require('classnames')
diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js
index 477d97597..75ba347fa 100644
--- a/ui/app/components/token-cell.js
+++ b/ui/app/components/token-cell.js
@@ -2,7 +2,7 @@ const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const connect = require('react-redux').connect
-const Identicon = require('./identicon')
+import Identicon from './identicon'
const prefixForNetwork = require('../../lib/etherscan-prefix-for-network')
const selectors = require('../selectors')
const actions = require('../actions')
diff --git a/ui/app/components/token-input/tests/token-input.component.test.js b/ui/app/components/token-input/tests/token-input.component.test.js
index 2131e7705..2dacb9bc4 100644
--- a/ui/app/components/token-input/tests/token-input.component.test.js
+++ b/ui/app/components/token-input/tests/token-input.component.test.js
@@ -122,7 +122,7 @@ describe('TokenInput Component', () => {
assert.equal(wrapper.find('.unit-input__suffix').length, 1)
assert.equal(wrapper.find('.unit-input__suffix').text(), 'ABC')
assert.equal(wrapper.find('.unit-input__input').props().value, '1')
- assert.equal(wrapper.find('.currency-display-component').text(), '2 ETH')
+ assert.equal(wrapper.find('.currency-display-component').text(), '2ETH')
})
it('should render properly with a token value for fiat', () => {
@@ -157,7 +157,7 @@ describe('TokenInput Component', () => {
assert.equal(wrapper.find('.unit-input__suffix').length, 1)
assert.equal(wrapper.find('.unit-input__suffix').text(), 'ABC')
assert.equal(wrapper.find('.unit-input__input').props().value, '1')
- assert.equal(wrapper.find('.currency-display-component').text(), '$462.12 USD')
+ assert.equal(wrapper.find('.currency-display-component').text(), '$462.12USD')
})
})
@@ -201,14 +201,14 @@ describe('TokenInput Component', () => {
const tokenInputInstance = wrapper.find(TokenInput).at(0).instance()
assert.equal(tokenInputInstance.state.decimalValue, 0)
assert.equal(tokenInputInstance.state.hexValue, undefined)
- assert.equal(wrapper.find('.currency-display-component').text(), '0 ETH')
+ assert.equal(wrapper.find('.currency-display-component').text(), '0ETH')
const input = wrapper.find('input')
assert.equal(input.props().value, 0)
input.simulate('change', { target: { value: 1 } })
assert.equal(handleChangeSpy.callCount, 1)
assert.ok(handleChangeSpy.calledWith('2710'))
- assert.equal(wrapper.find('.currency-display-component').text(), '2 ETH')
+ assert.equal(wrapper.find('.currency-display-component').text(), '2ETH')
assert.equal(tokenInputInstance.state.decimalValue, 1)
assert.equal(tokenInputInstance.state.hexValue, '2710')
@@ -250,14 +250,14 @@ describe('TokenInput Component', () => {
const tokenInputInstance = wrapper.find(TokenInput).at(0).instance()
assert.equal(tokenInputInstance.state.decimalValue, 0)
assert.equal(tokenInputInstance.state.hexValue, undefined)
- assert.equal(wrapper.find('.currency-display-component').text(), '$0.00 USD')
+ assert.equal(wrapper.find('.currency-display-component').text(), '$0.00USD')
const input = wrapper.find('input')
assert.equal(input.props().value, 0)
input.simulate('change', { target: { value: 1 } })
assert.equal(handleChangeSpy.callCount, 1)
assert.ok(handleChangeSpy.calledWith('2710'))
- assert.equal(wrapper.find('.currency-display-component').text(), '$462.12 USD')
+ assert.equal(wrapper.find('.currency-display-component').text(), '$462.12USD')
assert.equal(tokenInputInstance.state.decimalValue, 1)
assert.equal(tokenInputInstance.state.hexValue, '2710')
diff --git a/ui/app/components/transaction-activity-log/tests/transaction-activity-log.container.test.js b/ui/app/components/transaction-activity-log/tests/transaction-activity-log.container.test.js
index 85d56a6a2..a7c35f51e 100644
--- a/ui/app/components/transaction-activity-log/tests/transaction-activity-log.container.test.js
+++ b/ui/app/components/transaction-activity-log/tests/transaction-activity-log.container.test.js
@@ -18,10 +18,11 @@ describe('TransactionActivityLog container', () => {
const mockState = {
metamask: {
conversionRate: 280.45,
+ nativeCurrency: 'ETH',
},
}
- assert.deepEqual(mapStateToProps(mockState), { conversionRate: 280.45 })
+ assert.deepEqual(mapStateToProps(mockState), { conversionRate: 280.45, nativeCurrency: 'ETH' })
})
})
})
diff --git a/ui/app/components/transaction-activity-log/transaction-activity-log.component.js b/ui/app/components/transaction-activity-log/transaction-activity-log.component.js
index c4cf57d14..58d932a0f 100644
--- a/ui/app/components/transaction-activity-log/transaction-activity-log.component.js
+++ b/ui/app/components/transaction-activity-log/transaction-activity-log.component.js
@@ -4,7 +4,6 @@ import classnames from 'classnames'
import { getActivities } from './transaction-activity-log.util'
import Card from '../card'
import { getEthConversionFromWeiHex, getValueFromWeiHex } from '../../helpers/conversions.util'
-import { ETH } from '../../constants/common'
import { formatDate } from '../../util'
export default class TransactionActivityLog extends PureComponent {
@@ -16,6 +15,7 @@ export default class TransactionActivityLog extends PureComponent {
transaction: PropTypes.object,
className: PropTypes.string,
conversionRate: PropTypes.number,
+ nativeCurrency: PropTypes.string,
}
state = {
@@ -27,10 +27,14 @@ export default class TransactionActivityLog extends PureComponent {
}
componentDidUpdate (prevProps) {
- const { transaction: { history: prevHistory = [] } = {} } = prevProps
- const { transaction: { history = [] } = {} } = this.props
+ const {
+ transaction: { history: prevHistory = [], txReceipt: { status: prevStatus } = {} } = {},
+ } = prevProps
+ const {
+ transaction: { history = [], txReceipt: { status } = {} } = {},
+ } = this.props
- if (prevHistory.length !== history.length) {
+ if (prevHistory.length !== history.length || prevStatus !== status) {
this.setActivites()
}
}
@@ -41,16 +45,17 @@ export default class TransactionActivityLog extends PureComponent {
}
renderActivity (activity, index) {
- const { conversionRate } = this.props
+ const { conversionRate, nativeCurrency } = this.props
const { eventKey, value, timestamp } = activity
const ethValue = index === 0
? `${getValueFromWeiHex({
value,
- toCurrency: ETH,
+ fromCurrency: nativeCurrency,
+ toCurrency: nativeCurrency,
conversionRate,
numberOfDecimals: 6,
- })} ${ETH}`
- : getEthConversionFromWeiHex({ value, toCurrency: ETH, conversionRate })
+ })} ${nativeCurrency}`
+ : getEthConversionFromWeiHex({ value, fromCurrency: nativeCurrency, conversionRate })
const formattedTimestamp = formatDate(timestamp)
const activityText = this.context.t(eventKey, [ethValue, formattedTimestamp])
diff --git a/ui/app/components/transaction-activity-log/transaction-activity-log.container.js b/ui/app/components/transaction-activity-log/transaction-activity-log.container.js
index 4c8b6d971..622f77df1 100644
--- a/ui/app/components/transaction-activity-log/transaction-activity-log.container.js
+++ b/ui/app/components/transaction-activity-log/transaction-activity-log.container.js
@@ -1,10 +1,11 @@
import { connect } from 'react-redux'
import TransactionActivityLog from './transaction-activity-log.component'
-import { conversionRateSelector } from '../../selectors'
+import { conversionRateSelector, getNativeCurrency } from '../../selectors'
const mapStateToProps = state => {
return {
conversionRate: conversionRateSelector(state),
+ nativeCurrency: getNativeCurrency(state),
}
}
diff --git a/ui/app/components/transaction-activity-log/transaction-activity-log.util.js b/ui/app/components/transaction-activity-log/transaction-activity-log.util.js
index 97aa9a8f1..16597ae1a 100644
--- a/ui/app/components/transaction-activity-log/transaction-activity-log.util.js
+++ b/ui/app/components/transaction-activity-log/transaction-activity-log.util.js
@@ -18,6 +18,7 @@ const TRANSACTION_SUBMITTED_EVENT = 'transactionSubmitted'
const TRANSACTION_CONFIRMED_EVENT = 'transactionConfirmed'
const TRANSACTION_DROPPED_EVENT = 'transactionDropped'
const TRANSACTION_UPDATED_EVENT = 'transactionUpdated'
+const TRANSACTION_ERRORED_EVENT = 'transactionErrored'
const eventPathsHash = {
[STATUS_PATH]: true,
@@ -39,9 +40,9 @@ function eventCreator (eventKey, timestamp, value) {
}
export function getActivities (transaction) {
- const { history = [] } = transaction
+ const { history = [], txReceipt: { status } = {} } = transaction
- return history.reduce((acc, base) => {
+ const historyActivities = history.reduce((acc, base) => {
// First history item should be transaction creation
if (!Array.isArray(base) && base.status === UNAPPROVED_STATUS && base.txParams) {
const { time, txParams: { value } = {} } = base
@@ -83,4 +84,10 @@ export function getActivities (transaction) {
return acc
}, [])
+
+ // If txReceipt.status is '0x0', that means that an on-chain error occured for the transaction,
+ // so we add an error entry to the Activity Log.
+ return status === '0x0'
+ ? historyActivities.concat(eventCreator(TRANSACTION_ERRORED_EVENT))
+ : historyActivities
}
diff --git a/ui/app/components/transaction-breakdown/index.js b/ui/app/components/transaction-breakdown/index.js
index c887f504f..4a5b52663 100644
--- a/ui/app/components/transaction-breakdown/index.js
+++ b/ui/app/components/transaction-breakdown/index.js
@@ -1 +1 @@
-export { default } from './transaction-breakdown.component'
+export { default } from './transaction-breakdown.container'
diff --git a/ui/app/components/transaction-breakdown/transaction-breakdown.component.js b/ui/app/components/transaction-breakdown/transaction-breakdown.component.js
index 77bedcad7..3a7647873 100644
--- a/ui/app/components/transaction-breakdown/transaction-breakdown.component.js
+++ b/ui/app/components/transaction-breakdown/transaction-breakdown.component.js
@@ -6,7 +6,7 @@ import Card from '../card'
import CurrencyDisplay from '../currency-display'
import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display'
import HexToDecimal from '../hex-to-decimal'
-import { ETH, GWEI, PRIMARY, SECONDARY } from '../../constants/common'
+import { GWEI, PRIMARY, SECONDARY } from '../../constants/common'
import { getHexGasTotal } from '../../helpers/confirm-transaction/util'
import { sumHexes } from '../../helpers/transactions.util'
@@ -18,6 +18,7 @@ export default class TransactionBreakdown extends PureComponent {
static propTypes = {
transaction: PropTypes.object,
className: PropTypes.string,
+ nativeCurrency: PropTypes.string.isRequired,
}
static defaultProps = {
@@ -26,7 +27,7 @@ export default class TransactionBreakdown extends PureComponent {
render () {
const { t } = this.context
- const { transaction, className } = this.props
+ const { transaction, className, nativeCurrency } = this.props
const { txParams: { gas, gasPrice, value } = {}, txReceipt: { gasUsed } = {} } = transaction
const gasLimit = typeof gasUsed === 'string' ? gasUsed : gas
@@ -72,7 +73,7 @@ export default class TransactionBreakdown extends PureComponent {
<TransactionBreakdownRow title={t('gasPrice')}>
<CurrencyDisplay
className="transaction-breakdown__value"
- currency={ETH}
+ currency={nativeCurrency}
denomination={GWEI}
value={gasPrice}
hideLabel
diff --git a/ui/app/components/transaction-breakdown/transaction-breakdown.container.js b/ui/app/components/transaction-breakdown/transaction-breakdown.container.js
new file mode 100644
index 000000000..ed2708e03
--- /dev/null
+++ b/ui/app/components/transaction-breakdown/transaction-breakdown.container.js
@@ -0,0 +1,11 @@
+import { connect } from 'react-redux'
+import TransactionBreakdown from './transaction-breakdown.component'
+import { getNativeCurrency } from '../../selectors'
+
+const mapStateToProps = (state) => {
+ return {
+ nativeCurrency: getNativeCurrency(state),
+ }
+}
+
+export default connect(mapStateToProps)(TransactionBreakdown)
diff --git a/ui/app/components/transaction-list-item/index.scss b/ui/app/components/transaction-list-item/index.scss
index 9d694546b..ac0e7beeb 100644
--- a/ui/app/components/transaction-list-item/index.scss
+++ b/ui/app/components/transaction-list-item/index.scss
@@ -85,6 +85,7 @@
text-align: end;
grid-area: primary-amount;
align-self: end;
+ justify-self: end;
@media screen and (max-width: $break-small) {
padding-bottom: 2px;
@@ -97,6 +98,7 @@
color: #5e6064;
grid-area: secondary-amount;
align-self: start;
+ justify-self: end;
}
}
diff --git a/ui/app/components/transaction-list-item/transaction-list-item.component.js b/ui/app/components/transaction-list-item/transaction-list-item.component.js
index 88573d2d5..696634fe0 100644
--- a/ui/app/components/transaction-list-item/transaction-list-item.component.js
+++ b/ui/app/components/transaction-list-item/transaction-list-item.component.js
@@ -10,7 +10,6 @@ import TransactionListItemDetails from '../transaction-list-item-details'
import { CONFIRM_TRANSACTION_ROUTE } from '../../routes'
import { UNAPPROVED_STATUS, TOKEN_METHOD_TRANSFER } from '../../constants/transactions'
import { PRIMARY, SECONDARY } from '../../constants/common'
-import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../app/scripts/lib/enums'
import { getStatusKey } from '../../helpers/transactions.util'
export default class TransactionListItem extends PureComponent {
@@ -24,7 +23,6 @@ export default class TransactionListItem extends PureComponent {
showCancelModal: PropTypes.func,
showCancel: PropTypes.bool,
showRetry: PropTypes.bool,
- showTransactionDetailsModal: PropTypes.func,
token: PropTypes.object,
tokenData: PropTypes.object,
transaction: PropTypes.object,
@@ -39,31 +37,16 @@ export default class TransactionListItem extends PureComponent {
const {
transaction,
history,
- showTransactionDetailsModal,
- methodData,
- showCancel,
- showRetry,
} = this.props
const { id, status } = transaction
const { showTransactionDetails } = this.state
- const windowType = window.METAMASK_UI_TYPE
if (status === UNAPPROVED_STATUS) {
history.push(`${CONFIRM_TRANSACTION_ROUTE}/${id}`)
return
}
- if (windowType === ENVIRONMENT_TYPE_FULLSCREEN) {
- this.setState({ showTransactionDetails: !showTransactionDetails })
- } else {
- showTransactionDetailsModal({
- transaction,
- onRetry: this.handleRetry,
- showRetry: showRetry && methodData.done,
- onCancel: this.handleCancel,
- showCancel,
- })
- }
+ this.setState({ showTransactionDetails: !showTransactionDetails })
}
handleCancel = () => {
diff --git a/ui/app/components/transaction-list-item/transaction-list-item.container.js b/ui/app/components/transaction-list-item/transaction-list-item.container.js
index 72f5f5d61..62ed7a73f 100644
--- a/ui/app/components/transaction-list-item/transaction-list-item.container.js
+++ b/ui/app/components/transaction-list-item/transaction-list-item.container.js
@@ -28,16 +28,6 @@ const mapDispatchToProps = dispatch => {
showCancelModal: (transactionId, originalGasPrice) => {
return dispatch(showModal({ name: 'CANCEL_TRANSACTION', transactionId, originalGasPrice }))
},
- showTransactionDetailsModal: ({ transaction, onRetry, showRetry, onCancel, showCancel }) => {
- return dispatch(showModal({
- name: 'TRANSACTION_DETAILS',
- transaction,
- onRetry,
- showRetry,
- onCancel,
- showCancel,
- }))
- },
}
}
diff --git a/ui/app/components/transaction-list/index.scss b/ui/app/components/transaction-list/index.scss
index 777f701f9..ba7ffd87b 100644
--- a/ui/app/components/transaction-list/index.scss
+++ b/ui/app/components/transaction-list/index.scss
@@ -2,9 +2,7 @@
display: flex;
flex-direction: column;
flex: 1;
- overflow-y: hidden;
margin-top: 8px;
- border-top: 1px solid $geyser;
&__completed-transactions {
display: flex;
@@ -26,7 +24,6 @@
&__transactions {
flex: 1;
- overflow-y: auto;
}
&__pending-transactions {
diff --git a/ui/app/components/transaction-view-balance/index.scss b/ui/app/components/transaction-view-balance/index.scss
index 12045ab6d..659f896ff 100644
--- a/ui/app/components/transaction-view-balance/index.scss
+++ b/ui/app/components/transaction-view-balance/index.scss
@@ -4,11 +4,13 @@
align-items: center;
flex: 1;
height: 54px;
+ min-width: 0;
&__balance {
- margin-left: 12px;
+ margin: 0 12px;
display: flex;
flex-direction: column;
+ min-width: 0;
@media screen and (max-width: $break-small) {
align-items: center;
@@ -21,7 +23,8 @@
font-size: 1.5rem;
@media screen and (max-width: $break-small) {
- margin-bottom: 12px;
+ margin: 12px 0;
+ margin-left: 0;
font-size: 1.75rem;
}
}
@@ -30,7 +33,6 @@
font-size: 1.5rem;
@media screen and (max-width: $break-small) {
- margin-bottom: 12px;
font-size: 1.75rem;
}
}
@@ -45,6 +47,7 @@
display: flex;
flex-direction: row;
align-items: center;
+ min-width: 0;
@media screen and (max-width: $break-small) {
flex-direction: column;
diff --git a/ui/app/components/transaction-view-balance/transaction-view-balance.container.js b/ui/app/components/transaction-view-balance/transaction-view-balance.container.js
index 30c5cab16..cb8078ec1 100644
--- a/ui/app/components/transaction-view-balance/transaction-view-balance.container.js
+++ b/ui/app/components/transaction-view-balance/transaction-view-balance.container.js
@@ -2,7 +2,7 @@ import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
import { compose } from 'recompose'
import TransactionViewBalance from './transaction-view-balance.component'
-import { getSelectedToken, getSelectedAddress, getSelectedTokenAssetImage } from '../../selectors'
+import { getSelectedToken, getSelectedAddress, getNativeCurrency, getSelectedTokenAssetImage } from '../../selectors'
import { showModal } from '../../actions'
const mapStateToProps = state => {
@@ -15,6 +15,7 @@ const mapStateToProps = state => {
selectedToken: getSelectedToken(state),
network,
balance,
+ nativeCurrency: getNativeCurrency(state),
assetImage: getSelectedTokenAssetImage(state),
}
}
diff --git a/ui/app/components/transaction-view/index.scss b/ui/app/components/transaction-view/index.scss
index af9771ce0..13187f0e5 100644
--- a/ui/app/components/transaction-view/index.scss
+++ b/ui/app/components/transaction-view/index.scss
@@ -4,6 +4,7 @@
min-width: 0;
display: flex;
flex-direction: column;
+ overflow-y: auto;
&__balance-wrapper {
@media screen and (max-width: $break-small) {
diff --git a/ui/app/components/user-preferenced-currency-display/tests/user-preferenced-currency-display.container.test.js b/ui/app/components/user-preferenced-currency-display/tests/user-preferenced-currency-display.container.test.js
index 41ad3b73e..ba1c23d83 100644
--- a/ui/app/components/user-preferenced-currency-display/tests/user-preferenced-currency-display.container.test.js
+++ b/ui/app/components/user-preferenced-currency-display/tests/user-preferenced-currency-display.container.test.js
@@ -18,14 +18,16 @@ describe('UserPreferencedCurrencyDisplay container', () => {
it('should return the correct props', () => {
const mockState = {
metamask: {
+ nativeCurrency: 'ETH',
preferences: {
- useETHAsPrimaryCurrency: true,
+ useNativeCurrencyAsPrimaryCurrency: true,
},
},
}
assert.deepEqual(mapStateToProps(mockState), {
- useETHAsPrimaryCurrency: true,
+ nativeCurrency: 'ETH',
+ useNativeCurrencyAsPrimaryCurrency: true,
})
})
})
@@ -37,33 +39,38 @@ describe('UserPreferencedCurrencyDisplay container', () => {
const tests = [
{
stateProps: {
- useETHAsPrimaryCurrency: true,
+ useNativeCurrencyAsPrimaryCurrency: true,
+ nativeCurrency: 'ETH',
},
ownProps: {
type: 'PRIMARY',
},
result: {
currency: 'ETH',
+ nativeCurrency: 'ETH',
numberOfDecimals: 6,
prefix: undefined,
},
},
{
stateProps: {
- useETHAsPrimaryCurrency: false,
+ useNativeCurrencyAsPrimaryCurrency: false,
+ nativeCurrency: 'ETH',
},
ownProps: {
type: 'PRIMARY',
},
result: {
currency: undefined,
+ nativeCurrency: 'ETH',
numberOfDecimals: 2,
prefix: undefined,
},
},
{
stateProps: {
- useETHAsPrimaryCurrency: true,
+ useNativeCurrencyAsPrimaryCurrency: true,
+ nativeCurrency: 'ETH',
},
ownProps: {
type: 'SECONDARY',
@@ -71,6 +78,7 @@ describe('UserPreferencedCurrencyDisplay container', () => {
fiatPrefix: '-',
},
result: {
+ nativeCurrency: 'ETH',
currency: undefined,
numberOfDecimals: 4,
prefix: '-',
@@ -78,7 +86,8 @@ describe('UserPreferencedCurrencyDisplay container', () => {
},
{
stateProps: {
- useETHAsPrimaryCurrency: false,
+ useNativeCurrencyAsPrimaryCurrency: false,
+ nativeCurrency: 'ETH',
},
ownProps: {
type: 'SECONDARY',
@@ -89,6 +98,7 @@ describe('UserPreferencedCurrencyDisplay container', () => {
},
result: {
currency: 'ETH',
+ nativeCurrency: 'ETH',
numberOfDecimals: 3,
prefix: 'b',
},
diff --git a/ui/app/components/user-preferenced-currency-display/user-preferenced-currency-display.component.js b/ui/app/components/user-preferenced-currency-display/user-preferenced-currency-display.component.js
index 4d948ca6a..f2a834ea7 100644
--- a/ui/app/components/user-preferenced-currency-display/user-preferenced-currency-display.component.js
+++ b/ui/app/components/user-preferenced-currency-display/user-preferenced-currency-display.component.js
@@ -21,6 +21,7 @@ export default class UserPreferencedCurrencyDisplay extends PureComponent {
fiatPrefix: PropTypes.string,
// From container
currency: PropTypes.string,
+ nativeCurrency: PropTypes.string,
}
renderEthLogo () {
diff --git a/ui/app/components/user-preferenced-currency-display/user-preferenced-currency-display.container.js b/ui/app/components/user-preferenced-currency-display/user-preferenced-currency-display.container.js
index 23240c649..7999301ad 100644
--- a/ui/app/components/user-preferenced-currency-display/user-preferenced-currency-display.container.js
+++ b/ui/app/components/user-preferenced-currency-display/user-preferenced-currency-display.container.js
@@ -4,15 +4,16 @@ import { preferencesSelector } from '../../selectors'
import { ETH, PRIMARY, SECONDARY } from '../../constants/common'
const mapStateToProps = (state, ownProps) => {
- const { useETHAsPrimaryCurrency } = preferencesSelector(state)
+ const { useNativeCurrencyAsPrimaryCurrency } = preferencesSelector(state)
return {
- useETHAsPrimaryCurrency,
+ useNativeCurrencyAsPrimaryCurrency,
+ nativeCurrency: state.metamask.nativeCurrency,
}
}
const mergeProps = (stateProps, dispatchProps, ownProps) => {
- const { useETHAsPrimaryCurrency, ...restStateProps } = stateProps
+ const { useNativeCurrencyAsPrimaryCurrency, nativeCurrency, ...restStateProps } = stateProps
const {
type,
numberOfDecimals: propsNumberOfDecimals,
@@ -26,14 +27,14 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
let currency, numberOfDecimals, prefix
- if (type === PRIMARY && useETHAsPrimaryCurrency ||
- type === SECONDARY && !useETHAsPrimaryCurrency) {
+ if (type === PRIMARY && useNativeCurrencyAsPrimaryCurrency ||
+ type === SECONDARY && !useNativeCurrencyAsPrimaryCurrency) {
// Display ETH
- currency = ETH
+ currency = nativeCurrency || ETH
numberOfDecimals = propsNumberOfDecimals || ethNumberOfDecimals || 6
prefix = propsPrefix || ethPrefix
- } else if (type === SECONDARY && useETHAsPrimaryCurrency ||
- type === PRIMARY && !useETHAsPrimaryCurrency) {
+ } else if (type === SECONDARY && useNativeCurrencyAsPrimaryCurrency ||
+ type === PRIMARY && !useNativeCurrencyAsPrimaryCurrency) {
// Display Fiat
numberOfDecimals = propsNumberOfDecimals || fiatNumberOfDecimals || 2
prefix = propsPrefix || fiatPrefix
@@ -43,6 +44,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
...restStateProps,
...dispatchProps,
...restOwnProps,
+ nativeCurrency,
currency,
numberOfDecimals,
prefix,
diff --git a/ui/app/components/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js b/ui/app/components/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js
index 0af80a03d..710b5d519 100644
--- a/ui/app/components/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js
+++ b/ui/app/components/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js
@@ -15,17 +15,17 @@ describe('UserPreferencedCurrencyInput Component', () => {
assert.equal(wrapper.find(CurrencyInput).length, 1)
})
- it('should render useFiat for CurrencyInput based on preferences.useETHAsPrimaryCurrency', () => {
+ it('should render useFiat for CurrencyInput based on preferences.useNativeCurrencyAsPrimaryCurrency', () => {
const wrapper = shallow(
<UserPreferencedCurrencyInput
- useETHAsPrimaryCurrency
+ useNativeCurrencyAsPrimaryCurrency
/>
)
assert.ok(wrapper)
assert.equal(wrapper.find(CurrencyInput).length, 1)
assert.equal(wrapper.find(CurrencyInput).props().useFiat, false)
- wrapper.setProps({ useETHAsPrimaryCurrency: false })
+ wrapper.setProps({ useNativeCurrencyAsPrimaryCurrency: false })
assert.equal(wrapper.find(CurrencyInput).props().useFiat, true)
})
})
diff --git a/ui/app/components/user-preferenced-currency-input/tests/user-preferenced-currency-input.container.test.js b/ui/app/components/user-preferenced-currency-input/tests/user-preferenced-currency-input.container.test.js
index d860c38da..959726443 100644
--- a/ui/app/components/user-preferenced-currency-input/tests/user-preferenced-currency-input.container.test.js
+++ b/ui/app/components/user-preferenced-currency-input/tests/user-preferenced-currency-input.container.test.js
@@ -18,13 +18,13 @@ describe('UserPreferencedCurrencyInput container', () => {
const mockState = {
metamask: {
preferences: {
- useETHAsPrimaryCurrency: true,
+ useNativeCurrencyAsPrimaryCurrency: true,
},
},
}
assert.deepEqual(mapStateToProps(mockState), {
- useETHAsPrimaryCurrency: true,
+ useNativeCurrencyAsPrimaryCurrency: true,
})
})
})
diff --git a/ui/app/components/user-preferenced-currency-input/user-preferenced-currency-input.component.js b/ui/app/components/user-preferenced-currency-input/user-preferenced-currency-input.component.js
index 6e0e00a1d..463e66b80 100644
--- a/ui/app/components/user-preferenced-currency-input/user-preferenced-currency-input.component.js
+++ b/ui/app/components/user-preferenced-currency-input/user-preferenced-currency-input.component.js
@@ -4,16 +4,16 @@ import CurrencyInput from '../currency-input'
export default class UserPreferencedCurrencyInput extends PureComponent {
static propTypes = {
- useETHAsPrimaryCurrency: PropTypes.bool,
+ useNativeCurrencyAsPrimaryCurrency: PropTypes.bool,
}
render () {
- const { useETHAsPrimaryCurrency, ...restProps } = this.props
+ const { useNativeCurrencyAsPrimaryCurrency, ...restProps } = this.props
return (
<CurrencyInput
{...restProps}
- useFiat={!useETHAsPrimaryCurrency}
+ useFiat={!useNativeCurrencyAsPrimaryCurrency}
/>
)
}
diff --git a/ui/app/components/user-preferenced-currency-input/user-preferenced-currency-input.container.js b/ui/app/components/user-preferenced-currency-input/user-preferenced-currency-input.container.js
index 397cdc7cc..0b88eb5a7 100644
--- a/ui/app/components/user-preferenced-currency-input/user-preferenced-currency-input.container.js
+++ b/ui/app/components/user-preferenced-currency-input/user-preferenced-currency-input.container.js
@@ -3,10 +3,10 @@ import UserPreferencedCurrencyInput from './user-preferenced-currency-input.comp
import { preferencesSelector } from '../../selectors'
const mapStateToProps = state => {
- const { useETHAsPrimaryCurrency } = preferencesSelector(state)
+ const { useNativeCurrencyAsPrimaryCurrency } = preferencesSelector(state)
return {
- useETHAsPrimaryCurrency,
+ useNativeCurrencyAsPrimaryCurrency,
}
}
diff --git a/ui/app/components/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js b/ui/app/components/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js
index 910c7089f..d85bddeeb 100644
--- a/ui/app/components/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js
+++ b/ui/app/components/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js
@@ -15,17 +15,17 @@ describe('UserPreferencedCurrencyInput Component', () => {
assert.equal(wrapper.find(TokenInput).length, 1)
})
- it('should render showFiat for TokenInput based on preferences.useETHAsPrimaryCurrency', () => {
+ it('should render showFiat for TokenInput based on preferences.useNativeCurrencyAsPrimaryCurrency', () => {
const wrapper = shallow(
<UserPreferencedTokenInput
- useETHAsPrimaryCurrency
+ useNativeCurrencyAsPrimaryCurrency
/>
)
assert.ok(wrapper)
assert.equal(wrapper.find(TokenInput).length, 1)
assert.equal(wrapper.find(TokenInput).props().showFiat, false)
- wrapper.setProps({ useETHAsPrimaryCurrency: false })
+ wrapper.setProps({ useNativeCurrencyAsPrimaryCurrency: false })
assert.equal(wrapper.find(TokenInput).props().showFiat, true)
})
})
diff --git a/ui/app/components/user-preferenced-token-input/tests/user-preferenced-token-input.container.test.js b/ui/app/components/user-preferenced-token-input/tests/user-preferenced-token-input.container.test.js
index e3509149a..2f89fba90 100644
--- a/ui/app/components/user-preferenced-token-input/tests/user-preferenced-token-input.container.test.js
+++ b/ui/app/components/user-preferenced-token-input/tests/user-preferenced-token-input.container.test.js
@@ -18,13 +18,13 @@ describe('UserPreferencedTokenInput container', () => {
const mockState = {
metamask: {
preferences: {
- useETHAsPrimaryCurrency: true,
+ useNativeCurrencyAsPrimaryCurrency: true,
},
},
}
assert.deepEqual(mapStateToProps(mockState), {
- useETHAsPrimaryCurrency: true,
+ useNativeCurrencyAsPrimaryCurrency: true,
})
})
})
diff --git a/ui/app/components/user-preferenced-token-input/user-preferenced-token-input.component.js b/ui/app/components/user-preferenced-token-input/user-preferenced-token-input.component.js
index f2b537f11..8f14231ac 100644
--- a/ui/app/components/user-preferenced-token-input/user-preferenced-token-input.component.js
+++ b/ui/app/components/user-preferenced-token-input/user-preferenced-token-input.component.js
@@ -4,16 +4,16 @@ import TokenInput from '../token-input'
export default class UserPreferencedTokenInput extends PureComponent {
static propTypes = {
- useETHAsPrimaryCurrency: PropTypes.bool,
+ useNativeCurrencyAsPrimaryCurrency: PropTypes.bool,
}
render () {
- const { useETHAsPrimaryCurrency, ...restProps } = this.props
+ const { useNativeCurrencyAsPrimaryCurrency, ...restProps } = this.props
return (
<TokenInput
{...restProps}
- showFiat={!useETHAsPrimaryCurrency}
+ showFiat={!useNativeCurrencyAsPrimaryCurrency}
/>
)
}
diff --git a/ui/app/components/user-preferenced-token-input/user-preferenced-token-input.container.js b/ui/app/components/user-preferenced-token-input/user-preferenced-token-input.container.js
index 416d069dd..3305d4e29 100644
--- a/ui/app/components/user-preferenced-token-input/user-preferenced-token-input.container.js
+++ b/ui/app/components/user-preferenced-token-input/user-preferenced-token-input.container.js
@@ -3,10 +3,10 @@ import UserPreferencedTokenInput from './user-preferenced-token-input.component'
import { preferencesSelector } from '../../selectors'
const mapStateToProps = state => {
- const { useETHAsPrimaryCurrency } = preferencesSelector(state)
+ const { useNativeCurrencyAsPrimaryCurrency } = preferencesSelector(state)
return {
- useETHAsPrimaryCurrency,
+ useNativeCurrencyAsPrimaryCurrency,
}
}
diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js
index 8a7cb0f8d..e050e0ee6 100644
--- a/ui/app/components/wallet-view.js
+++ b/ui/app/components/wallet-view.js
@@ -7,7 +7,7 @@ const { compose } = require('recompose')
const inherits = require('util').inherits
const classnames = require('classnames')
const { checksumAddress } = require('../util')
-const Identicon = require('./identicon')
+import Identicon from './identicon'
// const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns
const Tooltip = require('./tooltip-v2.js').default
const copyToClipboard = require('copy-to-clipboard')
@@ -127,7 +127,6 @@ WalletView.prototype.render = function () {
identities,
} = this.props
// temporary logs + fake extra wallets
- // console.log('walletview, selectedAccount:', selectedAccount)
const checksummedAddress = checksumAddress(selectedAddress)
diff --git a/ui/app/constants/error-keys.js b/ui/app/constants/error-keys.js
index f70ed3b19..704064c96 100644
--- a/ui/app/constants/error-keys.js
+++ b/ui/app/constants/error-keys.js
@@ -1,3 +1,4 @@
export const INSUFFICIENT_FUNDS_ERROR_KEY = 'insufficientFunds'
export const GAS_LIMIT_TOO_LOW_ERROR_KEY = 'gasLimitTooLow'
export const TRANSACTION_ERROR_KEY = 'transactionError'
+export const TRANSACTION_NO_CONTRACT_ERROR_KEY = 'transactionErrorNoContract'
diff --git a/ui/app/css/itcss/components/buttons.scss b/ui/app/css/itcss/components/buttons.scss
index 655188a3e..5826a8b49 100644
--- a/ui/app/css/itcss/components/buttons.scss
+++ b/ui/app/css/itcss/components/buttons.scss
@@ -3,7 +3,7 @@
*/
.button {
- height: 44px;
+ min-height: 44px;
background: $white;
display: flex;
justify-content: center;
@@ -82,12 +82,13 @@
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.08);
padding: 6px;
height: initial;
+ min-height: initial;
width: initial;
min-width: initial;
}
.btn--large {
- height: 54px;
+ min-height: 54px;
}
.btn-green {
diff --git a/ui/app/css/itcss/components/request-signature.scss b/ui/app/css/itcss/components/request-signature.scss
index 445b9ebf5..6c950d846 100644
--- a/ui/app/css/itcss/components/request-signature.scss
+++ b/ui/app/css/itcss/components/request-signature.scss
@@ -19,7 +19,7 @@
}
@media screen and (min-width: $break-large) {
- max-height: 620px;
+ height: 620px;
}
}
diff --git a/ui/app/css/itcss/components/wallet-balance.scss b/ui/app/css/itcss/components/wallet-balance.scss
index 293771550..3c3349ae0 100644
--- a/ui/app/css/itcss/components/wallet-balance.scss
+++ b/ui/app/css/itcss/components/wallet-balance.scss
@@ -29,7 +29,7 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and (
align-items: center;
margin: 20px 24px;
flex-direction: row;
- flex-grow: 3;
+ min-width: 0;
@media #{$wallet-balance-breakpoint-range} {
margin: 10% 4%;
@@ -38,8 +38,7 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and (
.balance-display {
margin-left: 15px;
- justify-content: flex-start;
- align-items: flex-start;
+ min-width: 0;
.token-amount {
font-size: 1.5rem;
diff --git a/ui/app/ducks/confirm-transaction.duck.js b/ui/app/ducks/confirm-transaction.duck.js
index 2ceafbe08..275eb1551 100644
--- a/ui/app/ducks/confirm-transaction.duck.js
+++ b/ui/app/ducks/confirm-transaction.duck.js
@@ -2,6 +2,7 @@ import {
conversionRateSelector,
currentCurrencySelector,
unconfirmedTransactionsHashSelector,
+ getNativeCurrency,
} from '../selectors/confirm-transaction'
import {
@@ -292,16 +293,17 @@ export function updateTxDataAndCalculate (txData) {
const state = getState()
const currentCurrency = currentCurrencySelector(state)
const conversionRate = conversionRateSelector(state)
+ const nativeCurrency = getNativeCurrency(state)
dispatch(updateTxData(txData))
const { txParams: { value = '0x0', gas: gasLimit = '0x0', gasPrice = '0x0' } = {} } = txData
const fiatTransactionAmount = getValueFromWeiHex({
- value, toCurrency: currentCurrency, conversionRate, numberOfDecimals: 2,
+ value, fromCurrency: nativeCurrency, toCurrency: currentCurrency, conversionRate, numberOfDecimals: 2,
})
const ethTransactionAmount = getValueFromWeiHex({
- value, toCurrency: 'ETH', conversionRate, numberOfDecimals: 6,
+ value, fromCurrency: nativeCurrency, toCurrency: nativeCurrency, conversionRate, numberOfDecimals: 6,
})
dispatch(updateTransactionAmounts({
@@ -314,13 +316,15 @@ export function updateTxDataAndCalculate (txData) {
const fiatTransactionFee = getTransactionFee({
value: hexTransactionFee,
+ fromCurrency: nativeCurrency,
toCurrency: currentCurrency,
numberOfDecimals: 2,
conversionRate,
})
const ethTransactionFee = getTransactionFee({
value: hexTransactionFee,
- toCurrency: 'ETH',
+ fromCurrency: nativeCurrency,
+ toCurrency: nativeCurrency,
numberOfDecimals: 6,
conversionRate,
})
@@ -329,7 +333,6 @@ export function updateTxDataAndCalculate (txData) {
const fiatTransactionTotal = addFiat(fiatTransactionFee, fiatTransactionAmount)
const ethTransactionTotal = addEth(ethTransactionFee, ethTransactionAmount)
- console.log('HIHIH', value, hexTransactionFee)
const hexTransactionTotal = sumHexes(value, hexTransactionFee)
dispatch(updateTransactionTotals({
diff --git a/ui/app/helpers/confirm-transaction/util.js b/ui/app/helpers/confirm-transaction/util.js
index bcac22500..eb334a4b8 100644
--- a/ui/app/helpers/confirm-transaction/util.js
+++ b/ui/app/helpers/confirm-transaction/util.js
@@ -55,6 +55,7 @@ export function addFiat (...args) {
export function getValueFromWeiHex ({
value,
+ fromCurrency = 'ETH',
toCurrency,
conversionRate,
numberOfDecimals,
@@ -63,7 +64,7 @@ export function getValueFromWeiHex ({
return conversionUtil(value, {
fromNumericBase: 'hex',
toNumericBase: 'dec',
- fromCurrency: 'ETH',
+ fromCurrency,
toCurrency,
numberOfDecimals,
fromDenomination: 'WEI',
@@ -74,6 +75,7 @@ export function getValueFromWeiHex ({
export function getTransactionFee ({
value,
+ fromCurrency = 'ETH',
toCurrency,
conversionRate,
numberOfDecimals,
@@ -82,7 +84,7 @@ export function getTransactionFee ({
fromNumericBase: 'BN',
toNumericBase: 'dec',
fromDenomination: 'WEI',
- fromCurrency: 'ETH',
+ fromCurrency,
toCurrency,
numberOfDecimals,
conversionRate,
@@ -99,6 +101,7 @@ export function formatCurrency (value, currencyCode) {
export function convertTokenToFiat ({
value,
+ fromCurrency = 'ETH',
toCurrency,
conversionRate,
contractExchangeRate,
@@ -108,6 +111,7 @@ export function convertTokenToFiat ({
return conversionUtil(value, {
fromNumericBase: 'dec',
toNumericBase: 'dec',
+ fromCurrency,
toCurrency,
numberOfDecimals: 2,
conversionRate: totalExchangeRate,
diff --git a/ui/app/helpers/conversions.util.js b/ui/app/helpers/conversions.util.js
index 777537e1e..cb5e1b90b 100644
--- a/ui/app/helpers/conversions.util.js
+++ b/ui/app/helpers/conversions.util.js
@@ -20,8 +20,8 @@ export function decimalToHex (decimal) {
})
}
-export function getEthConversionFromWeiHex ({ value, conversionRate, numberOfDecimals = 6 }) {
- const denominations = [ETH, GWEI, WEI]
+export function getEthConversionFromWeiHex ({ value, fromCurrency = ETH, conversionRate, numberOfDecimals = 6 }) {
+ const denominations = [fromCurrency, GWEI, WEI]
let nonZeroDenomination
@@ -29,7 +29,8 @@ export function getEthConversionFromWeiHex ({ value, conversionRate, numberOfDec
const convertedValue = getValueFromWeiHex({
value,
conversionRate,
- toCurrency: ETH,
+ fromCurrency,
+ toCurrency: fromCurrency,
numberOfDecimals,
toDenomination: denominations[i],
})
@@ -45,6 +46,7 @@ export function getEthConversionFromWeiHex ({ value, conversionRate, numberOfDec
export function getValueFromWeiHex ({
value,
+ fromCurrency = ETH,
toCurrency,
conversionRate,
numberOfDecimals,
@@ -53,7 +55,7 @@ export function getValueFromWeiHex ({
return conversionUtil(value, {
fromNumericBase: 'hex',
toNumericBase: 'dec',
- fromCurrency: ETH,
+ fromCurrency,
toCurrency,
numberOfDecimals,
fromDenomination: WEI,
diff --git a/ui/app/helpers/transactions.util.js b/ui/app/helpers/transactions.util.js
index e50196196..2f4b1d095 100644
--- a/ui/app/helpers/transactions.util.js
+++ b/ui/app/helpers/transactions.util.js
@@ -27,10 +27,21 @@ export function getTokenData (data = '') {
const registry = new MethodRegistry({ provider: global.ethereumProvider })
+/**
+ * Attempts to return the method data from the MethodRegistry library, if the method exists in the
+ * registry. Otherwise, returns an empty object.
+ * @param {string} data - The hex data (@code txParams.data) of a transaction
+ * @returns {Object}
+ */
export async function getMethodData (data = '') {
const prefixedData = ethUtil.addHexPrefix(data)
const fourBytePrefix = prefixedData.slice(0, 10)
const sig = await registry.lookup(fourBytePrefix)
+
+ if (!sig) {
+ return {}
+ }
+
const parsedResult = registry.parse(sig)
return {
@@ -114,7 +125,9 @@ export function getLatestSubmittedTxWithNonce (transactions = [], nonce = '0x0')
export async function isSmartContractAddress (address) {
const code = await global.eth.getCode(address)
- return code && code !== '0x'
+ // Geth will return '0x', and ganache-core v2.2.1 will return '0x0'
+ const codeIsEmpty = !code || code === '0x' || code === '0x0'
+ return !codeIsEmpty
}
export function sumHexes (...args) {
diff --git a/ui/app/reducers.js b/ui/app/reducers.js
index 80e76d570..e1a982f93 100644
--- a/ui/app/reducers.js
+++ b/ui/app/reducers.js
@@ -1,3 +1,4 @@
+const clone = require('clone')
const extend = require('xtend')
const copyToClipboard = require('copy-to-clipboard')
@@ -52,19 +53,24 @@ function rootReducer (state, action) {
return state
}
+window.getCleanAppState = function () {
+ const state = clone(window.METAMASK_CACHED_LOG_STATE)
+ // append additional information
+ state.version = global.platform.getVersion()
+ state.browser = window.navigator.userAgent
+ // ensure seedWords are not included
+ if (state.metamask) delete state.metamask.seedWords
+ if (state.appState.currentView) delete state.appState.currentView.seedWords
+ return state
+}
+
window.logStateString = function (cb) {
- const state = window.METAMASK_CACHED_LOG_STATE
- const version = global.platform.getVersion()
- const browser = window.navigator.userAgent
- return global.platform.getPlatformInfo((err, platform) => {
- if (err) {
- return cb(err)
- }
- state.version = version
+ const state = window.getCleanAppState()
+ global.platform.getPlatformInfo((err, platform) => {
+ if (err) return cb(err)
state.platform = platform
- state.browser = browser
const stateString = JSON.stringify(state, removeSeedWords, 2)
- return cb(null, stateString)
+ cb(null, stateString)
})
}
diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js
index 37d8a9187..22fa53098 100644
--- a/ui/app/reducers/metamask.js
+++ b/ui/app/reducers/metamask.js
@@ -52,7 +52,7 @@ function reduceMetamask (state, action) {
welcomeScreenSeen: false,
currentLocale: '',
preferences: {
- useETHAsPrimaryCurrency: true,
+ useNativeCurrencyAsPrimaryCurrency: true,
},
}, state.metamask)
diff --git a/ui/app/selectors.js b/ui/app/selectors.js
index 9f11551be..7209f19d1 100644
--- a/ui/app/selectors.js
+++ b/ui/app/selectors.js
@@ -26,6 +26,7 @@ const selectors = {
getAddressBook,
getSendFrom,
getCurrentCurrency,
+ getNativeCurrency,
getSendAmount,
getSelectedTokenToFiatRate,
getSelectedTokenContract,
@@ -143,6 +144,10 @@ function getCurrentCurrency (state) {
return state.metamask.currentCurrency
}
+function getNativeCurrency (state) {
+ return state.metamask.nativeCurrency
+}
+
function getSelectedTokenToFiatRate (state) {
const selectedTokenExchangeRate = getSelectedTokenExchangeRate(state)
const conversionRate = conversionRateSelector(state)
diff --git a/ui/app/selectors/confirm-transaction.js b/ui/app/selectors/confirm-transaction.js
index 86b10bac3..90924c036 100644
--- a/ui/app/selectors/confirm-transaction.js
+++ b/ui/app/selectors/confirm-transaction.js
@@ -93,6 +93,7 @@ export const unconfirmedTransactionsCountSelector = createSelector(
export const currentCurrencySelector = state => state.metamask.currentCurrency
export const conversionRateSelector = state => state.metamask.conversionRate
+export const getNativeCurrency = state => state.metamask.nativeCurrency
const txDataSelector = state => state.confirmTransaction.txData
const tokenDataSelector = state => state.confirmTransaction.tokenData
diff --git a/ui/app/util.js b/ui/app/util.js
index 37c0fb698..b19a028cc 100644
--- a/ui/app/util.js
+++ b/ui/app/util.js
@@ -128,7 +128,7 @@ function parseBalance (balance) {
// Takes wei hex, returns an object with three properties.
// Its "formatted" property is what we generally use to render values.
-function formatBalance (balance, decimalsToKeep, needsParse = true) {
+function formatBalance (balance, decimalsToKeep, needsParse = true, ticker = 'ETH') {
var parsed = needsParse ? parseBalance(balance) : balance.split('.')
var beforeDecimal = parsed[0]
var afterDecimal = parsed[1]
@@ -138,14 +138,14 @@ function formatBalance (balance, decimalsToKeep, needsParse = true) {
if (afterDecimal !== '0') {
var sigFigs = afterDecimal.match(/^0*(.{2})/) // default: grabs 2 most significant digits
if (sigFigs) { afterDecimal = sigFigs[0] }
- formatted = '0.' + afterDecimal + ' ETH'
+ formatted = '0.' + afterDecimal + ` ${ticker}`
}
} else {
- formatted = beforeDecimal + '.' + afterDecimal.slice(0, 3) + ' ETH'
+ formatted = beforeDecimal + '.' + afterDecimal.slice(0, 3) + ` ${ticker}`
}
} else {
afterDecimal += Array(decimalsToKeep).join('0')
- formatted = beforeDecimal + '.' + afterDecimal.slice(0, decimalsToKeep) + ' ETH'
+ formatted = beforeDecimal + '.' + afterDecimal.slice(0, decimalsToKeep) + ` ${ticker}`
}
return formatted
}