diff options
66 files changed, 1252 insertions, 447 deletions
diff --git a/app/scripts/controllers/token-rates.js b/app/scripts/controllers/token-rates.js index 867d36433..4e396bb59 100644 --- a/app/scripts/controllers/token-rates.js +++ b/app/scripts/controllers/token-rates.js @@ -28,16 +28,16 @@ class TokenRatesController { async updateExchangeRates () { if (!this.isActive) { return } const contractExchangeRates = {} - const nativeCurrency = this.currency ? this.currency.getState().nativeCurrency.toUpperCase() : 'ETH' - const pairs = this._tokens.map(token => `pairs[]=${token.address}/${nativeCurrency}`) - const query = pairs.join('&') + const nativeCurrency = this.currency ? this.currency.getState().nativeCurrency.toLowerCase() : 'eth' + const pairs = this._tokens.map(token => token.address).join(',') + const query = `contract_addresses=${pairs}&vs_currencies=${nativeCurrency}` if (this._tokens.length > 0) { try { - const response = await fetch(`https://exchanges.balanc3.net/pie?${query}&autoConversion=false`) - const { prices = [] } = await response.json() - prices.forEach(({ pair, price }) => { - const address = pair.split('/')[0] - contractExchangeRates[normalizeAddress(address)] = typeof price === 'number' ? price : 0 + const response = await fetch(`https://api.coingecko.com/api/v3/simple/token_price/ethereum?${query}`) + const prices = await response.json() + this._tokens.forEach(token => { + const price = prices[token.address.toLowerCase()] + contractExchangeRates[normalizeAddress(token.address)] = price ? price[nativeCurrency] : 0 }) } catch (error) { log.warn(`MetaMask - TokenRatesController exchange rate fetch failed.`, error) diff --git a/docs/limited_site_access.md b/docs/limited_site_access.md new file mode 100644 index 000000000..f703d5c7e --- /dev/null +++ b/docs/limited_site_access.md @@ -0,0 +1,5 @@ +# Google Chrome/Brave Limited Site Access for Extensions + +Problem: MetaMask doesn't work with limited site access enabled under Chrome's extensions. + +Solution: In addition to the site you wish to whitelist, you must add 'api.infura.io' as another domain, so the MetaMask extension is authorized to make RPC calls to Infura. diff --git a/package-lock.json b/package-lock.json index 11eab5718..88f1832ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9759,8 +9759,8 @@ } }, "eth-contract-metadata": { - "version": "github:MetaMask/eth-contract-metadata#92e7d1442c7585bfd24e50a0fda78df11dedadfe", - "from": "github:MetaMask/eth-contract-metadata#92e7d1442c7585bfd24e50a0fda78df11dedadfe" + "version": "github:MetaMask/eth-contract-metadata#41a14e8004bdd37eaba5af5f2bb1fc4f4ff7063f", + "from": "github:MetaMask/eth-contract-metadata#41a14e8004bdd37eaba5af5f2bb1fc4f4ff7063f" }, "eth-ens-namehash": { "version": "2.0.8", @@ -9806,6 +9806,31 @@ "requires": { "bn.js": "^4.11.8", "ethereumjs-util": "^6.0.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz", + "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + } + } + }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" } } } @@ -9814,8 +9839,7 @@ "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" + "bn.js": "^4.11.8" } }, "ethereumjs-util": { @@ -9896,6 +9920,31 @@ "requires": { "bn.js": "^4.11.8", "ethereumjs-util": "^6.0.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz", + "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + } + } + }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" } } } @@ -9904,8 +9953,7 @@ "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" + "bn.js": "^4.11.8" } }, "ethereumjs-util": { @@ -10076,6 +10124,33 @@ "requires": { "bn.js": "^4.11.8", "ethereumjs-util": "^6.0.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz", + "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "dev": true, + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + } + } + }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "dev": true, + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" } } } @@ -10084,14 +10159,14 @@ "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" + "bn.js": "^4.11.8" } }, "ethereumjs-util": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "dev": true, "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", @@ -10192,8 +10267,7 @@ "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" + "bn.js": "^4.11.8" } }, "ethereumjs-util": { @@ -10502,8 +10576,7 @@ "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" + "bn.js": "^4.11.8" } }, "ethereumjs-util": { diff --git a/package.json b/package.json index 884c77387..c0355d12c 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ "test:integration:build": "gulp build:scss", "test:e2e:drizzle:beta": "SELENIUM_BROWSER=chrome test/e2e/beta/run-drizzle.sh", "test:e2e:chrome": "SELENIUM_BROWSER=chrome test/e2e/beta/run-all.sh", + "test:web3:chrome": "SELENIUM_BROWSER=chrome test/e2e/beta/run-web3.sh", + "test:web3:firefox": "SELENIUM_BROWSER=firefox test/e2e/beta/run-web3.sh", "test:e2e:firefox": "SELENIUM_BROWSER=firefox test/e2e/beta/run-all.sh", "test:screens": "shell-parallel -s 'npm run ganache:start' -x 'sleep 3 && npm run test:screens:run'", "test:screens:run": "node test/screens/new-ui.js", @@ -82,7 +84,7 @@ "ensnare": "^1.0.0", "eth-bin-to-ops": "^1.0.1", "eth-block-tracker": "^4.1.0", - "eth-contract-metadata": "github:MetaMask/eth-contract-metadata#92e7d1442c7585bfd24e50a0fda78df11dedadfe", + "eth-contract-metadata": "github:MetaMask/eth-contract-metadata#41a14e8004bdd37eaba5af5f2bb1fc4f4ff7063f", "eth-ens-namehash": "^2.0.8", "eth-hd-keyring": "^1.2.2", "eth-json-rpc-filters": "^3.0.1", diff --git a/test/e2e/beta/run-web3.sh b/test/e2e/beta/run-web3.sh new file mode 100755 index 000000000..9f77060de --- /dev/null +++ b/test/e2e/beta/run-web3.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + +export PATH="$PATH:./node_modules/.bin" + +shell-parallel -s 'static-server test/web3 --port 8080' -x 'sleep 5 && mocha test/e2e/beta/web3.spec'
\ No newline at end of file diff --git a/test/e2e/beta/web3.spec.js b/test/e2e/beta/web3.spec.js new file mode 100644 index 000000000..b3962c821 --- /dev/null +++ b/test/e2e/beta/web3.spec.js @@ -0,0 +1,365 @@ +const path = require('path') +const assert = require('assert') +const webdriver = require('selenium-webdriver') +const { By } = webdriver +const { + delay, + buildChromeWebDriver, + buildFirefoxWebdriver, + installWebExt, + getExtensionIdChrome, + getExtensionIdFirefox, +} = require('../func') +const { + checkBrowserForConsoleErrors, + closeAllWindowHandlesExcept, + findElement, + findElements, + openNewPage, + switchToWindowWithTitle, + verboseReportOnFailure, + waitUntilXWindowHandles, +} = require('./helpers') +const fetchMockResponses = require('./fetch-mocks.js') + + +describe('Using MetaMask with an existing account', function () { + let extensionId + let driver + + const testSeedPhrase = 'forum vessel pink push lonely enact gentle tail admit parrot grunt dress' + const regularDelayMs = 1000 + const largeDelayMs = regularDelayMs * 2 + + const button = async (x) => { + const buttoncheck = x + await buttoncheck.click() + await delay(largeDelayMs) + const [results] = await findElements(driver, By.css('#results')) + const resulttext = await results.getText() + var parsedData = JSON.parse(resulttext) + + return (parsedData) + + } + + this.timeout(0) + this.bail(true) + + before(async function () { + let extensionUrl + switch (process.env.SELENIUM_BROWSER) { + case 'chrome': { + const extensionPath = path.resolve('dist/chrome') + driver = buildChromeWebDriver(extensionPath) + extensionId = await getExtensionIdChrome(driver) + await delay(regularDelayMs) + extensionUrl = `chrome-extension://${extensionId}/home.html` + break + } + case 'firefox': { + const extensionPath = path.resolve('dist/firefox') + driver = buildFirefoxWebdriver() + await installWebExt(driver, extensionPath) + await delay(regularDelayMs) + extensionId = await getExtensionIdFirefox(driver) + extensionUrl = `moz-extension://${extensionId}/home.html` + break + } + } + // Depending on the state of the application built into the above directory (extPath) and the value of + // METAMASK_DEBUG we will see different post-install behaviour and possibly some extra windows. Here we + // are closing any extraneous windows to reset us to a single window before continuing. + const [tab1] = await driver.getAllWindowHandles() + await closeAllWindowHandlesExcept(driver, [tab1]) + await driver.switchTo().window(tab1) + await driver.get(extensionUrl) + }) + + beforeEach(async function () { + await driver.executeScript( + 'window.origFetch = window.fetch.bind(window);' + + 'window.fetch = ' + + '(...args) => { ' + + 'if (args[0] === "https://ethgasstation.info/json/ethgasAPI.json") { return ' + + 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.ethGasBasic + '\')) }); } else if ' + + '(args[0] === "https://ethgasstation.info/json/predictTable.json") { return ' + + 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.ethGasPredictTable + '\')) }); } else if ' + + '(args[0].match(/chromeextensionmm/)) { return ' + + 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.metametrics + '\')) }); } else if ' + + '(args[0] === "https://dev.blockscale.net/api/gasexpress.json") { return ' + + 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.gasExpress + '\')) }); } ' + + 'return window.origFetch(...args); };' + + 'function cancelInfuraRequest(requestDetails) {' + + 'console.log("Canceling: " + requestDetails.url);' + + 'return {' + + 'cancel: true' + + '};' + + ' }' + + 'window.chrome && window.chrome.webRequest && window.chrome.webRequest.onBeforeRequest.addListener(' + + 'cancelInfuraRequest,' + + '{urls: ["https://*.infura.io/*"]},' + + '["blocking"]' + + ');' + ) + }) + + afterEach(async function () { + if (process.env.SELENIUM_BROWSER === 'chrome') { + const errors = await checkBrowserForConsoleErrors(driver) + if (errors.length) { + const errorReports = errors.map(err => err.message) + const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` + console.error(new Error(errorMessage)) + } + } + if (this.currentTest.state === 'failed') { + await verboseReportOnFailure(driver, this.currentTest) + } + }) + + after(async function () { + await driver.quit() + }) + + describe('First time flow starting from an existing seed phrase', () => { + it('clicks the continue button on the welcome screen', async () => { + await findElement(driver, By.css('.welcome-page__header')) + const welcomeScreenBtn = await findElement(driver, By.css('.first-time-flow__button')) + welcomeScreenBtn.click() + await delay(largeDelayMs) + }) + + it('clicks the "Import Wallet" option', async () => { + const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Import Wallet')]`)) + customRpcButton.click() + await delay(largeDelayMs) + }) + + it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { + const optOutButton = await findElement(driver, By.css('.btn-default')) + optOutButton.click() + await delay(largeDelayMs) + }) + + it('imports a seed phrase', async () => { + const [seedTextArea] = await findElements(driver, By.css('textarea.first-time-flow__textarea')) + await seedTextArea.sendKeys(testSeedPhrase) + await delay(regularDelayMs) + + const [password] = await findElements(driver, By.id('password')) + await password.sendKeys('correct horse battery staple') + const [confirmPassword] = await findElements(driver, By.id('confirm-password')) + confirmPassword.sendKeys('correct horse battery staple') + + const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox')) + await tosCheckBox.click() + + const [importButton] = await findElements(driver, By.xpath(`//button[contains(text(), 'Import')]`)) + await importButton.click() + await delay(regularDelayMs) + }) + + it('clicks through the success screen', async () => { + await findElement(driver, By.xpath(`//div[contains(text(), 'Congratulations')]`)) + const doneButton = await findElement(driver, By.css('button.first-time-flow__button')) + await doneButton.click() + await delay(regularDelayMs) + }) + }) + + + describe('opens dapp', () => { + + it('switches to mainnet', async () => { + const networkDropdown = await findElement(driver, By.css('.network-name')) + await networkDropdown.click() + await delay(regularDelayMs) + + const [mainnet] = await findElements(driver, By.xpath(`//span[contains(text(), 'Main Ethereum Network')]`)) + await mainnet.click() + await delay(largeDelayMs * 2) + }) + + it('', async () => { + await openNewPage(driver, 'http://127.0.0.1:8080/') + await delay(regularDelayMs) + + await waitUntilXWindowHandles(driver, 3) + const windowHandles = await driver.getAllWindowHandles() + + const extension = windowHandles[0] + const popup = await switchToWindowWithTitle(driver, 'MetaMask Notification', windowHandles) + const dapp = windowHandles.find(handle => handle !== extension && handle !== popup) + + await delay(regularDelayMs) + const approveButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Connect')]`)) + await approveButton.click() + + await driver.switchTo().window(dapp) + await delay(regularDelayMs) + + + }) + }) + + describe('testing web3 methods', async () => { + + + it('testing hexa methods', async () => { + + + var List = await driver.findElements(By.className('hexaNumberMethods')) + + for (let i = 0; i < List.length; i++) { + try { + + var parsedData = await button(List[i]) + console.log(parsedData) + var result = parseInt(parsedData.result, 16) + + assert.equal((typeof result === 'number'), true) + await delay(regularDelayMs) + } catch (err) { + console.log(err) + assert(false) + + } + } + }) + + it('testing booleanMethods', async () => { + + var List = await driver.findElements(By.className('booleanMethods')) + + for (let i = 0; i < List.length; i++) { + try { + + var parsedData = await button(List[i]) + console.log(parsedData) + var result = parsedData.result + + assert.equal(result, false) + await delay(regularDelayMs) + } catch (err) { + console.log(err) + assert(false) + + + } + } + + }) + + it('testing transactionMethods', async () => { + + var List = await driver.findElements(By.className('transactionMethods')) + + for (let i = 0; i < List.length; i++) { + try { + + var parsedData = await button(List[i]) + + console.log(parsedData.result.blockHash) + + var result = [] + result.push(parseInt(parsedData.result.blockHash, 16)) + result.push(parseInt(parsedData.result.blockNumber, 16)) + result.push(parseInt(parsedData.result.gas, 16)) + result.push(parseInt(parsedData.result.gasPrice, 16)) + result.push(parseInt(parsedData.result.hash, 16)) + result.push(parseInt(parsedData.result.input, 16)) + result.push(parseInt(parsedData.result.nonce, 16)) + result.push(parseInt(parsedData.result.r, 16)) + result.push(parseInt(parsedData.result.s, 16)) + result.push(parseInt(parsedData.result.v, 16)) + result.push(parseInt(parsedData.result.to, 16)) + result.push(parseInt(parsedData.result.value, 16)) + + + result.forEach((value) => { + assert.equal((typeof value === 'number'), true) + }) + + + } catch (err) { + + console.log(err) + assert(false) + + + } + } + + }) + + it('testing blockMethods', async () => { + + var List = await driver.findElements(By.className('blockMethods')) + + for (let i = 0; i < List.length; i++) { + try { + + var parsedData = await button(List[i]) + console.log(JSON.stringify(parsedData) + i) + + console.log(parsedData.result.parentHash) + + var result = parseInt(parsedData.result.parentHash, 16) + + assert.equal((typeof result === 'number'), true) + await delay(regularDelayMs) + } catch (err) { + + console.log(err) + assert(false) + + + } + } + }) + + it('testing methods', async () => { + + var List = await driver.findElements(By.className('methods')) + var parsedData + var result + + for (let i = 0; i < List.length; i++) { + try { + + if (i === 2) { + + parsedData = await button(List[i]) + console.log(parsedData.result.blockHash) + + result = parseInt(parsedData.result.blockHash, 16) + + assert.equal((typeof result === 'number' || (result === 0)), true) + await delay(regularDelayMs) + } else { + parsedData = await button(List[i]) + console.log(parsedData.result) + + result = parseInt(parsedData.result, 16) + + assert.equal((typeof result === 'number' || (result === 0)), true) + await delay(regularDelayMs) + } + + + } catch (err) { + + console.log(err) + assert(false) + + + } + } + }) + + + }) + + + }) diff --git a/test/integration/lib/confirm-sig-requests.js b/test/integration/lib/confirm-sig-requests.js index e4540c4f2..c3b0dfcff 100644 --- a/test/integration/lib/confirm-sig-requests.js +++ b/test/integration/lib/confirm-sig-requests.js @@ -44,7 +44,7 @@ async function runConfirmSigRequestsTest (assert, done) { let confirmSigRowValue = await queryAsync($, '.request-signature__row-value') assert.equal(confirmSigRowValue[0].textContent, '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0') - let confirmSigSignButton = await queryAsync($, 'button.btn-primary.btn--large') + let confirmSigSignButton = await queryAsync($, 'button.btn-secondary.btn--large') confirmSigSignButton[0].click() await timeout(1000) confirmSigHeadline = await queryAsync($, '.request-signature__headline') @@ -53,7 +53,7 @@ async function runConfirmSigRequestsTest (assert, done) { confirmSigRowValue = await queryAsync($, '.request-signature__row-value') assert.ok(confirmSigRowValue[0].textContent.match(/^#\sTerms\sof\sUse/)) - confirmSigSignButton = await queryAsync($, 'button.btn-primary.btn--large') + confirmSigSignButton = await queryAsync($, 'button.btn-secondary.btn--large') confirmSigSignButton[0].click() await timeout(1000) confirmSigHeadline = await queryAsync($, '.request-signature__headline') @@ -63,7 +63,7 @@ async function runConfirmSigRequestsTest (assert, done) { assert.equal(confirmSigRowValue[0].textContent, 'Hi, Alice!') assert.equal(confirmSigRowValue[1].textContent, '1337') - confirmSigSignButton = await queryAsync($, 'button.btn-primary.btn--large') + confirmSigSignButton = await queryAsync($, 'button.btn-secondary.btn--large') confirmSigSignButton[0].click() await timeout(2000) diff --git a/test/integration/lib/send-new-ui.js b/test/integration/lib/send-new-ui.js index d7003f4cc..ce470fc02 100644 --- a/test/integration/lib/send-new-ui.js +++ b/test/integration/lib/send-new-ui.js @@ -43,7 +43,7 @@ async function runSendFlowTest (assert, done) { selectState.val('send new ui') reactTriggerChange(selectState[0]) - const sendScreenButton = await queryAsync($, 'button.btn-primary.transaction-view-balance__button') + const sendScreenButton = await queryAsync($, 'button.btn-secondary.transaction-view-balance__button') assert.ok(sendScreenButton[1], 'send screen button present') sendScreenButton[1].click() @@ -88,7 +88,7 @@ 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') - const sendButton = await queryAsync($, 'button.btn-primary.btn--large.page-container__footer-button') + const sendButton = await queryAsync($, 'button.btn-secondary.btn--large.page-container__footer-button') assert.equal(sendButton[0].textContent, 'Next', 'next button rendered') sendButton[0].click() await timeout() @@ -122,7 +122,7 @@ async function runSendFlowTest (assert, done) { sendAmountFieldInputInEdit.val('1.0') reactTriggerChange(sendAmountFieldInputInEdit[0]) - const sendButtonInEdit = await queryAsync($, '.btn-primary.btn--large.page-container__footer-button') + const sendButtonInEdit = await queryAsync($, '.btn-secondary.btn--large.page-container__footer-button') assert.equal(sendButtonInEdit[0].textContent, 'Next', 'next button in edit rendered') selectState.val('send new ui') diff --git a/test/web3/index.html b/test/web3/index.html new file mode 100644 index 000000000..cbc43290c --- /dev/null +++ b/test/web3/index.html @@ -0,0 +1,105 @@ +<html> + <head> + <title>Web3 Test Dapp</title> + </head> + <body> + <div style="display: flex; flex-flow: column;"> + <div style="display: flex; font-size: 1.25rem;">hexaNumberMethods</div> + <div style="display: flex;"> + <button id="eth_blockNumber" class="hexaNumberMethods">eth_blockNumber</button> + + <button id="eth_gasPrice" class="hexaNumberMethods">eth_gasPrice</button> + <button id="eth_newBlockFilter" class="hexaNumberMethods">eth_newBlockFilter</button> + <button id="eth_newPendingTransactionFilter" class="hexaNumberMethods"> + eth_newPendingTransactionFilter + </button> + <button id="eth_getUncleCountByBlockHash" class="hexaNumberMethods"> + eth_getUncleCountByBlockHash + </button> + <button id="eth_getBlockTransactionCountByHash" class="hexaNumberMethods"> + getBlockTransactionCountByHash + </button> + </div> + <div style="display: flex ;"> + <button id="eth_getTransactionCount" class="hexaNumberMethods">eth_getTransactionCount</button> + <button id="eth_getBalance" class="hexaNumberMethods">eth_getBalance</button> + <button id="eth_estimateGas" class="hexaNumberMethods">eth_estimateGas</button> + </div> + <div style="display: flex ;"> + + <button id="eth_getUncleCountByBlockNumber" class="hexaNumberMethods"> + eth_getUncleCountByBlockNumber + </button> + <button id='eth_getBlockTransactionCountByNumber' class="hexaNumberMethods"> + eth_getBlockTransactionCountByNumber + </button> + <button id="eth_protocolVersion" class="hexaNumberMethods">eth_protocolVersion</button> + + <button id="eth_getCode" class="hexaNumberMethods">eth_getCode</button> + </div> + </div> + <div style="display: flex; flex-flow: column;"> + <div style="display: flex; font-size: 1.25rem;">booleanMethods</div> + <div style="display: flex ;"> + <button id="eth_uninstallFilter" class = 'booleanMethods'>eth_uninstallFilter</button> + <button id="eth_mining" class = 'booleanMethods'>eth_mining</button> + <button id="eth_syncing" class = 'booleanMethods'>eth_syncing</button> + </div> + </div> + <div style="display: flex; flex-flow: column;"> + <div style="display: flex; font-size: 1.25rem;" >transactionMethods</div> + <div style="display: flex ;"> + <button id="eth_getTransactionByHash" class='transactionMethods'>eth_getTransactionByHash</button> + <button id="eth_getTransactionByBlockHashAndIndex" class = 'transactionMethods'> + eth_getTransactionByBlockHashAndIndex + </button> + <button id="eth_getTransactionByBlockNumberAndIndex" class="transactionMethods"> + eth_getTransactionByBlockNumberAndIndex + </button> + + + </div> + </div> + + <div style="display: flex; flex-flow: column;"> + <div style="display: flex; font-size: 1.25rem;">blockMethods</div> + + <div style="display: flex ;"> + + + <button id="eth_getUncleByBlockHashAndIndex" class="blockMethods"> + eth_getUncleByBlockHashAndIndex + </button> + <button id="eth_getBlockByHash" class="blockMethods">eth_getBlockByHash</button> + </div> + <div style="display: flex ;"> + <button id="eth_getBlockByNumber" class="blockMethods">eth_getBlockByNumber</button> + + + </div> + </div> + + <div style="display: flex; flex-flow: column;"> + <div style="display: flex; font-size: 1.25rem;">Methods</div> + <div style="display: flex ;"> + <button id="eth_call" class = 'methods'>eth_call</button> + <button id="eth_getStorageAt" class="methods">eth_getStorageAt</button> + <button id="eth_getTransactionReceipt" class="methods"> + eth_getTransactionReceipt + </button> + + </div> + </div> + <div style="display: flex; flex-flow: column;"> + <div id='results'></div> + </div> + + + + + </div> + <script src="schema.js"></script> + <script src="web3.js"></script> + + </body> +</html> diff --git a/test/web3/schema.js b/test/web3/schema.js new file mode 100644 index 000000000..61977f140 --- /dev/null +++ b/test/web3/schema.js @@ -0,0 +1,209 @@ +/* eslint no-unused-vars: 0 */ + +var params = { + // diffrent params used in the methods + param: [], + blockHashParams: '0xb3b20624f8f0f86eb50dd04688409e5cea4bd02d700bf6e79e9384d47d6a5a35', + filterParams: ['0xfe704947a3cd3ca12541458a4321c869'], + transactionHashParams: [ + '0xbb3a336e3f823ec18197f1e13ee875700f08f03e2cab75f0d0b118dabb44cba0', + ], + blockHashAndIndexParams: [ + '0xb3b20624f8f0f86eb50dd04688409e5cea4bd02d700bf6e79e9384d47d6a5a35', + '0x0', + ], + uncleByBlockNumberAndIndexParams: ['0x29c', '0x0'], + blockParameterParams: '0x5bad55', + data: '0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675', + addressParams: '0xc94770007dda54cF92009BFF0dE90c06F603a09f', + getStorageAtParams: [ + '0x295a70b2de5e3953354a6a8344e616ed314d7251', + '0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9', + '0x65a8db', + ], + getCodeParams: ['0x06012c8cf97bead5deae237070f9587f8e7a266d', '0x65a8db'], + estimateTransaction: { + from: '0xb60e8dd61c5d32be8058bb8eb970870f07233155', + to: '0xd46e8dd67c5d32be8058bb8eb970870f07244567', + gas: '0x76c0', + gasPrice: '0x9184e72a000', + value: '0x9184e72a', + data: '0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675', + }, + filterGetLogs: [{'blockHash': '0x7c5a35e9cb3e8ae0e221ab470abae9d446c3a5626ce6689fc777dcffcab52c70', 'topics': ['0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80']}], + block: { + __required: [], + number: 'Q', + hash: 'D32', + parentHash: 'D32', + nonce: 'D', + sha3Uncles: 'D', + logsBloom: 'D', + transactionsRoot: 'D', + stateRoot: 'D', + receiptsRoot: 'D', + miner: 'D', + difficulty: 'Q', + totalDifficulty: 'Q', + extraData: 'D', + size: 'Q', + gasLimit: 'Q', + gasUsed: 'Q', + timestamp: 'Q', + transactions: ['DATA|Transaction'], + uncles: ['D'], + }, + transaction: { + __required: [], + hash: 'D32', + nonce: 'Q', + blockHash: 'D32', + blockNumber: 'Q', + transactionIndex: 'Q', + from: 'D20', + to: 'D20', + value: 'Q', + gasPrice: 'Q', + gas: 'Q', + input: 'D', + }, + receipt: { + __required: [], + transactionHash: 'D32', + transactionIndex: 'Q', + blockHash: 'D32', + blockNumber: 'Q', + cumulativeGasUsed: 'Q', + gasUsed: 'Q', + contractAddress: 'D20', + logs: ['FilterChange'], + }, + + filterChange: { + __required: [], + removed: 'B', + logIndex: 'Q', + transactionIndex: 'Q', + transactionHash: 'D32', + blockHash: 'D32', + blockNumber: 'Q', + address: 'D20', + data: 'Array|DATA', + topics: ['D'], + }, +} + +var methods = { + hexaNumberMethods: { + // these are the methods which have output in the form of hexa decimal numbers + eth_blockNumber: ['eth_blockNumber', params.param, 'Q'], + eth_gasPrice: ['eth_gasPrice', params.param, 'Q'], + eth_newBlockFilter: ['eth_newBlockFilter', params.param, 'Q'], + eth_newPendingTransactionFilter: [ + 'eth_newPendingTransactionFilter', + params.param, + 'Q', + ], + eth_getUncleCountByBlockHash: [ + 'eth_getUncleCountByBlockHash', + [params.blockHashParams], + 'Q', + 1, + ], + eth_getBlockTransactionCountByHash: [ + 'eth_getBlockTransactionCountByHash', + [params.blockHashParams], + 'Q', + 1, + ], + eth_getTransactionCount: [ + 'eth_getTransactionCount', + [params.addressParams, params.blockParameterParams], + 'Q', + 1, + 2, + ], + eth_getBalance: ['eth_getBalance', [params.addressParams, 'latest'], 'Q', 1, 2], + eth_estimateGas: ['eth_estimateGas', [params.estimateTransaction], 'Q', 1], + eth_getUncleCountByBlockNumber: [ + 'eth_getUncleCountByBlockNumber', + [params.blockParameterParams], + 'Q', + 1, + ], + eth_getBlockTransactionCountByNumber: [ + 'eth_getBlockTransactionCountByNumber', + ['latest'], + 'Q', + 1, + ], + eth_protocolVersion: ['eth_protocolVersion', params.param, 'S'], + eth_getCode: ['eth_getCode', params.getCodeParams, 'D', 1, 2], + }, + booleanMethods: { + // these are the methods which have output in the form of boolean + eth_uninstallFilter: ['eth_uninstallFilter', params.filterParams, 'B', 1], + eth_mining: ['eth_mining', params.param, 'B'], + eth_syncing: ['eth_syncing', params.param, 'B|EthSyncing'], + }, + transactionMethods: { + // these are the methods which have output in the form of transaction object + eth_getTransactionByHash: [ + 'eth_getTransactionByHash', + params.transactionHashParams, + params.transaction, + 1, + ], + eth_getTransactionByBlockHashAndIndex: [ + 'eth_getTransactionByBlockHashAndIndex', + params.blockHashAndIndexParams, + params.transaction, + 2, + ], + eth_getTransactionByBlockNumberAndIndex: [ + 'eth_getTransactionByBlockNumberAndIndex', + [params.blockParameterParams, '0x0'], + params.transaction, + 2, + ], + + }, + blockMethods: { + // these are the methods which have output in the form of a block + + eth_getUncleByBlockNumberAndIndex: [ + 'eth_getUncleByBlockNumberAndIndex', + params.uncleByBlockNumberAndIndexParams, + params.block, + 2, + ], + eth_getBlockByHash: [ + 'eth_getBlockByHash', + [params.params, false], + params.block, + 2, + ], + eth_getBlockByNumber: [ + 'eth_getBlockByNumber', + [params.blockParameterParams, false], + params.block, + 2, + ], + }, + + methods: { + // these are the methods which have output in the form of bytes data + + eth_call: ['eth_call', [params.estimateTransaction, 'latest'], 'D', 1, 2], + eth_getStorageAt: ['eth_getStorageAt', params.getStorageAtParams, 'D', 2, 2], + eth_getTransactionReceipt: [ + 'eth_getTransactionReceipt', + params.transactionHashParams, + params.receipt, + 1, + ], + + }, + +} + diff --git a/test/web3/web3.js b/test/web3/web3.js new file mode 100644 index 000000000..5c2de078d --- /dev/null +++ b/test/web3/web3.js @@ -0,0 +1,34 @@ +/* eslint no-undef: 0 */ + +var json = methods + +web3.currentProvider.enable().then(() => { + + Object.keys(json).forEach(methodGroupKey => { + + console.log(methodGroupKey) + const methodGroup = json[methodGroupKey] + console.log(methodGroup) + Object.keys(methodGroup).forEach(methodKey => { + + const methodButton = document.getElementById(methodKey) + methodButton.addEventListener('click', function (event) { + + window.ethereum.sendAsync({ + method: methodKey, + params: methodGroup[methodKey][1], + }, function (err, result) { + if (err) { + console.log(err) + console.log(methodKey) + } else { + document.getElementById('results').innerHTML = JSON.stringify(result) + } + }) + }) + + }) + + }) + }) + diff --git a/ui/app/components/app/add-token-button/index.scss b/ui/app/components/app/add-token-button/index.scss index 39f404716..c4350a2d3 100644 --- a/ui/app/components/app/add-token-button/index.scss +++ b/ui/app/components/app/add-token-button/index.scss @@ -17,10 +17,7 @@ } &__button { - font-size: 0.75rem; + @extend %small-link; margin: 1rem; - text-transform: uppercase; - color: $curious-blue; - cursor: pointer; } } diff --git a/ui/app/components/app/coinbase-form.js b/ui/app/components/app/coinbase-form.js deleted file mode 100644 index 24d287604..000000000 --- a/ui/app/components/app/coinbase-form.js +++ /dev/null @@ -1,69 +0,0 @@ -const Component = require('react').Component -const PropTypes = require('prop-types') -const h = require('react-hyperscript') -const inherits = require('util').inherits -const connect = require('react-redux').connect -const actions = require('../../store/actions') - -CoinbaseForm.contextTypes = { - t: PropTypes.func, -} - -module.exports = connect(mapStateToProps)(CoinbaseForm) - - -function mapStateToProps (state) { - return { - warning: state.appState.warning, - } -} - -inherits(CoinbaseForm, Component) - -function CoinbaseForm () { - Component.call(this) -} - -CoinbaseForm.prototype.render = function () { - var props = this.props - - return h('.flex-column', { - style: { - marginTop: '35px', - padding: '25px', - width: '100%', - }, - }, [ - h('.flex-row', { - style: { - justifyContent: 'space-around', - margin: '33px', - marginTop: '0px', - }, - }, [ - h('button.btn-green', { - onClick: this.toCoinbase.bind(this), - }, this.context.t('continueToCoinbase')), - - h('button.btn-red', { - onClick: () => props.dispatch(actions.goHome()), - }, this.context.t('cancel')), - ]), - ]) -} - -CoinbaseForm.prototype.toCoinbase = function () { - const props = this.props - const address = props.buyView.buyAddress - props.dispatch(actions.buyEth({ network: '1', address, amount: 0 })) -} - -CoinbaseForm.prototype.renderLoading = function () { - return h('img', { - style: { - width: '27px', - marginRight: '-27px', - }, - src: 'images/loading.svg', - }) -} diff --git a/ui/app/components/app/customize-gas-modal/index.js b/ui/app/components/app/customize-gas-modal/index.js index dca77bb00..4434b8c25 100644 --- a/ui/app/components/app/customize-gas-modal/index.js +++ b/ui/app/components/app/customize-gas-modal/index.js @@ -382,7 +382,7 @@ CustomizeGasModal.prototype.render = function () { onClick: this.props.hideModal, }, [this.context.t('cancel')]), h(Button, { - type: 'primary', + type: 'secondary', className: 'send-v2__customize-gas__save', onClick: () => !error && this.save(newGasPrice, gasLimit, gasTotal), disabled: error, diff --git a/ui/app/components/app/modal/modal.component.js b/ui/app/components/app/modal/modal.component.js index 49e131b3c..44b180ac8 100644 --- a/ui/app/components/app/modal/modal.component.js +++ b/ui/app/components/app/modal/modal.component.js @@ -20,7 +20,7 @@ export default class Modal extends PureComponent { } static defaultProps = { - submitType: 'primary', + submitType: 'secondary', cancelType: 'default', } diff --git a/ui/app/components/app/modal/tests/modal.component.test.js b/ui/app/components/app/modal/tests/modal.component.test.js index a13d7c06a..5922177a6 100644 --- a/ui/app/components/app/modal/tests/modal.component.test.js +++ b/ui/app/components/app/modal/tests/modal.component.test.js @@ -12,7 +12,7 @@ describe('Modal Component', () => { assert.equal(wrapper.find('.modal-container').length, 1) const buttons = wrapper.find(Button) assert.equal(buttons.length, 1) - assert.equal(buttons.at(0).props().type, 'primary') + assert.equal(buttons.at(0).props().type, 'secondary') }) it('should render a modal with a cancel and a submit button', () => { @@ -38,7 +38,7 @@ describe('Modal Component', () => { cancelButton.simulate('click') assert.equal(handleCancel.callCount, 1) - assert.equal(submitButton.props().type, 'primary') + assert.equal(submitButton.props().type, 'secondary') assert.equal(submitButton.props().children, 'Submit') assert.equal(handleSubmit.callCount, 0) submitButton.simulate('click') diff --git a/ui/app/components/app/modals/account-details-modal.js b/ui/app/components/app/modals/account-details-modal.js index 94ed04df9..1b1ca6b8e 100644 --- a/ui/app/components/app/modals/account-details-modal.js +++ b/ui/app/components/app/modals/account-details-modal.js @@ -84,7 +84,7 @@ AccountDetailsModal.prototype.render = function () { h('div.account-modal-divider'), h(Button, { - type: 'primary', + type: 'secondary', className: 'account-modal__button', onClick: () => global.platform.openWindow({ url: genAccountLink(address, network) }), }, this.context.t('etherscanView')), @@ -92,7 +92,7 @@ AccountDetailsModal.prototype.render = function () { // Holding on redesign for Export Private Key functionality exportPrivateKeyFeatureEnabled ? h(Button, { - type: 'primary', + type: 'secondary', className: 'account-modal__button', onClick: () => showExportPrivateKeyModal(), }, this.context.t('exportPrivateKey')) : null, diff --git a/ui/app/components/app/modals/customize-gas/customize-gas.component.js b/ui/app/components/app/modals/customize-gas/customize-gas.component.js index 5db5c79e7..178f45729 100644 --- a/ui/app/components/app/modals/customize-gas/customize-gas.component.js +++ b/ui/app/components/app/modals/customize-gas/customize-gas.component.js @@ -128,7 +128,7 @@ export default class CustomizeGas extends Component { { t('cancel') } </Button> <Button - type="primary" + type="secondary" className="customize-gas__save" onClick={() => { metricsEvent({ diff --git a/ui/app/components/app/modals/deposit-ether-modal.js b/ui/app/components/app/modals/deposit-ether-modal.js index 6f622a17c..e4ab7eba1 100644 --- a/ui/app/components/app/modals/deposit-ether-modal.js +++ b/ui/app/components/app/modals/deposit-ether-modal.js @@ -119,7 +119,7 @@ DepositEtherModal.prototype.renderRow = function ({ !hideButton && h('div.deposit-ether-modal__buy-row__button', [ h(Button, { - type: 'primary', + type: 'secondary', className: 'deposit-ether-modal__deposit-button', large: true, onClick: onButtonClick, diff --git a/ui/app/components/app/modals/edit-account-name-modal.js b/ui/app/components/app/modals/edit-account-name-modal.js index 41a9862e9..aa21765c4 100644 --- a/ui/app/components/app/modals/edit-account-name-modal.js +++ b/ui/app/components/app/modals/edit-account-name-modal.js @@ -66,7 +66,7 @@ EditAccountNameModal.prototype.render = function () { value: this.state.inputText, }, []), - h('button.btn-clear.edit-account-name-modal-save-button.allcaps', { + h('button.button.btn-secondary.edit-account-name-modal-save-button.allcaps', { onClick: () => { if (this.state.inputText.length !== 0) { setAccountLabel(identity.address, this.state.inputText) diff --git a/ui/app/components/app/modals/export-private-key-modal.js b/ui/app/components/app/modals/export-private-key-modal.js index 639887d4c..70987330a 100644 --- a/ui/app/components/app/modals/export-private-key-modal.js +++ b/ui/app/components/app/modals/export-private-key-modal.js @@ -110,14 +110,14 @@ ExportPrivateKeyModal.prototype.renderButtons = function (privateKey, password, (privateKey ? ( h(Button, { - type: 'primary', + type: 'secondary', large: true, className: 'export-private-key__button', onClick: () => hideModal(), }, this.context.t('done')) ) : ( h(Button, { - type: 'primary', + type: 'secondary', large: true, className: 'export-private-key__button', onClick: () => this.exportAccountAndGetPrivateKey(this.state.password, address), diff --git a/ui/app/components/app/modals/hide-token-confirmation-modal.js b/ui/app/components/app/modals/hide-token-confirmation-modal.js index 8a9a48fd2..e2b098923 100644 --- a/ui/app/components/app/modals/hide-token-confirmation-modal.js +++ b/ui/app/components/app/modals/hide-token-confirmation-modal.js @@ -67,12 +67,12 @@ HideTokenConfirmationModal.prototype.render = function () { ]), h('div.hide-token-confirmation__buttons', {}, [ - h('button.btn-cancel.hide-token-confirmation__button.allcaps', { + h('button.btn-default.hide-token-confirmation__button.btn--large', { onClick: () => hideModal(), }, [ this.context.t('cancel'), ]), - h('button.btn-clear.hide-token-confirmation__button.allcaps', { + h('button.btn-secondary.hide-token-confirmation__button.btn--large', { onClick: () => hideToken(address), }, [ this.context.t('hide'), diff --git a/ui/app/components/app/modals/notification-modal.js b/ui/app/components/app/modals/notification-modal.js index 2d73b2cfa..b8503ec1a 100644 --- a/ui/app/components/app/modals/notification-modal.js +++ b/ui/app/components/app/modals/notification-modal.js @@ -37,11 +37,11 @@ class NotificationModal extends Component { showButtons && h('div.notification-modal__buttons', [ - showCancelButton && h('div.btn-cancel.notification-modal__buttons__btn', { + showCancelButton && h('div.btn-default.notification-modal__buttons__btn', { onClick: hideModal, }, 'Cancel'), - showConfirmButton && h('div.btn-clear.notification-modal__buttons__btn', { + showConfirmButton && h('div.button.btn-secondary.notification-modal__buttons__btn', { onClick: () => { onConfirm() hideModal() diff --git a/ui/app/components/app/send/send.container.js b/ui/app/components/app/send/send.container.js index e65463b93..303639c76 100644 --- a/ui/app/components/app/send/send.container.js +++ b/ui/app/components/app/send/send.container.js @@ -2,6 +2,10 @@ import { connect } from 'react-redux' import SendEther from './send.component' import { withRouter } from 'react-router-dom' import { compose } from 'recompose' +const { + getSelectedAddress, +} = require('../../../selectors/selectors') + import { getAmountConversionRate, getBlockGasLimit, @@ -12,7 +16,6 @@ import { getGasTotal, getPrimaryCurrency, getRecentBlocks, - getSelectedAddress, getSelectedToken, getSelectedTokenContract, getSelectedTokenToFiatRate, diff --git a/ui/app/components/app/send/send.selectors.js b/ui/app/components/app/send/send.selectors.js index 2ec677ad1..6056dea21 100644 --- a/ui/app/components/app/send/send.selectors.js +++ b/ui/app/components/app/send/send.selectors.js @@ -5,6 +5,7 @@ const { } = require('../../../helpers/utils/conversion-util') const { getMetaMaskAccounts, + getSelectedAddress, } = require('../../../selectors/selectors') const { estimateGasPriceFromRecentBlocks, @@ -33,7 +34,6 @@ const selectors = { getPrimaryCurrency, getRecentBlocks, getSelectedAccount, - getSelectedAddress, getSelectedIdentity, getSelectedToken, getSelectedTokenContract, @@ -149,12 +149,6 @@ function getSelectedAccount (state) { return accounts[selectedAddress] } -function getSelectedAddress (state) { - const selectedAddress = state.metamask.selectedAddress || Object.keys(getMetaMaskAccounts(state))[0] - - return selectedAddress -} - function getSelectedIdentity (state) { const selectedAddress = getSelectedAddress(state) const identities = state.metamask.identities @@ -246,9 +240,7 @@ function getSendTo (state) { function getSendToAccounts (state) { const fromAccounts = accountsWithSendEtherInfoSelector(state) const addressBookAccounts = getAddressBook(state) - const allAccounts = [...fromAccounts, ...addressBookAccounts] - // TODO: figure out exactly what the below returns and put a descriptive variable name on it - return Object.entries(allAccounts).map(([key, account]) => account) + return [...fromAccounts, ...addressBookAccounts] } function getSendWarnings (state) { diff --git a/ui/app/components/app/send/tests/send-container.test.js b/ui/app/components/app/send/tests/send-container.test.js index 9538b67b3..9d7365ac9 100644 --- a/ui/app/components/app/send/tests/send-container.test.js +++ b/ui/app/components/app/send/tests/send-container.test.js @@ -35,7 +35,6 @@ proxyquire('../send.container.js', { getGasTotal: (s) => `mockGasTotal:${s}`, getPrimaryCurrency: (s) => `mockPrimaryCurrency:${s}`, getRecentBlocks: (s) => `mockRecentBlocks:${s}`, - getSelectedAddress: (s) => `mockSelectedAddress:${s}`, getSelectedToken: (s) => `mockSelectedToken:${s}`, getSelectedTokenContract: (s) => `mockTokenContract:${s}`, getSelectedTokenToFiatRate: (s) => `mockTokenToFiatRate:${s}`, @@ -47,11 +46,15 @@ proxyquire('../send.container.js', { getTokenBalance: (s) => `mockTokenBalance:${s}`, getQrCodeData: (s) => `mockQrCodeData:${s}`, }, + '../../../selectors/selectors': { + getSelectedAddress: (s) => `mockSelectedAddress:${s}`, + }, '../../../store/actions': actionSpies, '../../../ducks/send/send.duck': duckActionSpies, './send.utils.js': { calcGasTotal: (gasLimit, gasPrice) => gasLimit + gasPrice, }, + }) describe('send container', () => { diff --git a/ui/app/components/app/send/tests/send-selectors.test.js b/ui/app/components/app/send/tests/send-selectors.test.js index cdc86fe59..ccc126795 100644 --- a/ui/app/components/app/send/tests/send-selectors.test.js +++ b/ui/app/components/app/send/tests/send-selectors.test.js @@ -20,7 +20,6 @@ const { getPrimaryCurrency, getRecentBlocks, getSelectedAccount, - getSelectedAddress, getSelectedIdentity, getSelectedToken, getSelectedTokenContract, @@ -274,14 +273,6 @@ describe('send selectors', () => { }) }) - describe('getSelectedAddress()', () => { - it('should', () => { - assert.equal( - getSelectedAddress(mockState), - '0xd85a4b6a394794842887b8284293d69163007bbb' - ) - }) - }) describe('getSelectedIdentity()', () => { it('should return the identity object of the currently selected address', () => { diff --git a/ui/app/components/app/shapeshift-form.js b/ui/app/components/app/shapeshift-form.js index 11459fd5e..34a6f3acd 100644 --- a/ui/app/components/app/shapeshift-form.js +++ b/ui/app/components/app/shapeshift-form.js @@ -245,7 +245,7 @@ ShapeshiftForm.prototype.render = function () { ]), !depositAddress && h(Button, { - type: 'primary', + type: 'secondary', large: true, className: `${btnClass} shapeshift-form__shapeshift-buy-btn`, disabled: !token, diff --git a/ui/app/components/app/signature-request.js b/ui/app/components/app/signature-request.js index e47791b67..fa237f1d1 100644 --- a/ui/app/components/app/signature-request.js +++ b/ui/app/components/app/signature-request.js @@ -311,7 +311,7 @@ SignatureRequest.prototype.renderFooter = function () { }, }, this.context.t('cancel')), h(Button, { - type: 'primary', + type: 'secondary', large: true, className: 'request-signature__footer__sign-button', onClick: event => { diff --git a/ui/app/components/app/transaction-view-balance/transaction-view-balance.component.js b/ui/app/components/app/transaction-view-balance/transaction-view-balance.component.js index fa63b6fd3..3f6abbb00 100644 --- a/ui/app/components/app/transaction-view-balance/transaction-view-balance.component.js +++ b/ui/app/components/app/transaction-view-balance/transaction-view-balance.component.js @@ -87,7 +87,7 @@ export default class TransactionViewBalance extends PureComponent { { !selectedToken && ( <Button - type="primary" + type="secondary" className="transaction-view-balance__button" onClick={() => { metricsEvent({ @@ -105,7 +105,7 @@ export default class TransactionViewBalance extends PureComponent { ) } <Button - type="primary" + type="secondary" className="transaction-view-balance__button" onClick={() => { metricsEvent({ diff --git a/ui/app/components/app/wallet-view.js b/ui/app/components/app/wallet-view.js index cec8228b1..b8bae5421 100644 --- a/ui/app/components/app/wallet-view.js +++ b/ui/app/components/app/wallet-view.js @@ -190,7 +190,7 @@ WalletView.prototype.render = function () { identities[selectedAddress].name, ]), - h('button.btn-clear.wallet-view__details-button.allcaps', this.context.t('details')), + h('button.btn-secondary.wallet-view__details-button', this.context.t('details')), ]), ]), diff --git a/ui/app/components/ui/button/button.component.js b/ui/app/components/ui/button/button.component.js index 5d19219b4..01d946927 100644 --- a/ui/app/components/ui/button/button.component.js +++ b/ui/app/components/ui/button/button.component.js @@ -17,6 +17,10 @@ const typeHash = { confirm: CLASSNAME_CONFIRM, raised: CLASSNAME_RAISED, 'first-time': CLASSNAME_FIRST_TIME, + warning: 'btn-warning', + danger: 'btn-danger', + 'danger-primary': 'btn-danger-primary', + link: 'btn-link', } export default class Button extends Component { diff --git a/ui/app/components/ui/button/button.stories.js b/ui/app/components/ui/button/button.stories.js index 667824a47..9df53439d 100644 --- a/ui/app/components/ui/button/button.stories.js +++ b/ui/app/components/ui/button/button.stories.js @@ -2,57 +2,70 @@ import React from 'react' import { storiesOf } from '@storybook/react' import { action } from '@storybook/addon-actions' import Button from '.' -import { text } from '@storybook/addon-knobs/react' +import { text, boolean } from '@storybook/addon-knobs/react' +// ', 'secondary', 'default', 'warning', 'danger', 'danger-primary', 'link'], 'primary')} storiesOf('Button', module) - .add('primary', () => + .add('Button - Primary', () => <Button onClick={action('clicked')} type="primary" + disabled={boolean('disabled', false)} > {text('text', 'Click me')} </Button> ) - .add('secondary', () => + .add('Button - Secondary', () => <Button onClick={action('clicked')} type="secondary" + disabled={boolean('disabled', false)} > {text('text', 'Click me')} </Button> ) - .add('default', () => ( + .add('Button - Default', () => <Button onClick={action('clicked')} type="default" + disabled={boolean('disabled', false)} > {text('text', 'Click me')} </Button> - )) - .add('large primary', () => ( + ) + .add('Button - Warning', () => <Button onClick={action('clicked')} - type="primary" - large + type="warning" + disabled={boolean('disabled', false)} > {text('text', 'Click me')} </Button> - )) - .add('large secondary', () => ( + ) + .add('Button - Danger', () => <Button onClick={action('clicked')} - type="secondary" - large + type="danger" + disabled={boolean('disabled', false)} > {text('text', 'Click me')} </Button> - )) - .add('large default', () => ( + ) + .add('Button - Danger Primary', () => <Button onClick={action('clicked')} - type="default" - large + type="danger-primary" + disabled={boolean('disabled', false)} > {text('text', 'Click me')} </Button> - )) + ) + .add('Button - Link', () => + <Button + onClick={action('clicked')} + type="link" + disabled={boolean('disabled', false)} + > + {text('text', 'Click me')} + </Button> + ) diff --git a/ui/app/components/ui/button/buttons.scss b/ui/app/components/ui/button/buttons.scss new file mode 100644 index 000000000..0fc87415b --- /dev/null +++ b/ui/app/components/ui/button/buttons.scss @@ -0,0 +1,244 @@ +/* + Buttons + */ + +$hover-secondary: #B0D7F2; +$hover-default: #B3B3B3; +$hover-confirm: #0372C3; +$hover-red: #FEB6BF; +$hover-red-primary: #C72837; +$hover-orange: #FFD3B5; + +%button { + @include h6; + + font-weight: 500; + font-family: Roboto, Arial; + line-height: 1.25rem; + padding: .75rem 1rem; + display: flex; + justify-content: center; + align-items: center; + box-sizing: border-box; + border-radius: 6px; + width: 100%; + outline: none; + transition: border-color .3s ease, background-color .3s ease; + + &--disabled, + &[disabled] { + cursor: auto; + opacity: .5; + pointer-events: none; + } +} + +%link { + @include h4; + + color: $Blue-500; + line-height: 1.25rem; + cursor: pointer; + background-color: transparent; + + &:hover { + color: $Blue-400; + } + + &:active { + color: $Blue-600; + } + + &--disabled, + &[disabled] { + cursor: auto; + opacity: 1; + pointer-events: none; + color: $hover-secondary; + } +} + +%small-link { + @extend %link; + @include h6; +} + +.button { + @extend %button; +} + +.btn-secondary { + color: $Blue-500; + border: 2px solid $hover-secondary; + + &:hover { + border-color: $Blue-500; + } + + &:active { + background: $Blue-000; + border-color: $Blue-500; + } + + &--disabled, + &[disabled] { + opacity: 1; + color: $hover-secondary; + } +} + +.btn-warning { + color: $Orange-500; + border: 2px solid $hover-orange; + + &:hover { + border-color: $Orange-500; + } + + &:active { + background: $Orange-000; + border-color: $Orange-500; + } + + &--disabled, + &[disabled] { + opacity: 1; + color: $hover-orange; + } +} + +.btn-danger { + color: $Red-500; + border: 2px solid $hover-red; + + &:hover { + border-color: $Red-500; + } + + &:active { + background: $Red-000; + border-color: $Red-500; + } + + &--disabled, + &[disabled] { + opacity: 1; + color: $hover-red; + } +} + +.btn-danger-primary { + color: $white; + border: 2px solid $Red-500; + background-color: $Red-500; + + &:hover { + border-color: $hover-red-primary; + background-color: $hover-red-primary; + } + + &:active { + background: $Red-600; + border-color: $Red-600; + } + + &--disabled, + &[disabled] { + opacity: 1; + border-color: $hover-red; + background-color: $hover-red; + } +} + +.btn-default { + color: $Grey-500; + border: 2px solid $hover-default; + + &:hover { + border-color: $Grey-500; + } + + &:active { + background: #FBFBFC; + border-color: $Grey-500; + } + + &--disabled, + &[disabled] { + opacity: 1; + color: $hover-default; + } +} + +.btn-primary { + color: $white; + border: 2px solid $Blue-500; + background-color: $Blue-500; + + &:hover { + border-color: $hover-confirm; + background-color: $hover-confirm; + } + + &:active { + background: $Blue-600; + border-color: $Blue-600; + } + + &--disabled, + &[disabled] { + border-color: $hover-secondary; + background-color: $hover-secondary; + } +} + +.btn-link { + @extend %link; +} + +.btn--large { + min-height: 54px; +} + +/** + All Buttons styles are deviations from design guide + */ + +.btn-raised { + color: $curious-blue; + background-color: $white; + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.08); + padding: 6px; + height: initial; + min-height: initial; + width: initial; + min-width: initial; +} + +.btn--first-time { + height: 54px; + width: 198px; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .14); + color: $white; + font-size: 1.25rem; + font-weight: 500; + transition: 200ms ease-in-out; + background-color: rgba(247, 134, 28, .9); + border-radius: 0; +} + +button[disabled], +input[type="submit"][disabled] { + cursor: not-allowed; + opacity: .5; +} + +button.primary { + padding: 8px 12px; + background: #f7861c; + box-shadow: 0 3px 6px rgba(247, 134, 28, .36); + color: $white; + font-size: 1.1em; + font-family: Roboto; + text-transform: uppercase; +} diff --git a/ui/app/components/ui/page-container/index.scss b/ui/app/components/ui/page-container/index.scss index b71a3cb9d..003c5a0e2 100644 --- a/ui/app/components/ui/page-container/index.scss +++ b/ui/app/components/ui/page-container/index.scss @@ -55,11 +55,6 @@ border-top: 1px solid $geyser; flex: 0 0 auto; - .btn-default, - .btn-confirm { - font-size: 1rem; - } - header { display: flex; flex-flow: row; @@ -86,9 +81,6 @@ } &__footer-button { - height: 55px; - font-size: 1rem; - text-transform: uppercase; margin-right: 16px; &:last-of-type { diff --git a/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js b/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js index 85b16cefe..4ef203521 100644 --- a/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js +++ b/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js @@ -45,7 +45,7 @@ export default class PageContainerFooter extends Component { </Button>} <Button - type={submitButtonType || 'primary'} + type={submitButtonType || 'secondary'} large className="page-container__footer-button" disabled={disabled} diff --git a/ui/app/css/itcss/components/buttons.scss b/ui/app/css/itcss/components/buttons.scss deleted file mode 100644 index 3e99d0ac6..000000000 --- a/ui/app/css/itcss/components/buttons.scss +++ /dev/null @@ -1,230 +0,0 @@ -/* - Buttons - */ - -.button { - min-height: 44px; - background: $white; - display: flex; - justify-content: center; - align-items: center; - box-sizing: border-box; - border-radius: 4px; - font-size: 14px; - font-weight: 400; - transition: border-color .3s ease; - padding: 0 16px; - min-width: 140px; - width: 100%; - text-transform: uppercase; - outline: none; - font-family: Roboto; - - &--disabled, - &[disabled] { - cursor: auto; - opacity: .5; - pointer-events: none; - } -} - -.btn-primary { - color: $curious-blue; - border: 2px solid $spindle; - - &:active { - background: $zumthor; - border-color: $curious-blue; - } - - &:hover { - border-color: $curious-blue; - } -} - -.btn-secondary { - color: $monzo; - border: 2px solid lighten($monzo, 40%); - - &:active { - background: lighten($monzo, 55%); - border-color: $monzo; - } - - &:hover { - border-color: $monzo; - } -} - -.btn-default { - color: $scorpion; - border: 2px solid $dusty-gray; - - &:active { - background: $gallery; - border-color: $dusty-gray; - } - - &:hover { - border-color: $scorpion; - } -} - -.btn-confirm { - color: $white; - border: 2px solid $curious-blue; - background-color: $curious-blue; -} - -.btn-raised { - color: $curious-blue; - background-color: $white; - box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.08); - padding: 6px; - height: initial; - min-height: initial; - width: initial; - min-width: initial; -} - -.btn--first-time { - height: 54px; - width: 198px; - box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .14); - color: $white; - font-size: 1.25rem; - font-weight: 500; - transition: 200ms ease-in-out; - background-color: rgba(247, 134, 28, .9); - border-radius: 0; -} - -.btn--large { - min-height: 54px; -} - -.btn-green { - background-color: #02c9b1; // TODO: reusable color in colors.css -} - -.btn-clear { - background: $white; - text-align: center; - padding: .8rem 1rem; - color: $curious-blue; - border: 2px solid $spindle; - border-radius: 4px; - font-size: .85rem; - font-weight: 400; - transition: border-color .3s ease; - - &:hover { - border-color: $curious-blue; - } - - &--disabled, - &[disabled] { - cursor: auto; - opacity: .5; - pointer-events: none; - } -} - -.btn-cancel { - background: $white; - text-align: center; - padding: .9rem 1rem; - color: $scorpion; - border: 2px solid $dusty-gray; - border-radius: 4px; - font-size: .85rem; - font-weight: 400; - transition: border-color .3s ease; - width: 100%; - - &:hover { - border-color: $scorpion; - } -} - -// No longer used in flat design, remove when modal buttons done -// div.wallet-btn { -// border: 1px solid rgb(91, 93, 103); -// border-radius: 2px; -// height: 30px; -// width: 75px; -// font-size: 0.8em; -// text-align: center; -// line-height: 25px; -// } - -// .btn-red { -// background: rgba(254, 35, 17, 1); -// box-shadow: 0px 3px 6px rgba(254, 35, 17, 0.36); -// } - -button[disabled], -input[type="submit"][disabled] { - cursor: not-allowed; - opacity: .5; - // background: rgba(197, 197, 197, 1); - // box-shadow: 0 3px 6px rgba(197, 197, 197, .36); -} - -// button.spaced { -// margin: 2px; -// } - -// button:not([disabled]):hover, input[type="submit"]:not([disabled]):hover { -// transform: scale(1.1); -// } -// button:not([disabled]):active, input[type="submit"]:not([disabled]):active { -// transform: scale(0.95); -// } - -button.primary { - padding: 8px 12px; - background: #f7861c; - box-shadow: 0 3px 6px rgba(247, 134, 28, .36); - color: $white; - font-size: 1.1em; - font-family: Roboto; - text-transform: uppercase; -} - -.btn-light { - padding: 8px 12px; - // background: #FFFFFF; // $bg-white - box-shadow: 0 3px 6px rgba(247, 134, 28, .36); - color: #585d67; // TODO: make reusable light button color - font-size: 1.1em; - font-family: Roboto; - text-transform: uppercase; - text-align: center; - line-height: 20px; - border-radius: 2px; - border: 1px solid #979797; // #TODO: make reusable light border color - opacity: .5; -} - -// TODO: cleanup: not used anywhere -button.btn-thin { - border: 1px solid; - border-color: #4d4d4d; - color: #4d4d4d; - background: rgb(255, 174, 41); - border-radius: 4px; - min-width: 200px; - margin: 12px 0; - padding: 6px; - font-size: 13px; -} - -.btn-tertiary { - border: 1px solid transparent; - border-radius: 2px; - background-color: transparent; - font-size: 16px; - line-height: 24px; - padding: 16px 42px; -} diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index f2f37bfa3..3d426a33c 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -1,4 +1,4 @@ -@import './buttons.scss'; +@import '../../../components/ui/button/buttons'; @import './footer.scss'; diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss index 42ef7ae0a..9c0a5cf61 100644 --- a/ui/app/css/itcss/components/modal.scss +++ b/ui/app/css/itcss/components/modal.scss @@ -538,6 +538,8 @@ } &__button { + @include paragraph; + @extend %button; width: 141px; margin: 0 5px; } diff --git a/ui/app/css/itcss/generic/index.scss b/ui/app/css/itcss/generic/index.scss index d8e62c97a..8b282aa1e 100644 --- a/ui/app/css/itcss/generic/index.scss +++ b/ui/app/css/itcss/generic/index.scss @@ -18,6 +18,7 @@ body { height: 100%; margin: 0; padding: 0; + font-size: 16px; @media screen and (max-width: $break-small) { overflow-y: overlay; diff --git a/ui/app/css/itcss/settings/typography.scss b/ui/app/css/itcss/settings/typography.scss index 18c444c8a..93107a106 100644 --- a/ui/app/css/itcss/settings/typography.scss +++ b/ui/app/css/itcss/settings/typography.scss @@ -403,3 +403,40 @@ font-weight: 400; font-style: normal; } + +@mixin fontScale($weight: 400, $size: 1rem) { + font-weight: $weight; + font-size: $size; +} + +@mixin h1($weight: 400, $size: 2.5rem){ + @include fontScale($weight, $size); +} + +@mixin h2($weight: 400, $size: 2rem){ + @include fontScale($weight, $size); +} + +@mixin h3($weight: 400, $size: 1.5rem){ + @include fontScale($weight, $size); +} + +@mixin h4($weight: 400, $size: 1.125rem){ + @include fontScale($weight, $size); +} + +@mixin h5($weight: 400, $size: 1rem){ + @include fontScale($weight, $size); +} + +@mixin h6($weight: 400, $size: .875rem){ + @include fontScale($weight, $size); +} + +@mixin h7($weight: 400, $size: .75rem){ + @include fontScale($weight, $size); +} + +@mixin paragraph($weight: 400, $size: 1rem){ + @include fontScale($weight, $size); +} diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/app/css/itcss/settings/variables.scss index 89bd8b96a..f7003b1f4 100644 --- a/ui/app/css/itcss/settings/variables.scss +++ b/ui/app/css/itcss/settings/variables.scss @@ -26,7 +26,7 @@ $dusty-gray: #9b9b9b; $alto: #dedede; $alabaster: #fafafa; $silver-chalice: #aeaeae; -$curious-blue: #2f9ae0; +$curious-blue: #037DD6; $concrete: #f3f3f3; $tundora: #4d4d4d; $nile-blue: #1b344d; @@ -93,3 +93,19 @@ $break-large: 576px; $primary-font-type: Roboto; +$Blue-000: #eaf6ff; +$Blue-400: #1098fc; +$Blue-500: #037DD6; +$Blue-600: #0260a4; + +$Grey-000: #f2f3f4; +$Grey-500: #6A737D; + +$Red-000: #fcf2f3; +$Red-500: #D73A49; +$Red-600: #b92534; + +$Orange-000: #fef5ef; +$Orange-500: #F66A0A; + + diff --git a/ui/app/helpers/utils/transactions.util.js b/ui/app/helpers/utils/transactions.util.js index cb6c9536c..8d96b1487 100644 --- a/ui/app/helpers/utils/transactions.util.js +++ b/ui/app/helpers/utils/transactions.util.js @@ -30,6 +30,21 @@ export function getTokenData (data = '') { return abiDecoder.decodeMethod(data) } +async function getMethodFrom4Byte (fourBytePrefix) { + const fourByteResponse = (await fetch(`https://www.4byte.directory/api/v1/signatures/?hex_signature=${fourBytePrefix}`, { + referrerPolicy: 'no-referrer-when-downgrade', + body: null, + method: 'GET', + mode: 'cors', + })).json() + + if (fourByteResponse.count === 1) { + return fourByteResponse.results[0].text_signature + } else { + return null + } +} + const registry = new MethodRegistry({ provider: global.ethereumProvider }) /** @@ -43,7 +58,16 @@ const registry = new MethodRegistry({ provider: global.ethereumProvider }) const fourBytePrefix = prefixedData.slice(0, 10) try { - const sig = await registry.lookup(fourBytePrefix) + const fourByteSig = getMethodFrom4Byte(fourBytePrefix).catch((e) => { + log.error(e) + return null + }) + + let sig = await registry.lookup(fourBytePrefix) + + if (!sig) { + sig = await fourByteSig + } if (!sig) { return {} @@ -57,8 +81,8 @@ const registry = new MethodRegistry({ provider: global.ethereumProvider }) } } catch (error) { log.error(error) - const contractData = getTokenData(data) - const { name } = contractData || {} + const tokenData = getTokenData(data) + const { name } = tokenData || {} return { name } } diff --git a/ui/app/pages/add-token/token-list/token-list-placeholder/index.scss b/ui/app/pages/add-token/token-list/token-list-placeholder/index.scss index cc495dfb0..a363c77c5 100644 --- a/ui/app/pages/add-token/token-list/token-list-placeholder/index.scss +++ b/ui/app/pages/add-token/token-list/token-list-placeholder/index.scss @@ -18,6 +18,7 @@ } &__link { - color: $curious-blue; + @extend %link; + margin-top: .5rem; } } diff --git a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js index 7edb8f541..9a118a815 100644 --- a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js +++ b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js @@ -103,7 +103,7 @@ export default class ConfirmAddSuggestedToken extends Component { { this.context.t('cancel') } </Button> <Button - type="primary" + type="secondary" large className="page-container__footer-button" onClick={() => { diff --git a/ui/app/pages/confirm-add-token/confirm-add-token.component.js b/ui/app/pages/confirm-add-token/confirm-add-token.component.js index c0ec624ac..f0a19e8d9 100644 --- a/ui/app/pages/confirm-add-token/confirm-add-token.component.js +++ b/ui/app/pages/confirm-add-token/confirm-add-token.component.js @@ -96,7 +96,7 @@ export default class ConfirmAddToken extends Component { { this.context.t('back') } </Button> <Button - type="primary" + type="secondary" large className="page-container__footer-button" onClick={() => { diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js index 5cafe91c9..63e63ce4a 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -543,7 +543,7 @@ export default class ConfirmTransactionBase extends Component { toName={toName} toAddress={toAddress} showEdit={onEdit && !isTxReprice} - action={this.context.t(actionKey) || getMethodName(name) || this.context.t('contractInteraction')} + action={actionKey && this.context.t(actionKey) || getMethodName(name) || this.context.t('contractInteraction')} title={title} titleComponent={this.renderTitleComponent()} subtitle={subtitle} diff --git a/ui/app/pages/create-account/connect-hardware/account-list.js b/ui/app/pages/create-account/connect-hardware/account-list.js index 617fb8833..a521c7eaf 100644 --- a/ui/app/pages/create-account/connect-hardware/account-list.js +++ b/ui/app/pages/create-account/connect-hardware/account-list.js @@ -152,7 +152,7 @@ class AccountList extends Component { }, [this.context.t('cancel')]), h(Button, { - type: 'confirm', + type: 'primary', large: true, className: 'new-account-connect-form__button unlock', disabled, diff --git a/ui/app/pages/create-account/connect-hardware/connect-screen.js b/ui/app/pages/create-account/connect-hardware/connect-screen.js index 7e9dee970..f5a83e6cf 100644 --- a/ui/app/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/pages/create-account/connect-hardware/connect-screen.js @@ -46,7 +46,7 @@ class ConnectScreen extends Component { this.renderConnectToTrezorButton(), ]), h(Button, { - type: 'confirm', + type: 'primary', large: true, className: 'hw-connect__connect-btn', onClick: this.connect, diff --git a/ui/app/pages/create-account/import-account/json.js b/ui/app/pages/create-account/import-account/json.js index 17bef763c..ad430ba58 100644 --- a/ui/app/pages/create-account/import-account/json.js +++ b/ui/app/pages/create-account/import-account/json.js @@ -61,7 +61,7 @@ class JsonImportSubview extends Component { }, [this.context.t('cancel')]), h(Button, { - type: 'primary', + type: 'secondary', large: true, className: 'new-account-create-form__button', onClick: () => this.createNewKeychain(), diff --git a/ui/app/pages/create-account/import-account/private-key.js b/ui/app/pages/create-account/import-account/private-key.js index 450614e87..0cdf25ce9 100644 --- a/ui/app/pages/create-account/import-account/private-key.js +++ b/ui/app/pages/create-account/import-account/private-key.js @@ -75,7 +75,7 @@ PrivateKeyImportView.prototype.render = function () { }, [this.context.t('cancel')]), h(Button, { - type: 'primary', + type: 'secondary', large: true, className: 'new-account-create-form__button', onClick: () => this.createNewKeychain(), diff --git a/ui/app/pages/create-account/new-account.js b/ui/app/pages/create-account/new-account.js index 316fbe6f1..d19e6bc38 100644 --- a/ui/app/pages/create-account/new-account.js +++ b/ui/app/pages/create-account/new-account.js @@ -47,7 +47,7 @@ class NewAccountCreateForm extends Component { }, [this.context.t('cancel')]), h(Button, { - type: 'primary', + type: 'secondary', large: true, className: 'new-account-create-form__button', onClick: () => { diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js index 96ff11eaf..5092d277e 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js @@ -261,7 +261,7 @@ export default class ImportWithSeedPhrase extends PureComponent { </span> </div> <Button - type="confirm" + type="primary" className="first-time-flow__button" disabled={!this.isValid() || !termsChecked} onClick={this.handleImport} diff --git a/ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js b/ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js index c040cff88..de073af2f 100644 --- a/ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js +++ b/ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js @@ -211,7 +211,7 @@ export default class NewAccount extends PureComponent { </span> </div> <Button - type="confirm" + type="primary" className="first-time-flow__button" disabled={!this.isValid() || !termsChecked} onClick={this.handleCreate} diff --git a/ui/app/pages/first-time-flow/create-password/unique-image/unique-image.component.js b/ui/app/pages/first-time-flow/create-password/unique-image/unique-image.component.js index 3434d117a..590cf0303 100644 --- a/ui/app/pages/first-time-flow/create-password/unique-image/unique-image.component.js +++ b/ui/app/pages/first-time-flow/create-password/unique-image/unique-image.component.js @@ -34,7 +34,7 @@ export default class UniqueImageScreen extends PureComponent { { t('protectYourKeysMessage2') } </div> <Button - type="confirm" + type="primary" className="first-time-flow__button" onClick={() => { this.context.metricsEvent({ diff --git a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js b/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js index c4292331b..83b0e7fc6 100644 --- a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js +++ b/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js @@ -71,7 +71,7 @@ export default class EndOfFlowScreen extends PureComponent { </a>. </div> <Button - type="confirm" + type="primary" className="first-time-flow__button" onClick={async () => { await completeOnboarding() diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js index 59b4f73a6..f3bfc3171 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js @@ -142,7 +142,7 @@ export default class ConfirmSeedPhrase extends PureComponent { } </div> <Button - type="confirm" + type="primary" className="first-time-flow__button" onClick={this.handleSubmit} disabled={!this.isValid()} diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js index ee352d74e..4e9948a0e 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js @@ -130,7 +130,7 @@ export default class RevealSeedPhrase extends PureComponent { </div> </div> <Button - type="confirm" + type="primary" className="first-time-flow__button" onClick={this.handleNext} disabled={!isShowingSeedPhrase} diff --git a/ui/app/pages/first-time-flow/select-action/select-action.component.js b/ui/app/pages/first-time-flow/select-action/select-action.component.js index b25a15514..5af29a505 100644 --- a/ui/app/pages/first-time-flow/select-action/select-action.component.js +++ b/ui/app/pages/first-time-flow/select-action/select-action.component.js @@ -95,7 +95,7 @@ export default class SelectAction extends PureComponent { </div> </div> <Button - type="confirm" + type="primary" className="first-time-flow__button" onClick={this.handleCreate} > diff --git a/ui/app/pages/first-time-flow/welcome/welcome.component.js b/ui/app/pages/first-time-flow/welcome/welcome.component.js index 3b8d6eb17..c720d2572 100644 --- a/ui/app/pages/first-time-flow/welcome/welcome.component.js +++ b/ui/app/pages/first-time-flow/welcome/welcome.component.js @@ -56,7 +56,7 @@ export default class Welcome extends PureComponent { <div>{ t('happyToSeeYou') }</div> </div> <Button - type="confirm" + type="primary" className="first-time-flow__button" onClick={this.handleContinue} > diff --git a/ui/app/pages/keychains/reveal-seed.js b/ui/app/pages/keychains/reveal-seed.js index edc9db5a0..e83e3fd98 100644 --- a/ui/app/pages/keychains/reveal-seed.js +++ b/ui/app/pages/keychains/reveal-seed.js @@ -116,7 +116,7 @@ class RevealSeedPage extends Component { onClick: () => this.props.history.push(DEFAULT_ROUTE), }, this.context.t('cancel')), h(Button, { - type: 'primary', + type: 'secondary', large: true, className: 'page-container__footer-button', onClick: event => this.handleSubmit(event), diff --git a/ui/app/pages/mobile-sync/index.js b/ui/app/pages/mobile-sync/index.js index 0938ad103..00a514534 100644 --- a/ui/app/pages/mobile-sync/index.js +++ b/ui/app/pages/mobile-sync/index.js @@ -315,7 +315,7 @@ class MobileSyncPage extends Component { }, this.context.t('cancel')), h(Button, { - type: 'primary', + type: 'secondary', large: true, className: 'new-account-create-form__button', onClick: event => this.handleSubmit(event), diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js index d1cad1746..14b9daae6 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js +++ b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js @@ -189,7 +189,7 @@ export default class AdvancedTab extends PureComponent { <div className="settings-page__content-item"> <div className="settings-page__content-item-col"> <Button - type="primary" + type="secondary" large onClick={event => { event.preventDefault() @@ -219,7 +219,7 @@ export default class AdvancedTab extends PureComponent { <div className="settings-page__content-item"> <div className="settings-page__content-item-col"> <Button - type="primary" + type="secondary" large onClick={() => { window.logStateString((err, result) => { @@ -251,7 +251,7 @@ export default class AdvancedTab extends PureComponent { <div className="settings-page__content-item"> <div className="settings-page__content-item-col"> <Button - type="secondary" + type="warning" large className="settings-tab__button--orange" onClick={event => { diff --git a/ui/app/pages/settings/info-tab/index.scss b/ui/app/pages/settings/info-tab/index.scss index 43ad6f652..9cc7e21b2 100644 --- a/ui/app/pages/settings/info-tab/index.scss +++ b/ui/app/pages/settings/info-tab/index.scss @@ -30,7 +30,7 @@ } &__link-text { - color: $curious-blue; + @extend %link; } &__version-number { diff --git a/ui/app/pages/settings/security-tab/security-tab.component.js b/ui/app/pages/settings/security-tab/security-tab.component.js index 233561115..01a28bac7 100644 --- a/ui/app/pages/settings/security-tab/security-tab.component.js +++ b/ui/app/pages/settings/security-tab/security-tab.component.js @@ -39,7 +39,7 @@ export default class SecurityTab extends PureComponent { <div className="settings-page__content-item"> <div className="settings-page__content-item-col"> <Button - type="primary" + type="secondary" large onClick={() => { window.logStateString((err, result) => { @@ -73,7 +73,7 @@ export default class SecurityTab extends PureComponent { <div className="settings-page__content-item"> <div className="settings-page__content-item-col"> <Button - type="secondary" + type="warning" large className="settings-tab__button--orange" onClick={event => { @@ -101,7 +101,7 @@ export default class SecurityTab extends PureComponent { <div className="settings-page__content-item"> <div className="settings-page__content-item-col"> <Button - type="secondary" + type="danger" large onClick={event => { event.preventDefault() diff --git a/ui/app/pages/settings/settings-tab/index.scss b/ui/app/pages/settings/settings-tab/index.scss index ef32b0e4c..c1750af2c 100644 --- a/ui/app/pages/settings/settings-tab/index.scss +++ b/ui/app/pages/settings/settings-tab/index.scss @@ -6,19 +6,15 @@ } &__advanced-link { - color: $curious-blue; + @extend %small-link; padding-left: 5px; } &__rpc-save-button { align-self: flex-end; padding: 5px; - text-transform: uppercase; - color: $dusty-gray; cursor: pointer; width: 25%; - min-width: 80px; - height: 33px; } &__button--red { @@ -35,20 +31,6 @@ } } - &__button--orange { - border-color: lighten($ecstasy, 20%); - color: $ecstasy; - - &:active { - background: lighten($ecstasy, 40%); - border-color: $ecstasy; - } - - &:hover { - border-color: $ecstasy; - } - } - &__radio-buttons { display: flex; align-items: center; |