fix merge conflicts

feature/default_network_editable
brunobar79 6 years ago
commit 9b1df386de
  1. 22
      .eslintrc
  2. 4
      CHANGELOG.md
  3. 2
      app/manifest.json
  4. 2
      app/scripts/controllers/transactions/index.js
  5. 2
      app/scripts/controllers/transactions/pending-tx-tracker.js
  6. 2
      app/scripts/controllers/transactions/tx-state-manager.js
  7. 4
      app/scripts/inpage.js
  8. 2
      app/scripts/lib/ens-ipfs/setup.js
  9. 27
      app/scripts/migrations/029.js
  10. 41
      app/scripts/migrations/fail-tx.js
  11. 1
      app/scripts/migrations/index.js
  12. 26
      auto-changelog.sh
  13. 2
      development/version-bump.js
  14. 16086
      package-lock.json
  15. 16
      package.json
  16. 8
      test/e2e/beta/metamask-beta-ui.spec.js
  17. 1
      test/lib/mock-tx-gen.js
  18. 1
      test/unit/app/controllers/metamask-controller-test.js
  19. 2
      test/unit/app/controllers/transactions/pending-tx-test.js
  20. 48
      test/unit/app/controllers/transactions/tx-controller-test.js
  21. 2
      test/unit/development/sample-changelog.md
  22. 38
      test/unit/migrations/029-test.js
  23. 2
      test/unit/ui/app/selectors.spec.js
  24. 2
      ui/app/actions.js
  25. 19
      ui/app/components/currency-display/currency-display.container.js
  26. 2
      ui/app/components/currency-display/tests/currency-display.container.test.js
  27. 2
      ui/app/components/index.scss
  28. 2
      ui/app/components/pages/create-account/connect-hardware/account-list.js
  29. 16
      ui/app/components/pages/create-account/connect-hardware/connect-screen.js
  30. 4
      ui/app/components/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js
  31. 9
      ui/app/components/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js
  32. 2
      ui/app/components/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js
  33. 5
      ui/app/components/send/send-content/send-amount-row/send-amount-row.component.js
  34. 1
      ui/app/components/send/send-content/send-amount-row/tests/send-amount-row-component.test.js
  35. 4
      ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.component.js
  36. 5
      ui/app/components/send/send-content/send-from-row/send-from-row.component.js
  37. 4
      ui/app/components/send/send-content/send-gas-row/send-gas-row.component.js
  38. 4
      ui/app/components/send/send-content/send-to-row/send-to-row.component.js
  39. 4
      ui/app/components/send/send-footer/send-footer.component.js
  40. 6
      ui/app/components/send/send.component.js
  41. 6
      ui/app/components/send/send.utils.js
  42. 2
      ui/app/components/send/tests/send-component.test.js
  43. 3
      ui/app/components/send/tests/send-utils.test.js
  44. 14
      ui/app/components/token-balance/index.scss
  45. 12
      ui/app/components/token-balance/token-balance.component.js
  46. 15
      ui/app/components/token-currency-display/token-currency-display.component.js
  47. 8
      ui/app/components/token-input/token-input.component.js
  48. 2
      ui/app/components/transaction-list-item/index.scss
  49. 26
      ui/app/components/transaction-view-balance/index.scss
  50. 4
      ui/app/components/transaction-view-balance/transaction-view-balance.component.js
  51. 4
      ui/app/components/unit-input/index.scss
  52. 2
      ui/app/components/unit-input/unit-input.component.js
  53. 2
      ui/app/conversion-util.js
  54. 42
      ui/app/css/itcss/components/new-account.scss
  55. 2
      ui/app/css/itcss/components/send.scss
  56. 2
      ui/app/reducers/metamask.js
  57. 9
      ui/app/selectors/confirm-transaction.js
  58. 2
      ui/app/token-util.js

@ -55,13 +55,13 @@
"constructor-super": 2, "constructor-super": 2,
"curly": [2, "multi-line"], "curly": [2, "multi-line"],
"dot-location": [2, "property"], "dot-location": [2, "property"],
"eol-last": 1, "eol-last": 2,
"eqeqeq": [2, "allow-null"], "eqeqeq": [2, "allow-null"],
"generator-star-spacing": [2, { "before": true, "after": true }], "generator-star-spacing": [2, { "before": true, "after": true }],
"handle-callback-err": [1, "^(err|error)$" ], "handle-callback-err": [2, "^(err|error)$" ],
"indent": "off", "indent": "off",
"jsx-quotes": [2, "prefer-double"], "jsx-quotes": [2, "prefer-double"],
"key-spacing": 1, "key-spacing": 2,
"keyword-spacing": [2, { "before": true, "after": true }], "keyword-spacing": [2, { "before": true, "after": true }],
"new-cap": [2, { "newIsCap": true, "capIsNew": false }], "new-cap": [2, { "newIsCap": true, "capIsNew": false }],
"new-parens": 2, "new-parens": 2,
@ -100,7 +100,7 @@
"no-mixed-spaces-and-tabs": 2, "no-mixed-spaces-and-tabs": 2,
"no-multi-spaces": 2, "no-multi-spaces": 2,
"no-multi-str": 2, "no-multi-str": 2,
"no-multiple-empty-lines": [1, { "max": 2 }], "no-multiple-empty-lines": [2, { "max": 2 }],
"no-native-reassign": 2, "no-native-reassign": 2,
"no-negated-in-lhs": 2, "no-negated-in-lhs": 2,
"no-new": 2, "no-new": 2,
@ -112,7 +112,7 @@
"no-obj-calls": 2, "no-obj-calls": 2,
"no-octal": 2, "no-octal": 2,
"no-octal-escape": 2, "no-octal-escape": 2,
"no-path-concat": 1, "no-path-concat": 2,
"no-proto": 2, "no-proto": 2,
"no-redeclare": 2, "no-redeclare": 2,
"no-regex-spaces": 2, "no-regex-spaces": 2,
@ -125,7 +125,7 @@
"no-sparse-arrays": 2, "no-sparse-arrays": 2,
"no-this-before-super": 2, "no-this-before-super": 2,
"no-throw-literal": 2, "no-throw-literal": 2,
"no-trailing-spaces": 1, "no-trailing-spaces": 2,
"no-undef": 2, "no-undef": 2,
"no-undef-init": 2, "no-undef-init": 2,
"no-unexpected-multiline": 2, "no-unexpected-multiline": 2,
@ -141,15 +141,15 @@
"no-whitespace-before-property": 2, "no-whitespace-before-property": 2,
"no-with": 2, "no-with": 2,
"one-var": [2, { "initialized": "never" }], "one-var": [2, { "initialized": "never" }],
"operator-linebreak": [1, "after", { "overrides": { "?": "ignore", ":": "ignore" } }], "operator-linebreak": [2, "after", { "overrides": { "?": "ignore", ":": "ignore" } }],
"padded-blocks": "off", "padded-blocks": "off",
"quotes": [2, "single", {"avoidEscape": true, "allowTemplateLiterals": true}], "quotes": [2, "single", {"avoidEscape": true, "allowTemplateLiterals": true}],
"react/no-deprecated": 0, "react/no-deprecated": 0,
"semi": [2, "never"], "semi": [2, "never"],
"semi-spacing": [2, { "before": false, "after": true }], "semi-spacing": [2, { "before": false, "after": true }],
"space-before-blocks": [1, "always"], "space-before-blocks": [2, "always"],
"space-before-function-paren": [1, "always"], "space-before-function-paren": [2, "always"],
"space-in-parens": [1, "never"], "space-in-parens": [2, "never"],
"space-infix-ops": 2, "space-infix-ops": 2,
"space-unary-ops": [2, { "words": true, "nonwords": false }], "space-unary-ops": [2, { "words": true, "nonwords": false }],
"spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","], "exceptions": ["=", "-"] } ], "spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","], "exceptions": ["=", "-"] } ],
@ -160,7 +160,7 @@
"wrap-iife": [2, "any"], "wrap-iife": [2, "any"],
"yield-star-spacing": [2, "both"], "yield-star-spacing": [2, "both"],
"yoda": [2, "never"], "yoda": [2, "never"],
"prefer-const": 1, "prefer-const": 2,
"mocha/no-exclusive-tests": "error" "mocha/no-exclusive-tests": "error"
} }
} }

@ -2,7 +2,11 @@
## Current Develop Branch ## Current Develop Branch
## 5.0.3 Mon Nov 19 2018
- [#5547](https://github.com/MetaMask/metamask-extension/pull/5547): Bundle some ui dependencies separately to limit the build size of ui.js
- Resubmit approved transactions on new block, to fix bug where an error can stick transactions in this state. - Resubmit approved transactions on new block, to fix bug where an error can stick transactions in this state.
- Fixed a bug that could cause an error when sending the max number of tokens.
## 5.0.2 Friday November 9 2018 ## 5.0.2 Friday November 9 2018

@ -1,7 +1,7 @@
{ {
"name": "__MSG_appName__", "name": "__MSG_appName__",
"short_name": "__MSG_appName__", "short_name": "__MSG_appName__",
"version": "5.0.2", "version": "5.0.3",
"manifest_version": 2, "manifest_version": 2,
"author": "https://metamask.io", "author": "https://metamask.io",
"description": "__MSG_appDescription__", "description": "__MSG_appDescription__",

@ -1,4 +1,4 @@
const EventEmitter = require('events') const EventEmitter = require('safe-event-emitter')
const ObservableStore = require('obs-store') const ObservableStore = require('obs-store')
const ethUtil = require('ethereumjs-util') const ethUtil = require('ethereumjs-util')
const Transaction = require('ethereumjs-tx') const Transaction = require('ethereumjs-tx')

@ -1,4 +1,4 @@
const EventEmitter = require('events') const EventEmitter = require('safe-event-emitter')
const log = require('loglevel') const log = require('loglevel')
const EthQuery = require('ethjs-query') const EthQuery = require('ethjs-query')

@ -1,5 +1,5 @@
const extend = require('xtend') const extend = require('xtend')
const EventEmitter = require('events') const EventEmitter = require('safe-event-emitter')
const ObservableStore = require('obs-store') const ObservableStore = require('obs-store')
const ethUtil = require('ethereumjs-util') const ethUtil = require('ethereumjs-util')
const log = require('loglevel') const log = require('loglevel')

@ -59,7 +59,9 @@ onMessage('metamasksetlocked', () => { isEnabled = false })
// set up a listener for privacy mode responses // set up a listener for privacy mode responses
onMessage('ethereumproviderlegacy', ({ data: { selectedAddress } }) => { onMessage('ethereumproviderlegacy', ({ data: { selectedAddress } }) => {
isEnabled = true isEnabled = true
setTimeout(() => {
inpageProvider.publicConfigStore.updateState({ selectedAddress }) inpageProvider.publicConfigStore.updateState({ selectedAddress })
}, 0)
}, true) }, true)
// augment the provider with its enable method // augment the provider with its enable method
@ -70,7 +72,9 @@ inpageProvider.enable = function ({ force } = {}) {
reject(error) reject(error)
} else { } else {
window.removeEventListener('message', providerHandle) window.removeEventListener('message', providerHandle)
setTimeout(() => {
inpageProvider.publicConfigStore.updateState({ selectedAddress }) inpageProvider.publicConfigStore.updateState({ selectedAddress })
}, 0)
// wait for the background to update with an account // wait for the background to update with an account
inpageProvider.sendAsync({ method: 'eth_accounts', params: [] }, (error, response) => { inpageProvider.sendAsync({ method: 'eth_accounts', params: [] }, (error, response) => {

@ -39,7 +39,7 @@ function setupEnsIpfsResolver({ provider }) {
extension.tabs.update(tabId, { url: `loading.html` }) extension.tabs.update(tabId, { url: `loading.html` })
try { try {
const ipfsContentId = await resolveEnsToIpfsContentId({ provider, name }) const ipfsContentId = await resolveEnsToIpfsContentId({ provider, name })
let url = `https://gateway.ipfs.io/ipfs/${ipfsContentId}${path}${search || ''}` const url = `https://gateway.ipfs.io/ipfs/${ipfsContentId}${path}${search || ''}`
try { try {
// check if ipfs gateway has result // check if ipfs gateway has result
const response = await fetch(url, { method: 'HEAD' }) const response = await fetch(url, { method: 'HEAD' })

@ -0,0 +1,27 @@
// next version number
const version = 29
const failTxsThat = require('./fail-tx')
// time
const seconds = 1000
const minutes = 60 * seconds
const hours = 60 * minutes
const unacceptableDelay = 12 * hours
/*
normalizes txParams on unconfirmed txs
*/
module.exports = {
version,
migrate: failTxsThat(version, 'Stuck in approved state for too long.', (txMeta) => {
const isApproved = txMeta.status === 'approved'
const createdTime = txMeta.submittedTime
const now = Date.now()
return isApproved && now - createdTime > unacceptableDelay
}),
}

@ -0,0 +1,41 @@
const clone = require('clone')
module.exports = function (version, reason, condition) {
return function (originalVersionedData) {
const versionedData = clone(originalVersionedData)
versionedData.meta.version = version
try {
const state = versionedData.data
const newState = transformState(state, condition, reason)
versionedData.data = newState
} catch (err) {
console.warn(`MetaMask Migration #${version}` + err.stack)
}
return Promise.resolve(versionedData)
}
}
function transformState (state, condition, reason) {
const newState = state
const { TransactionController } = newState
if (TransactionController && TransactionController.transactions) {
const transactions = TransactionController.transactions
newState.TransactionController.transactions = transactions.map((txMeta) => {
if (!condition(txMeta)) {
return txMeta
}
txMeta.status = 'failed'
txMeta.err = {
message: reason,
note: `Tx automatically failed by migration because ${reason}`,
}
return txMeta
})
}
return newState
}

@ -39,4 +39,5 @@ module.exports = [
require('./026'), require('./026'),
require('./027'), require('./027'),
require('./028'), require('./028'),
require('./029'),
] ]

@ -0,0 +1,26 @@
#! /bin/bash
# update tags
git fetch --tags
# get origin
URL='https://github.com/MetaMask/metamask-extension'
# get git logs from last tag until HEAD, pretty by 'subject::body' filtered by grep for PRs made with Github squash merge or Github regular merge
LOG=$(git log $(git describe --tags $(git rev-list --tags --max-count=1))..HEAD --pretty="%s::%b" --reverse --grep="Merge pull request #" --grep="(#");
while read -r line; do
# get git log subject
SUBJECT=$(echo $line | sed -E 's/(.*):{2}(.*)/\1/')
# get git log PR id, PR made with Github squash merge or Github regular merge
PR=$(echo $SUBJECT | sed 's/^.*(#\([^&]*\)).*/\1/' | sed 's/^.*#\([^&]*\) from.*/\1/')
# if PR made with Github squash merge, subject is the body
if [ -z "$(echo $line | sed -E 's/(.*):{2}(.*)/\2/')" ]; then
BODY=$(echo $SUBJECT | sed "s/(#$PR)//g"); else
BODY=$(echo $line | sed -E 's/(.*):{2}(.*)/\2/')
fi
# add entry to CHANGELOG
if [[ "$OSTYPE" == "linux-gnu" ]]; then
sed -i'' '/## Current Develop Branch/a\
- [#'"$PR"']('"$URL"'/pull/'"$PR"'): '"$BODY"''$'\n' CHANGELOG.md; else
sed -i '' '/## Current Develop Branch/a\
- [#'"$PR"']('"$URL"'/pull/'"$PR"'): '"$BODY"''$'\n' CHANGELOG.md;
fi
done <<< "$LOG"
echo 'CHANGELOG updated'

@ -10,7 +10,7 @@ async function versionBump (bumpType, changelog, oldManifest) {
const logHeader = `\n## ${newVersion} ${date}` const logHeader = `\n## ${newVersion} ${date}`
const logLines = changelog.split('\n') const logLines = changelog.split('\n')
for (let i = 0; i < logLines.length; i++) { for (let i = 0; i < logLines.length; i++) {
if (logLines[i].includes('Current Master')) { if (logLines[i].includes('Current Develop Branch')) {
logLines.splice(i + 1, 0, logHeader) logLines.splice(i + 1, 0, logHeader)
break break
} }

16086
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -49,7 +49,8 @@
"disc": "gulp disc --debug", "disc": "gulp disc --debug",
"announce": "node development/announcer.js", "announce": "node development/announcer.js",
"version:bump": "node development/run-version-bump.js", "version:bump": "node development/run-version-bump.js",
"storybook": "start-storybook -p 6006 -c .storybook" "storybook": "start-storybook -p 6006 -c .storybook",
"update-changelog": "./auto-changelog.sh"
}, },
"browserify": { "browserify": {
"transform": [ "transform": [
@ -119,7 +120,7 @@
"eth-hd-keyring": "^1.2.2", "eth-hd-keyring": "^1.2.2",
"eth-json-rpc-filters": "^3.0.1", "eth-json-rpc-filters": "^3.0.1",
"eth-json-rpc-infura": "^3.0.0", "eth-json-rpc-infura": "^3.0.0",
"eth-keyring-controller": "^3.1.4", "eth-keyring-controller": "^3.3.1",
"eth-ledger-bridge-keyring": "^0.1.0", "eth-ledger-bridge-keyring": "^0.1.0",
"eth-method-registry": "^1.0.0", "eth-method-registry": "^1.0.0",
"eth-phishing-detect": "^1.1.4", "eth-phishing-detect": "^1.1.4",
@ -166,7 +167,7 @@
"lodash.uniqby": "^4.7.0", "lodash.uniqby": "^4.7.0",
"loglevel": "^1.4.1", "loglevel": "^1.4.1",
"metamascara": "^2.0.0", "metamascara": "^2.0.0",
"metamask-inpage-provider": "^1.2.2", "metamask-inpage-provider": "^1.3.0",
"metamask-logo": "^2.1.4", "metamask-logo": "^2.1.4",
"mkdirp": "^0.5.1", "mkdirp": "^0.5.1",
"multihashes": "^0.4.12", "multihashes": "^0.4.12",
@ -211,6 +212,7 @@
"redux-thunk": "^2.2.0", "redux-thunk": "^2.2.0",
"request-promise": "^4.2.1", "request-promise": "^4.2.1",
"reselect": "^3.0.1", "reselect": "^3.0.1",
"safe-event-emitter": "^1.0.1",
"sandwich-expando": "^1.1.3", "sandwich-expando": "^1.1.3",
"semaphore": "^1.0.5", "semaphore": "^1.0.5",
"semver": "^5.4.1", "semver": "^5.4.1",
@ -268,14 +270,14 @@
"fs-extra": "^6.0.1", "fs-extra": "^6.0.1",
"fs-promise": "^2.0.3", "fs-promise": "^2.0.3",
"ganache-cli": "^6.1.0", "ganache-cli": "^6.1.0",
"ganache-core": "^2.1.5", "ganache-core": "^2.2.1",
"geckodriver": "^1.11.0", "geckodriver": "^1.14.1",
"gh-pages": "^1.2.0", "gh-pages": "^1.2.0",
"gifencoder": "^1.1.0", "gifencoder": "^1.1.0",
"gulp": "github:gulpjs/gulp#6d71a658c61edb3090221579d8f97dbe086ba2ed", "gulp": "github:gulpjs/gulp#6d71a658c61edb3090221579d8f97dbe086ba2ed",
"gulp-babel": "^7.0.0", "gulp-babel": "^7.0.0",
"gulp-json-editor": "^2.2.1", "gulp-json-editor": "^2.2.1",
"gulp-livereload": "^3.8.1", "gulp-livereload": "^4.0.0",
"gulp-multi-process": "^1.3.1", "gulp-multi-process": "^1.3.1",
"gulp-replace": "^0.6.1", "gulp-replace": "^0.6.1",
"gulp-sourcemaps": "^2.6.0", "gulp-sourcemaps": "^2.6.0",
@ -293,7 +295,7 @@
"jsdom": "^11.2.0", "jsdom": "^11.2.0",
"jsdom-global": "^3.0.2", "jsdom-global": "^3.0.2",
"jshint-stylish": "~2.2.1", "jshint-stylish": "~2.2.1",
"karma": "^2.0.4", "karma": "^3.1.1",
"karma-chrome-launcher": "^2.2.0", "karma-chrome-launcher": "^2.2.0",
"karma-cli": "^1.0.1", "karma-cli": "^1.0.1",
"karma-firefox-launcher": "^1.0.1", "karma-firefox-launcher": "^1.0.1",

@ -840,7 +840,7 @@ describe('MetaMask', function () {
}) })
it('renders the balance for the new token', async () => { it('renders the balance for the new token', async () => {
const balance = await findElement(driver, By.css('.transaction-view-balance .transaction-view-balance__token-balance')) const balance = await findElement(driver, By.css('.transaction-view-balance .transaction-view-balance__primary-balance'))
await driver.wait(until.elementTextMatches(balance, /^100\s*TST\s*$/)) await driver.wait(until.elementTextMatches(balance, /^100\s*TST\s*$/))
const tokenAmount = await balance.getText() const tokenAmount = await balance.getText()
assert.ok(/^100\s*TST\s*$/.test(tokenAmount)) assert.ok(/^100\s*TST\s*$/.test(tokenAmount))
@ -1019,8 +1019,8 @@ describe('MetaMask', function () {
// test cancelled on firefox until https://github.com/mozilla/geckodriver/issues/906 is resolved, // 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 // or possibly until we use latest version of firefox in the tests
if (process.env.SELENIUM_BROWSER !== 'firefox') { if (process.env.SELENIUM_BROWSER !== 'firefox') {
const tokenBalanceAmount = await findElement(driver, By.css('.transaction-view-balance__token-balance')) const tokenBalanceAmount = await findElements(driver, By.css('.transaction-view-balance__primary-balance'))
assert.equal(await tokenBalanceAmount.getText(), '43 TST') await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /43\s*TST/))
} }
}) })
}) })
@ -1180,7 +1180,7 @@ describe('MetaMask', function () {
}) })
it('renders the balance for the chosen token', async () => { it('renders the balance for the chosen token', async () => {
const balance = await findElement(driver, By.css('.transaction-view-balance__token-balance')) const balance = await findElement(driver, By.css('.transaction-view-balance__primary-balance'))
await driver.wait(until.elementTextMatches(balance, /0\s*BAT/)) await driver.wait(until.elementTextMatches(balance, /0\s*BAT/))
await delay(regularDelayMs) await delay(regularDelayMs)
}) })

@ -2,6 +2,7 @@ const extend = require('xtend')
const BN = require('ethereumjs-util').BN const BN = require('ethereumjs-util').BN
const template = { const template = {
'status': 'submitted', 'status': 'submitted',
'history': [{}],
'txParams': { 'txParams': {
'from': '0x7d3517b0d011698406d6e0aed8453f0be2697926', 'from': '0x7d3517b0d011698406d6e0aed8453f0be2697926',
'gas': '0x30d40', 'gas': '0x30d40',

@ -58,6 +58,7 @@ describe('MetaMaskController', function () {
}, },
}, },
initState: clone(firstTimeState), initState: clone(firstTimeState),
platform: { showTransactionNotification: () => {} },
}) })
// disable diagnostics // disable diagnostics
metamaskController.diagnostics = null metamaskController.diagnostics = null

@ -20,10 +20,12 @@ describe('PendingTransactionTracker', function () {
nonce: '0x1', nonce: '0x1',
value: '0xfffff', value: '0xfffff',
}, },
history: [{}],
rawTx: '0xf86c808504a817c800827b0d940c62bb85faa3311a998d3aba8098c1235c564966880de0b6b3a7640000802aa08ff665feb887a25d4099e40e11f0fef93ee9608f404bd3f853dd9e84ed3317a6a02ec9d3d1d6e176d4d2593dd760e74ccac753e6a0ea0d00cc9789d0d7ff1f471d', rawTx: '0xf86c808504a817c800827b0d940c62bb85faa3311a998d3aba8098c1235c564966880de0b6b3a7640000802aa08ff665feb887a25d4099e40e11f0fef93ee9608f404bd3f853dd9e84ed3317a6a02ec9d3d1d6e176d4d2593dd760e74ccac753e6a0ea0d00cc9789d0d7ff1f471d',
} }
txMetaNoHash = { txMetaNoHash = {
id: 2, id: 2,
history: [{}],
status: 'submitted', status: 'submitted',
txParams: { from: '0x1678a085c290ebd122dc42cba69373b5953b831d'}, txParams: { from: '0x1678a085c290ebd122dc42cba69373b5953b831d'},
} }

@ -52,9 +52,9 @@ describe('Transaction Controller', function () {
describe('#getUnapprovedTxCount', function () { describe('#getUnapprovedTxCount', function () {
it('should return the number of unapproved txs', function () { it('should return the number of unapproved txs', function () {
txController.txStateManager._saveTxList([ txController.txStateManager._saveTxList([
{ id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] }, { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
{ id: 2, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] }, { id: 2, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
{ id: 3, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] }, { id: 3, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
]) ])
const unapprovedTxCount = txController.getUnapprovedTxCount() const unapprovedTxCount = txController.getUnapprovedTxCount()
assert.equal(unapprovedTxCount, 3, 'should be 3') assert.equal(unapprovedTxCount, 3, 'should be 3')
@ -64,9 +64,9 @@ describe('Transaction Controller', function () {
describe('#getPendingTxCount', function () { describe('#getPendingTxCount', function () {
it('should return the number of pending txs', function () { it('should return the number of pending txs', function () {
txController.txStateManager._saveTxList([ txController.txStateManager._saveTxList([
{ id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] }, { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
{ id: 2, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] }, { id: 2, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
{ id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] }, { id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
]) ])
const pendingTxCount = txController.getPendingTxCount() const pendingTxCount = txController.getPendingTxCount()
assert.equal(pendingTxCount, 3, 'should be 3') assert.equal(pendingTxCount, 3, 'should be 3')
@ -82,15 +82,15 @@ describe('Transaction Controller', function () {
'to': '0xc684832530fcbddae4b4230a47e991ddcec2831d', 'to': '0xc684832530fcbddae4b4230a47e991ddcec2831d',
} }
txController.txStateManager._saveTxList([ txController.txStateManager._saveTxList([
{id: 0, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [] }, {id: 0, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
{id: 1, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [] }, {id: 1, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
{id: 2, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [] }, {id: 2, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
{id: 3, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams, history: [] }, {id: 3, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
{id: 4, status: 'rejected', metamaskNetworkId: currentNetworkId, txParams, history: [] }, {id: 4, status: 'rejected', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
{id: 5, status: 'approved', metamaskNetworkId: currentNetworkId, txParams, history: [] }, {id: 5, status: 'approved', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
{id: 6, status: 'signed', metamaskNetworkId: currentNetworkId, txParams, history: [] }, {id: 6, status: 'signed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
{id: 7, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [] }, {id: 7, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
{id: 8, status: 'failed', metamaskNetworkId: currentNetworkId, txParams, history: [] }, {id: 8, status: 'failed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
]) ])
}) })
@ -112,7 +112,7 @@ describe('Transaction Controller', function () {
id: 1, id: 1,
metamaskNetworkId: currentNetworkId, metamaskNetworkId: currentNetworkId,
txParams, txParams,
history: [], history: [{}],
} }
txController.txStateManager._saveTxList([txMeta]) txController.txStateManager._saveTxList([txMeta])
stub = sinon.stub(txController, 'addUnapprovedTransaction').callsFake(() => { stub = sinon.stub(txController, 'addUnapprovedTransaction').callsFake(() => {
@ -232,7 +232,7 @@ describe('Transaction Controller', function () {
from: '0xc684832530fcbddae4b4230a47e991ddcec2831d', from: '0xc684832530fcbddae4b4230a47e991ddcec2831d',
to: '0xc684832530fcbddae4b4230a47e991ddcec2831d', to: '0xc684832530fcbddae4b4230a47e991ddcec2831d',
}, },
history: [], history: [{}],
} }
providerResultStub.eth_gasPrice = '4a817c800' providerResultStub.eth_gasPrice = '4a817c800'
providerResultStub.eth_getBlockByNumber = { gasLimit: '47b784' } providerResultStub.eth_getBlockByNumber = { gasLimit: '47b784' }
@ -423,7 +423,7 @@ describe('Transaction Controller', function () {
data: '0x0', data: '0x0',
} }
txController.txStateManager._saveTxList([ txController.txStateManager._saveTxList([
{ id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [] }, { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
]) ])
txController.retryTransaction(1) txController.retryTransaction(1)
.then((txMeta) => { .then((txMeta) => {
@ -462,12 +462,12 @@ describe('Transaction Controller', function () {
beforeEach(function () { beforeEach(function () {
txController.txStateManager._saveTxList([ txController.txStateManager._saveTxList([
{ id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} }, { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} },
{ id: 2, status: 'rejected', metamaskNetworkId: currentNetworkId, txParams: {} }, { id: 2, status: 'rejected', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
{ id: 3, status: 'approved', metamaskNetworkId: currentNetworkId, txParams: {} }, { id: 3, status: 'approved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
{ id: 4, status: 'signed', metamaskNetworkId: currentNetworkId, txParams: {} }, { id: 4, status: 'signed', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
{ id: 5, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {} }, { id: 5, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
{ id: 6, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {} }, { id: 6, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
{ id: 7, status: 'failed', metamaskNetworkId: currentNetworkId, txParams: {} }, { id: 7, status: 'failed', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
]) ])
}) })
it('should show only submitted and approved transactions as pending transasction', function () { it('should show only submitted and approved transactions as pending transasction', function () {

@ -1,6 +1,6 @@
# Changelog # Changelog
## Current Master ## Current Develop Branch
## 4.1.3 2018-2-28 ## 4.1.3 2018-2-28

@ -0,0 +1,38 @@
const assert = require('assert')
const migration29 = require('../../../app/scripts/migrations/029')
const properTime = (new Date()).getTime()
const storage = {
'meta': {},
'data': {
'TransactionController': {
'transactions': [
{ 'status': 'approved', id: 1, submittedTime: 0 },
{ 'status': 'approved', id: 2, submittedTime: properTime },
{ 'status': 'confirmed', id: 3, submittedTime: properTime },
{ 'status': 'submitted', id: 4, submittedTime: properTime },
{ 'status': 'submitted', id: 5, submittedTime: 0 },
],
},
},
}
describe('storage is migrated successfully where transactions that are submitted have submittedTimes', () => {
it('should auto fail transactions more than 12 hours old', (done) => {
migration29.migrate(storage)
.then((migratedData) => {
const txs = migratedData.data.TransactionController.transactions
const [ txMeta1 ] = txs
assert.equal(migratedData.meta.version, 29)
assert.equal(txMeta1.status, 'failed', 'old tx is auto failed')
assert(txMeta1.err.message.includes('too long'), 'error message assigned')
txs.forEach((tx) => {
if (tx.id === 1) return
assert.notEqual(tx.status, 'failed', 'other tx is not auto failed')
})
done()
}).catch(done)
})
})

@ -148,7 +148,7 @@ describe('Selectors', function () {
it('#getSelectedTokenToFiatRate', () => { it('#getSelectedTokenToFiatRate', () => {
const selectedTokenToFiatRate = selectors.getSelectedTokenToFiatRate(mockState) const selectedTokenToFiatRate = selectors.getSelectedTokenToFiatRate(mockState)
assert.equal(selectedTokenToFiatRate, '0.21880988420033493') assert.equal(selectedTokenToFiatRate, '0.21880988420033492152')
}) })
describe('#getSelectedTokenContract', () => { describe('#getSelectedTokenContract', () => {

@ -995,7 +995,7 @@ function updateSendTokenBalance ({
.then(usersToken => { .then(usersToken => {
if (usersToken) { if (usersToken) {
const newTokenBalance = calcTokenBalance({ selectedToken, usersToken }) const newTokenBalance = calcTokenBalance({ selectedToken, usersToken })
dispatch(setSendTokenBalance(newTokenBalance.toString(10))) dispatch(setSendTokenBalance(newTokenBalance))
} }
}) })
.catch(err => { .catch(err => {

@ -20,15 +20,24 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
currency, currency,
denomination, denomination,
hideLabel, hideLabel,
displayValue: propsDisplayValue,
suffix: propsSuffix,
...restOwnProps ...restOwnProps
} = ownProps } = ownProps
const toCurrency = currency || currentCurrency const toCurrency = currency || currentCurrency
const convertedValue = getValueFromWeiHex({
value, fromCurrency: nativeCurrency, toCurrency, conversionRate, numberOfDecimals, toDenomination: denomination, const displayValue = propsDisplayValue || formatCurrency(
}) getValueFromWeiHex({
const displayValue = formatCurrency(convertedValue, toCurrency) value,
const suffix = hideLabel ? undefined : toCurrency.toUpperCase() fromCurrency: nativeCurrency,
toCurrency, conversionRate,
numberOfDecimals,
toDenomination: denomination,
}),
toCurrency
)
const suffix = propsSuffix || (hideLabel ? undefined : toCurrency.toUpperCase())
return { return {
...restStateProps, ...restStateProps,

@ -131,7 +131,7 @@ describe('CurrencyDisplay container', () => {
}, },
result: { result: {
nativeCurrency: 'ETH', nativeCurrency: 'ETH',
displayValue: '1e-9', displayValue: '0.000000001',
suffix: undefined, suffix: undefined,
}, },
}, },

@ -40,6 +40,8 @@
@import './tabs/index'; @import './tabs/index';
@import './token-balance/index';
@import './transaction-activity-log/index'; @import './transaction-activity-log/index';
@import './transaction-breakdown/index'; @import './transaction-breakdown/index';

@ -152,7 +152,7 @@ class AccountList extends Component {
}, [this.context.t('cancel')]), }, [this.context.t('cancel')]),
h(Button, { h(Button, {
type: 'primary', type: 'confirm',
large: true, large: true,
className: 'new-account-connect-form__button unlock', className: 'new-account-connect-form__button unlock',
disabled, disabled,

@ -45,11 +45,13 @@ class ConnectScreen extends Component {
this.renderConnectToLedgerButton(), this.renderConnectToLedgerButton(),
this.renderConnectToTrezorButton(), this.renderConnectToTrezorButton(),
]), ]),
h( h(Button, {
`button.hw-connect__connect-btn${!this.state.selectedDevice ? '.disabled' : ''}`, type: 'confirm',
{ onClick: this.connect }, large: true,
this.context.t('connect') className: 'hw-connect__connect-btn',
), onClick: this.connect,
disabled: !this.state.selectedDevice,
}, this.context.t('connect')),
]) ])
) )
} }
@ -67,9 +69,7 @@ class ConnectScreen extends Component {
onClick: () => global.platform.openWindow({ onClick: () => global.platform.openWindow({
url: 'https://google.com/chrome', url: 'https://google.com/chrome',
}), }),
}, }, this.context.t('downloadGoogleChrome')),
this.context.t('downloadGoogleChrome')
),
]) ])
) )
} }

@ -11,11 +11,11 @@ export default class AmountMaxButton extends Component {
setAmountToMax: PropTypes.func, setAmountToMax: PropTypes.func,
setMaxModeTo: PropTypes.func, setMaxModeTo: PropTypes.func,
tokenBalance: PropTypes.string, tokenBalance: PropTypes.string,
}; }
static contextTypes = { static contextTypes = {
t: PropTypes.func, t: PropTypes.func,
}; }
setMaxAmount () { setMaxAmount () {
const { const {

@ -9,7 +9,14 @@ function calcMaxAmount ({ balance, gasTotal, selectedToken, tokenBalance }) {
const multiplier = Math.pow(10, Number(decimals || 0)) const multiplier = Math.pow(10, Number(decimals || 0))
return selectedToken return selectedToken
? multiplyCurrencies(tokenBalance, multiplier, {toNumericBase: 'hex'}) ? multiplyCurrencies(
tokenBalance,
multiplier,
{
toNumericBase: 'hex',
multiplicandBase: 16,
}
)
: subtractCurrencies( : subtractCurrencies(
ethUtil.addHexPrefix(balance), ethUtil.addHexPrefix(balance),
ethUtil.addHexPrefix(gasTotal), ethUtil.addHexPrefix(gasTotal),

@ -19,7 +19,7 @@ describe('amount-max-button utils', () => {
selectedToken: { selectedToken: {
decimals: 10, decimals: 10,
}, },
tokenBalance: 100, tokenBalance: '64',
}), 'e8d4a51000') }), 'e8d4a51000')
}) })
}) })

@ -26,11 +26,11 @@ export default class SendAmountRow extends Component {
updateSendAmount: PropTypes.func, updateSendAmount: PropTypes.func,
updateSendAmountError: PropTypes.func, updateSendAmountError: PropTypes.func,
updateGas: PropTypes.func, updateGas: PropTypes.func,
}; }
static contextTypes = { static contextTypes = {
t: PropTypes.func, t: PropTypes.func,
}; }
validateAmount (amount) { validateAmount (amount) {
const { const {
@ -58,7 +58,6 @@ export default class SendAmountRow extends Component {
if (selectedToken) { if (selectedToken) {
updateGasFeeError({ updateGasFeeError({
amount,
amountConversionRate, amountConversionRate,
balance, balance,
conversionRate, conversionRate,

@ -82,7 +82,6 @@ describe('SendAmountRow Component', function () {
assert.deepEqual( assert.deepEqual(
propsMethodSpies.updateGasFeeError.getCall(0).args, propsMethodSpies.updateGasFeeError.getCall(0).args,
[{ [{
amount: 'someAmount',
amountConversionRate: 'mockAmountConversionRate', amountConversionRate: 'mockAmountConversionRate',
balance: 'mockBalance', balance: 'mockBalance',
conversionRate: 7, conversionRate: 7,

@ -12,11 +12,11 @@ export default class FromDropdown extends Component {
onSelect: PropTypes.func, onSelect: PropTypes.func,
openDropdown: PropTypes.func, openDropdown: PropTypes.func,
selectedAccount: PropTypes.object, selectedAccount: PropTypes.object,
}; }
static contextTypes = { static contextTypes = {
t: PropTypes.func, t: PropTypes.func,
}; }
render () { render () {
const { const {

@ -15,11 +15,11 @@ export default class SendFromRow extends Component {
tokenContract: PropTypes.object, tokenContract: PropTypes.object,
updateSendFrom: PropTypes.func, updateSendFrom: PropTypes.func,
setSendTokenBalance: PropTypes.func, setSendTokenBalance: PropTypes.func,
}; }
static contextTypes = { static contextTypes = {
t: PropTypes.func, t: PropTypes.func,
}; }
async handleFromChange (newFrom) { async handleFromChange (newFrom) {
const { const {
@ -32,6 +32,7 @@ export default class SendFromRow extends Component {
const usersToken = await tokenContract.balanceOf(newFrom.address) const usersToken = await tokenContract.balanceOf(newFrom.address)
setSendTokenBalance(usersToken) setSendTokenBalance(usersToken)
} }
updateSendFrom(newFrom) updateSendFrom(newFrom)
} }

@ -12,11 +12,11 @@ export default class SendGasRow extends Component {
gasLoadingError: PropTypes.bool, gasLoadingError: PropTypes.bool,
gasTotal: PropTypes.string, gasTotal: PropTypes.string,
showCustomizeGasModal: PropTypes.func, showCustomizeGasModal: PropTypes.func,
}; }
static contextTypes = { static contextTypes = {
t: PropTypes.func, t: PropTypes.func,
}; }
render () { render () {
const { const {

@ -19,11 +19,11 @@ export default class SendToRow extends Component {
updateSendTo: PropTypes.func, updateSendTo: PropTypes.func,
updateSendToError: PropTypes.func, updateSendToError: PropTypes.func,
scanQrCode: PropTypes.func, scanQrCode: PropTypes.func,
}; }
static contextTypes = { static contextTypes = {
t: PropTypes.func, t: PropTypes.func,
}; }
handleToChange (to, nickname = '', toError) { handleToChange (to, nickname = '', toError) {
const { hasHexData, updateSendTo, updateSendToError, updateGas } = this.props const { hasHexData, updateSendTo, updateSendToError, updateGas } = this.props

@ -26,11 +26,11 @@ export default class SendFooter extends Component {
tokenBalance: PropTypes.string, tokenBalance: PropTypes.string,
unapprovedTxs: PropTypes.object, unapprovedTxs: PropTypes.object,
update: PropTypes.func, update: PropTypes.func,
}; }
static contextTypes = { static contextTypes = {
t: PropTypes.func, t: PropTypes.func,
}; }
onCancel () { onCancel () {
this.props.clearSend() this.props.clearSend()

@ -41,11 +41,11 @@ export default class SendTransactionScreen extends PersistentForm {
scanQrCode: PropTypes.func, scanQrCode: PropTypes.func,
qrCodeDetected: PropTypes.func, qrCodeDetected: PropTypes.func,
qrCodeData: PropTypes.object, qrCodeData: PropTypes.object,
}; }
static contextTypes = { static contextTypes = {
t: PropTypes.func, t: PropTypes.func,
}; }
componentWillReceiveProps (nextProps) { componentWillReceiveProps (nextProps) {
if (nextProps.qrCodeData) { if (nextProps.qrCodeData) {
@ -138,14 +138,12 @@ export default class SendTransactionScreen extends PersistentForm {
}) })
const gasFeeErrorObject = selectedToken const gasFeeErrorObject = selectedToken
? getGasFeeErrorObject({ ? getGasFeeErrorObject({
amount,
amountConversionRate, amountConversionRate,
balance, balance,
conversionRate, conversionRate,
gasTotal, gasTotal,
primaryCurrency, primaryCurrency,
selectedToken, selectedToken,
tokenBalance,
}) })
: { gasFee: null } : { gasFee: null }
updateSendErrors(Object.assign(amountErrorObject, gasFeeErrorObject)) updateSendErrors(Object.assign(amountErrorObject, gasFeeErrorObject))

@ -89,11 +89,10 @@ function isTokenBalanceSufficient ({
const tokenBalanceIsSufficient = conversionGTE( const tokenBalanceIsSufficient = conversionGTE(
{ {
value: tokenBalance, value: tokenBalance,
fromNumericBase: 'dec', fromNumericBase: 'hex',
}, },
{ {
value: calcTokenAmount(amountInDec, decimals), value: calcTokenAmount(amountInDec, decimals),
fromNumericBase: 'dec',
}, },
) )
@ -151,7 +150,6 @@ function getAmountErrorObject ({
} }
function getGasFeeErrorObject ({ function getGasFeeErrorObject ({
amount,
amountConversionRate, amountConversionRate,
balance, balance,
conversionRate, conversionRate,
@ -180,7 +178,7 @@ function getGasFeeErrorObject ({
function calcTokenBalance ({ selectedToken, usersToken }) { function calcTokenBalance ({ selectedToken, usersToken }) {
const { decimals } = selectedToken || {} const { decimals } = selectedToken || {}
return calcTokenAmount(usersToken.balance.toString(), decimals) + '' return calcTokenAmount(usersToken.balance.toString(), decimals).toString(16)
} }
function doesAmountErrorRequireUpdate ({ function doesAmountErrorRequireUpdate ({

@ -158,14 +158,12 @@ describe('Send Component', function () {
assert.deepEqual( assert.deepEqual(
utilsMethodStubs.getGasFeeErrorObject.getCall(0).args[0], utilsMethodStubs.getGasFeeErrorObject.getCall(0).args[0],
{ {
amount: 'mockAmount',
amountConversionRate: 'mockAmountConversionRate', amountConversionRate: 'mockAmountConversionRate',
balance: 'mockBalance', balance: 'mockBalance',
conversionRate: 10, conversionRate: 10,
gasTotal: 'mockGasTotal', gasTotal: 'mockGasTotal',
primaryCurrency: 'mockPrimaryCurrency', primaryCurrency: 'mockPrimaryCurrency',
selectedToken: 'mockSelectedToken', selectedToken: 'mockSelectedToken',
tokenBalance: 'mockTokenBalance',
} }
) )
}) })

@ -285,11 +285,10 @@ describe('send utils', () => {
[ [
{ {
value: 123, value: 123,
fromNumericBase: 'dec', fromNumericBase: 'hex',
}, },
{ {
value: 'calc:1610', value: 'calc:1610',
fromNumericBase: 'dec',
}, },
] ]
) )

@ -0,0 +1,14 @@
.token-balance-component {
display: flex;
align-items: center;
&__text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&__suffix {
padding-left: 4px;
}
}

@ -1,6 +1,6 @@
import React, { PureComponent } from 'react' import React, { PureComponent } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import classnames from 'classnames' import CurrencyDisplay from '../currency-display'
export default class TokenBalance extends PureComponent { export default class TokenBalance extends PureComponent {
static propTypes = { static propTypes = {
@ -12,12 +12,14 @@ export default class TokenBalance extends PureComponent {
} }
render () { render () {
const { className, string, withSymbol, symbol } = this.props const { className, string, symbol } = this.props
return ( return (
<div className={classnames('hide-text-overflow', className)}> <CurrencyDisplay
{ string + (withSymbol ? ` ${symbol}` : '') } className={className}
</div> displayValue={string}
suffix={symbol}
/>
) )
} }
} }

@ -1,6 +1,6 @@
import React, { PureComponent } from 'react' import React, { PureComponent } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import CurrencyDisplay from '../currency-display/currency-display.component' import CurrencyDisplay from '../currency-display'
import { getTokenData } from '../../helpers/transactions.util' import { getTokenData } from '../../helpers/transactions.util'
import { getTokenValue, calcTokenAmount } from '../../token-util' import { getTokenValue, calcTokenAmount } from '../../token-util'
@ -12,6 +12,7 @@ export default class TokenCurrencyDisplay extends PureComponent {
state = { state = {
displayValue: '', displayValue: '',
suffix: '',
} }
componentDidMount () { componentDidMount () {
@ -29,25 +30,27 @@ export default class TokenCurrencyDisplay extends PureComponent {
setDisplayValue () { setDisplayValue () {
const { transactionData: data, token } = this.props const { transactionData: data, token } = this.props
const { decimals = '', symbol = '' } = token const { decimals = '', symbol: suffix = '' } = token
const tokenData = getTokenData(data) const tokenData = getTokenData(data)
let displayValue let displayValue
if (tokenData.params && tokenData.params.length) { if (tokenData.params && tokenData.params.length) {
const tokenValue = getTokenValue(tokenData.params) const tokenValue = getTokenValue(tokenData.params)
const tokenAmount = calcTokenAmount(tokenValue, decimals) displayValue = calcTokenAmount(tokenValue, decimals).toString()
displayValue = `${tokenAmount} ${symbol}`
} }
this.setState({ displayValue }) this.setState({ displayValue, suffix })
} }
render () { render () {
const { displayValue, suffix } = this.state
return ( return (
<CurrencyDisplay <CurrencyDisplay
{...this.props} {...this.props}
displayValue={this.state.displayValue} displayValue={displayValue}
suffix={suffix}
/> />
) )
} }

@ -32,7 +32,7 @@ export default class TokenInput extends PureComponent {
super(props) super(props)
const { value: hexValue } = props const { value: hexValue } = props
const decimalValue = hexValue ? this.getDecimalValue(props) : 0 const decimalValue = hexValue ? this.getValue(props) : 0
this.state = { this.state = {
decimalValue, decimalValue,
@ -46,12 +46,12 @@ export default class TokenInput extends PureComponent {
const { hexValue: stateHexValue } = this.state const { hexValue: stateHexValue } = this.state
if (prevPropsHexValue !== propsHexValue && propsHexValue !== stateHexValue) { if (prevPropsHexValue !== propsHexValue && propsHexValue !== stateHexValue) {
const decimalValue = this.getDecimalValue(this.props) const decimalValue = this.getValue(this.props)
this.setState({ hexValue: propsHexValue, decimalValue }) this.setState({ hexValue: propsHexValue, decimalValue })
} }
} }
getDecimalValue (props) { getValue (props) {
const { value: hexValue, selectedToken: { decimals, symbol } = {} } = props const { value: hexValue, selectedToken: { decimals, symbol } = {} } = props
const multiplier = Math.pow(10, Number(decimals || 0)) const multiplier = Math.pow(10, Number(decimals || 0))
@ -63,7 +63,7 @@ export default class TokenInput extends PureComponent {
invertConversionRate: true, invertConversionRate: true,
}) })
return Number(decimalValueString) || 0 return Number(decimalValueString) ? decimalValueString : ''
} }
handleChange = decimalValue => { handleChange = decimalValue => {

@ -80,6 +80,8 @@
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
min-width: 0;
max-width: 100%;
&--primary { &--primary {
text-align: end; text-align: end;

@ -6,6 +6,12 @@
height: 54px; height: 54px;
min-width: 0; min-width: 0;
@media screen and (max-width: $break-small) {
flex-direction: column;
height: initial;
width: 100%;
}
&__balance { &__balance {
margin: 0 12px; margin: 0 12px;
display: flex; display: flex;
@ -15,17 +21,8 @@
@media screen and (max-width: $break-small) { @media screen and (max-width: $break-small) {
align-items: center; align-items: center;
margin: 16px 0; margin: 16px 0;
} padding: 0 16px;
} max-width: 100%;
&__token-balance {
margin-left: 12px;
font-size: 1.5rem;
@media screen and (max-width: $break-small) {
margin: 12px 0;
margin-left: 0;
font-size: 1.75rem;
} }
} }
@ -34,6 +31,7 @@
@media screen and (max-width: $break-small) { @media screen and (max-width: $break-small) {
font-size: 1.75rem; font-size: 1.75rem;
width: 100%;
} }
} }
@ -51,6 +49,7 @@
@media screen and (max-width: $break-small) { @media screen and (max-width: $break-small) {
flex-direction: column; flex-direction: column;
width: 100%;
} }
} }
@ -71,9 +70,4 @@
margin-right: 12px; margin-right: 12px;
} }
} }
@media screen and (max-width: $break-small) {
flex-direction: column;
height: initial
}
} }

@ -26,11 +26,13 @@ export default class TransactionViewBalance extends PureComponent {
return selectedToken return selectedToken
? ( ? (
<div className="transaction-view-balance__balance">
<TokenBalance <TokenBalance
token={selectedToken} token={selectedToken}
withSymbol withSymbol
className="transaction-view-balance__token-balance" className="transaction-view-balance__primary-balance"
/> />
</div>
) : ( ) : (
<div className="transaction-view-balance__balance"> <div className="transaction-view-balance__balance">
<UserPreferencedCurrencyDisplay <UserPreferencedCurrencyDisplay

@ -38,6 +38,10 @@
align-items: center; align-items: center;
} }
&__suffix {
margin-left: 3px;
}
&--error { &--error {
border-color: $red; border-color: $red;
} }

@ -66,7 +66,7 @@ export default class UnitInput extends PureComponent {
const valueString = String(value) const valueString = String(value)
const valueLength = valueString.length || 1 const valueLength = valueString.length || 1
const decimalPointDeficit = valueString.match(/\./) ? -0.5 : 0 const decimalPointDeficit = valueString.match(/\./) ? -0.5 : 0
return (valueLength + decimalPointDeficit + 0.75) + 'ch' return (valueLength + decimalPointDeficit + 0.5) + 'ch'
} }
render () { render () {

@ -62,7 +62,7 @@ const toSpecifiedDenomination = {
} }
const baseChange = { const baseChange = {
hex: n => n.toString(16), hex: n => n.toString(16),
dec: n => Number(n).toString(10), dec: n => (new BigNumber(n)).toString(10),
BN: n => new BN(n.toString(16)), BN: n => new BN(n.toString(16)),
} }

@ -3,6 +3,7 @@
background-color: #FFFFFF; background-color: #FFFFFF;
box-shadow: 0 0 7px 0 rgba(0,0,0,0.08); box-shadow: 0 0 7px 0 rgba(0,0,0,0.08);
z-index: 25; z-index: 25;
height: 100%;
&__header { &__header {
display: flex; display: flex;
@ -186,22 +187,8 @@
} }
&__connect-btn { &__connect-btn {
background-color: #259De5;
color: #fff;
border: none;
width: 315px; width: 315px;
min-height: 54px; margin: 20px;
font-weight: 300;
font-size: 14px;
margin-bottom: 20px;
margin-top: 20px;
border-radius: 5px;
display: flex;
flex: 1;
margin-left: 20px;
margin-right: 20px;
justify-content: center;
text-transform: uppercase;
} }
&__connect-btn.disabled { &__connect-btn.disabled {
@ -490,29 +477,8 @@
justify-content: space-between; justify-content: space-between;
} }
&__button { &__button:not(:last-child) {
width: 150px; margin-right: 16px;
min-width: initial;
}
.btn-primary {
background-color: #259DE5;
color: #FFFFFF;
border: none;
width: 100%;
min-height: 54px;
font-weight: 300;
font-size: 14px;
margin-bottom: 20px
}
&__button.unlock {
width: 50%;
}
&__button.btn-primary--disabled {
cursor: not-allowed;
opacity: .5;
} }
} }

@ -552,6 +552,7 @@
&__form-field { &__form-field {
flex: 1 1 auto; flex: 1 1 auto;
min-width: 0;
.currency-display { .currency-display {
color: $tundora; color: $tundora;
@ -580,6 +581,7 @@
line-height: 22px; line-height: 22px;
width: 88px; width: 88px;
font-weight: 400; font-weight: 400;
flex: 0 0 auto;
} }
&__from-dropdown { &__from-dropdown {

@ -33,7 +33,7 @@ function reduceMetamask (state, action) {
gasLimit: null, gasLimit: null,
gasPrice: null, gasPrice: null,
gasTotal: null, gasTotal: null,
tokenBalance: null, tokenBalance: '0x0',
from: '', from: '',
to: '', to: '',
amount: '0x0', amount: '0x0',

@ -137,11 +137,12 @@ export const tokenAmountAndToAddressSelector = createSelector(
const valueParam = params.find(param => param.name === TOKEN_PARAM_VALUE) const valueParam = params.find(param => param.name === TOKEN_PARAM_VALUE)
toAddress = toParam ? toParam.value : params[0].value toAddress = toParam ? toParam.value : params[0].value
const value = valueParam ? Number(valueParam.value) : Number(params[1].value) const value = valueParam ? Number(valueParam.value) : Number(params[1].value)
tokenAmount = roundExponential(value)
if (tokenDecimals) { if (tokenDecimals) {
tokenAmount = calcTokenAmount(value, tokenDecimals) tokenAmount = calcTokenAmount(value, tokenDecimals).toNumber()
} }
tokenAmount = roundExponential(tokenAmount)
} }
return { return {
@ -163,7 +164,7 @@ export const approveTokenAmountAndToAddressSelector = createSelector(
const value = Number(params.find(param => param.name === TOKEN_PARAM_VALUE).value) const value = Number(params.find(param => param.name === TOKEN_PARAM_VALUE).value)
if (tokenDecimals) { if (tokenDecimals) {
tokenAmount = calcTokenAmount(value, tokenDecimals) tokenAmount = calcTokenAmount(value, tokenDecimals).toNumber()
} }
tokenAmount = roundExponential(tokenAmount) tokenAmount = roundExponential(tokenAmount)
@ -188,7 +189,7 @@ export const sendTokenTokenAmountAndToAddressSelector = createSelector(
let value = Number(params.find(param => param.name === TOKEN_PARAM_VALUE).value) let value = Number(params.find(param => param.name === TOKEN_PARAM_VALUE).value)
if (tokenDecimals) { if (tokenDecimals) {
value = calcTokenAmount(value, tokenDecimals) value = calcTokenAmount(value, tokenDecimals).toNumber()
} }
tokenAmount = roundExponential(value) tokenAmount = roundExponential(value)

@ -109,7 +109,7 @@ export function tokenInfoGetter () {
export function calcTokenAmount (value, decimals) { export function calcTokenAmount (value, decimals) {
const multiplier = Math.pow(10, Number(decimals || 0)) const multiplier = Math.pow(10, Number(decimals || 0))
return new BigNumber(String(value)).div(multiplier).toNumber() return new BigNumber(String(value)).div(multiplier)
} }
export function getTokenValue (tokenParams = []) { export function getTokenValue (tokenParams = []) {

Loading…
Cancel
Save