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/network/createInfuraClient.js
  5. 2
      app/scripts/controllers/transactions/index.js
  6. 2
      app/scripts/controllers/transactions/pending-tx-tracker.js
  7. 4
      app/scripts/controllers/transactions/tx-state-manager.js
  8. 16
      app/scripts/inpage.js
  9. 2
      app/scripts/lib/ens-ipfs/resolver.js
  10. 6
      app/scripts/lib/ens-ipfs/setup.js
  11. 8
      app/scripts/lib/setupFetchDebugging.js
  12. 2
      app/scripts/lib/setupSentry.js
  13. 4
      app/scripts/metamask-controller.js
  14. 27
      app/scripts/migrations/029.js
  15. 41
      app/scripts/migrations/fail-tx.js
  16. 1
      app/scripts/migrations/index.js
  17. 2
      app/scripts/ui.js
  18. 26
      auto-changelog.sh
  19. 2
      development/version-bump.js
  20. 4
      old-ui/app/config.js
  21. 16116
      package-lock.json
  22. 16
      package.json
  23. 8
      test/e2e/beta/metamask-beta-ui.spec.js
  24. 1
      test/lib/mock-tx-gen.js
  25. 1
      test/unit/app/controllers/metamask-controller-test.js
  26. 6
      test/unit/app/controllers/preferences-controller-test.js
  27. 2
      test/unit/app/controllers/transactions/pending-tx-test.js
  28. 48
      test/unit/app/controllers/transactions/tx-controller-test.js
  29. 2
      test/unit/development/sample-changelog.md
  30. 38
      test/unit/migrations/029-test.js
  31. 2
      test/unit/ui/app/reducers/metamask.spec.js
  32. 2
      test/unit/ui/app/selectors.spec.js
  33. 2
      ui/app/actions.js
  34. 19
      ui/app/components/currency-display/currency-display.container.js
  35. 2
      ui/app/components/currency-display/tests/currency-display.container.test.js
  36. 2
      ui/app/components/index.scss
  37. 2
      ui/app/components/menu-bar/menu-bar.component.js
  38. 2
      ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js
  39. 2
      ui/app/components/pages/create-account/connect-hardware/account-list.js
  40. 16
      ui/app/components/pages/create-account/connect-hardware/connect-screen.js
  41. 4
      ui/app/components/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js
  42. 25
      ui/app/components/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js
  43. 2
      ui/app/components/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js
  44. 5
      ui/app/components/send/send-content/send-amount-row/send-amount-row.component.js
  45. 4
      ui/app/components/send/send-content/send-amount-row/send-amount-row.container.js
  46. 1
      ui/app/components/send/send-content/send-amount-row/tests/send-amount-row-component.test.js
  47. 4
      ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.component.js
  48. 5
      ui/app/components/send/send-content/send-from-row/send-from-row.component.js
  49. 10
      ui/app/components/send/send-content/send-from-row/send-from-row.container.js
  50. 4
      ui/app/components/send/send-content/send-gas-row/send-gas-row.component.js
  51. 6
      ui/app/components/send/send-content/send-gas-row/send-gas-row.container.js
  52. 4
      ui/app/components/send/send-content/send-to-row/send-to-row.component.js
  53. 4
      ui/app/components/send/send-footer/send-footer.component.js
  54. 6
      ui/app/components/send/send.component.js
  55. 6
      ui/app/components/send/send.utils.js
  56. 2
      ui/app/components/send/tests/send-component.test.js
  57. 3
      ui/app/components/send/tests/send-utils.test.js
  58. 14
      ui/app/components/token-balance/index.scss
  59. 12
      ui/app/components/token-balance/token-balance.component.js
  60. 15
      ui/app/components/token-currency-display/token-currency-display.component.js
  61. 8
      ui/app/components/token-input/token-input.component.js
  62. 2
      ui/app/components/transaction-list-item/index.scss
  63. 26
      ui/app/components/transaction-view-balance/index.scss
  64. 12
      ui/app/components/transaction-view-balance/transaction-view-balance.component.js
  65. 4
      ui/app/components/unit-input/index.scss
  66. 2
      ui/app/components/unit-input/unit-input.component.js
  67. 2
      ui/app/conversion-util.js
  68. 42
      ui/app/css/itcss/components/new-account.scss
  69. 2
      ui/app/css/itcss/components/send.scss
  70. 2
      ui/app/reducers/metamask.js
  71. 9
      ui/app/selectors/confirm-transaction.js
  72. 2
      ui/app/token-util.js

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

@ -2,7 +2,11 @@
## 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.
- Fixed a bug that could cause an error when sending the max number of tokens.
## 5.0.2 Friday November 9 2018

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

@ -28,7 +28,7 @@ function createInfuraClient ({ network }) {
return { networkMiddleware, blockTracker }
}
function createNetworkAndChainIdMiddleware({ network }) {
function createNetworkAndChainIdMiddleware ({ network }) {
let chainId
let netId

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

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

@ -1,5 +1,5 @@
const extend = require('xtend')
const EventEmitter = require('events')
const EventEmitter = require('safe-event-emitter')
const ObservableStore = require('obs-store')
const ethUtil = require('ethereumjs-util')
const log = require('loglevel')
@ -86,7 +86,7 @@ class TransactionStateManager extends EventEmitter {
@returns {array} the tx list whos status is approved if no address is provide
returns all txMetas who's status is approved for the current network
*/
getApprovedTransactions(address) {
getApprovedTransactions (address) {
const opts = { status: 'approved' }
if (address) opts.from = address
return this.getFilteredTxList(opts)

@ -29,7 +29,7 @@ console.warn('ATTENTION: In an effort to improve user privacy, MetaMask ' +
* @param {Function} handler - event handler
* @param {boolean} remove - removes this handler after being triggered
*/
function onMessage(messageType, handler, remove) {
function onMessage (messageType, handler, remove) {
window.addEventListener('message', function ({ data }) {
if (!data || data.type !== messageType) { return }
remove && window.removeEventListener('message', handler)
@ -59,7 +59,9 @@ onMessage('metamasksetlocked', () => { isEnabled = false })
// set up a listener for privacy mode responses
onMessage('ethereumproviderlegacy', ({ data: { selectedAddress } }) => {
isEnabled = true
inpageProvider.publicConfigStore.updateState({ selectedAddress })
setTimeout(() => {
inpageProvider.publicConfigStore.updateState({ selectedAddress })
}, 0)
}, true)
// augment the provider with its enable method
@ -70,7 +72,9 @@ inpageProvider.enable = function ({ force } = {}) {
reject(error)
} else {
window.removeEventListener('message', providerHandle)
inpageProvider.publicConfigStore.updateState({ selectedAddress })
setTimeout(() => {
inpageProvider.publicConfigStore.updateState({ selectedAddress })
}, 0)
// wait for the background to update with an account
inpageProvider.sendAsync({ method: 'eth_accounts', params: [] }, (error, response) => {
@ -104,7 +108,7 @@ inpageProvider._metamask = new Proxy({
*
* @returns {Promise<boolean>} - Promise resolving to true if this domain has been previously approved
*/
isApproved: function() {
isApproved: function () {
return new Promise((resolve) => {
isApprovedHandle = ({ data: { caching, isApproved } }) => {
if (caching) {
@ -133,7 +137,7 @@ inpageProvider._metamask = new Proxy({
})
},
}, {
get: function(obj, prop) {
get: function (obj, prop) {
!warned && console.warn('Heads up! ethereum._metamask exposes methods that have ' +
'not been standardized yet. This means that these methods may not be implemented ' +
'in other dapp browsers and may be removed from MetaMask in the future.')
@ -153,7 +157,7 @@ const proxiedInpageProvider = new Proxy(inpageProvider, {
window.ethereum = proxiedInpageProvider
// detect eth_requestAccounts and pipe to enable for now
function detectAccountRequest(method) {
function detectAccountRequest (method) {
const originalMethod = inpageProvider[method]
inpageProvider[method] = function ({ method }) {
if (method === 'eth_requestAccounts') {

@ -38,7 +38,7 @@ async function resolveEnsToIpfsContentId ({ provider, name }) {
return contentId
}
function hexValueIsEmpty(value) {
function hexValueIsEmpty (value) {
return [undefined, null, '0x', '0x0', '0x0000000000000000000000000000000000000000000000000000000000000000'].includes(value)
}

@ -6,7 +6,7 @@ const supportedTopLevelDomains = ['eth']
module.exports = setupEnsIpfsResolver
function setupEnsIpfsResolver({ provider }) {
function setupEnsIpfsResolver ({ provider }) {
// install listener
const urlPatterns = supportedTopLevelDomains.map(tld => `*://*.${tld}/*`)
@ -35,11 +35,11 @@ function setupEnsIpfsResolver({ provider }) {
attemptResolve({ tabId, name, path, search })
}
async function attemptResolve({ tabId, name, path, search }) {
async function attemptResolve ({ tabId, name, path, search }) {
extension.tabs.update(tabId, { url: `loading.html` })
try {
const ipfsContentId = await resolveEnsToIpfsContentId({ provider, name })
let url = `https://gateway.ipfs.io/ipfs/${ipfsContentId}${path}${search || ''}`
const url = `https://gateway.ipfs.io/ipfs/${ipfsContentId}${path}${search || ''}`
try {
// check if ipfs gateway has result
const response = await fetch(url, { method: 'HEAD' })

@ -6,13 +6,13 @@ module.exports = setupFetchDebugging
// https://github.com/getsentry/sentry-javascript/pull/1293
//
function setupFetchDebugging() {
function setupFetchDebugging () {
if (!global.fetch) return
const originalFetch = global.fetch
global.fetch = wrappedFetch
async function wrappedFetch(...args) {
async function wrappedFetch (...args) {
const initialStack = getCurrentStack()
try {
return await originalFetch.call(window, ...args)
@ -20,14 +20,14 @@ function setupFetchDebugging() {
if (!err.stack) {
console.warn('FetchDebugger - fetch encountered an Error without a stack', err)
console.warn('FetchDebugger - overriding stack to point of original call')
err.stack = initialStack
err.stack = initialStack
}
throw err
}
}
}
function getCurrentStack() {
function getCurrentStack () {
try {
throw new Error('Fake error for generating stack trace')
} catch (err) {

@ -32,7 +32,7 @@ function setupSentry (opts) {
scope.setExtra('isBrave', isBrave)
})
function rewriteReport(report) {
function rewriteReport (report) {
try {
// simplify certain complex error messages (e.g. Ethjs)
simplifyErrorMessages(report)

@ -200,7 +200,7 @@ module.exports = class MetamaskController extends EventEmitter {
this.networkController.on('networkDidChange', () => {
this.balancesController.updateAllBalances()
var currentCurrency = this.currencyController.getCurrentCurrency()
this.setCurrentCurrency(currentCurrency, function() {})
this.setCurrentCurrency(currentCurrency, function () {})
})
this.balancesController.updateAllBalances()
@ -1581,7 +1581,7 @@ module.exports = class MetamaskController extends EventEmitter {
/**
* Locks MetaMask
*/
setLocked() {
setLocked () {
this.providerApprovalController.setLocked()
return this.keyringController.setLocked()
}

@ -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('./027'),
require('./028'),
require('./029'),
]

@ -23,7 +23,7 @@ async function start () {
const release = global.platform.getVersion()
setupSentry({ release, getState })
// provide app state to append to error logs
function getState() {
function getState () {
// get app state
const state = window.getCleanAppState()
// remove unnecessary data

@ -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 logLines = changelog.split('\n')
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)
break
}

@ -222,7 +222,7 @@ ConfigScreen.prototype.render = function () {
},
}, 'Clear privacy data'),
]),
h('hr.horizontal-line'),
h('div', {
@ -253,7 +253,7 @@ ConfigScreen.prototype.render = function () {
'Enable privacy mode'
),
]),
h('hr.horizontal-line'),
h('div', {

16116
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -49,7 +49,8 @@
"disc": "gulp disc --debug",
"announce": "node development/announcer.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": {
"transform": [
@ -119,7 +120,7 @@
"eth-hd-keyring": "^1.2.2",
"eth-json-rpc-filters": "^3.0.1",
"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-method-registry": "^1.0.0",
"eth-phishing-detect": "^1.1.4",
@ -166,7 +167,7 @@
"lodash.uniqby": "^4.7.0",
"loglevel": "^1.4.1",
"metamascara": "^2.0.0",
"metamask-inpage-provider": "^1.2.2",
"metamask-inpage-provider": "^1.3.0",
"metamask-logo": "^2.1.4",
"mkdirp": "^0.5.1",
"multihashes": "^0.4.12",
@ -211,6 +212,7 @@
"redux-thunk": "^2.2.0",
"request-promise": "^4.2.1",
"reselect": "^3.0.1",
"safe-event-emitter": "^1.0.1",
"sandwich-expando": "^1.1.3",
"semaphore": "^1.0.5",
"semver": "^5.4.1",
@ -268,14 +270,14 @@
"fs-extra": "^6.0.1",
"fs-promise": "^2.0.3",
"ganache-cli": "^6.1.0",
"ganache-core": "^2.1.5",
"geckodriver": "^1.11.0",
"ganache-core": "^2.2.1",
"geckodriver": "^1.14.1",
"gh-pages": "^1.2.0",
"gifencoder": "^1.1.0",
"gulp": "github:gulpjs/gulp#6d71a658c61edb3090221579d8f97dbe086ba2ed",
"gulp-babel": "^7.0.0",
"gulp-json-editor": "^2.2.1",
"gulp-livereload": "^3.8.1",
"gulp-livereload": "^4.0.0",
"gulp-multi-process": "^1.3.1",
"gulp-replace": "^0.6.1",
"gulp-sourcemaps": "^2.6.0",
@ -293,7 +295,7 @@
"jsdom": "^11.2.0",
"jsdom-global": "^3.0.2",
"jshint-stylish": "~2.2.1",
"karma": "^2.0.4",
"karma": "^3.1.1",
"karma-chrome-launcher": "^2.2.0",
"karma-cli": "^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 () => {
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*$/))
const tokenAmount = await balance.getText()
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,
// or possibly until we use latest version of firefox in the tests
if (process.env.SELENIUM_BROWSER !== 'firefox') {
const tokenBalanceAmount = await findElement(driver, By.css('.transaction-view-balance__token-balance'))
assert.equal(await tokenBalanceAmount.getText(), '43 TST')
const tokenBalanceAmount = await findElements(driver, By.css('.transaction-view-balance__primary-balance'))
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 () => {
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 delay(regularDelayMs)
})

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

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

@ -515,14 +515,14 @@ describe('preferences controller', function () {
it('should add custom RPC url to state', function () {
preferencesController.addToFrequentRpcList('rpc_url', 1)
preferencesController.addToFrequentRpcList('http://localhost:8545', 1)
assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }] )
assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }])
preferencesController.addToFrequentRpcList('rpc_url', 1)
assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }] )
assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }])
})
it('should remove custom RPC url from state', function () {
preferencesController.addToFrequentRpcList('rpc_url', 1)
assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }] )
assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }])
preferencesController.removeFromFrequentRpcList('other_rpc_url')
preferencesController.removeFromFrequentRpcList('http://localhost:8545')
preferencesController.removeFromFrequentRpcList('rpc_url')

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

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

@ -1,6 +1,6 @@
# Changelog
## Current Master
## Current Develop Branch
## 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)
})
})

@ -5,7 +5,7 @@ import * as actions from '../../../../../ui/app/actions'
describe('MetaMask Reducers', () => {
it('init state', () => {
const initState = reduceMetamask({metamask:{}}, {})
const initState = reduceMetamask({metamask: {}}, {})
assert(initState)
})

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

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

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

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

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

@ -52,7 +52,7 @@ export default class MenuBar extends PureComponent {
{
accountDetailsMenuOpen && (
<AccountDetailsDropdown
className="menu-bar__account-details-dropdown"
className="menu-bar__account-details-dropdown"
onClose={() => this.setState({ accountDetailsMenuOpen: false })}
/>
)

@ -348,7 +348,7 @@ export default class ConfirmTransactionBase extends Component {
/>
)
}
handleNextTx (txId) {
const { history, clearConfirmTransaction } = this.props
if (txId) {

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

@ -45,11 +45,13 @@ class ConnectScreen extends Component {
this.renderConnectToLedgerButton(),
this.renderConnectToTrezorButton(),
]),
h(
`button.hw-connect__connect-btn${!this.state.selectedDevice ? '.disabled' : ''}`,
{ onClick: this.connect },
this.context.t('connect')
),
h(Button, {
type: 'confirm',
large: true,
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({
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,
setMaxModeTo: PropTypes.func,
tokenBalance: PropTypes.string,
};
}
static contextTypes = {
t: PropTypes.func,
};
}
setMaxAmount () {
const {

@ -5,16 +5,23 @@ const {
const ethUtil = require('ethereumjs-util')
function calcMaxAmount ({ balance, gasTotal, selectedToken, tokenBalance }) {
const { decimals } = selectedToken || {}
const multiplier = Math.pow(10, Number(decimals || 0))
const { decimals } = selectedToken || {}
const multiplier = Math.pow(10, Number(decimals || 0))
return selectedToken
? multiplyCurrencies(tokenBalance, multiplier, {toNumericBase: 'hex'})
: subtractCurrencies(
ethUtil.addHexPrefix(balance),
ethUtil.addHexPrefix(gasTotal),
{ toNumericBase: 'hex' }
)
return selectedToken
? multiplyCurrencies(
tokenBalance,
multiplier,
{
toNumericBase: 'hex',
multiplicandBase: 16,
}
)
: subtractCurrencies(
ethUtil.addHexPrefix(balance),
ethUtil.addHexPrefix(gasTotal),
{ toNumericBase: 'hex' }
)
}
module.exports = {

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

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

@ -45,10 +45,10 @@ function mapDispatchToProps (dispatch) {
setMaxModeTo: bool => dispatch(setMaxModeTo(bool)),
updateSendAmount: newAmount => dispatch(updateSendAmount(newAmount)),
updateGasFeeError: (amountDataObject) => {
dispatch(updateSendErrors(getGasFeeErrorObject(amountDataObject)))
dispatch(updateSendErrors(getGasFeeErrorObject(amountDataObject)))
},
updateSendAmountError: (amountDataObject) => {
dispatch(updateSendErrors(getAmountErrorObject(amountDataObject)))
dispatch(updateSendErrors(getAmountErrorObject(amountDataObject)))
},
}
}

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

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

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

@ -10,8 +10,8 @@ import {
} from './send-from-row.selectors.js'
import { calcTokenBalance } from '../../send.utils.js'
import {
updateSendFrom,
setSendTokenBalance,
updateSendFrom,
setSendTokenBalance,
} from '../../../../actions'
import {
closeFromDropdown,
@ -37,10 +37,10 @@ function mapDispatchToProps (dispatch) {
openFromDropdown: () => dispatch(openFromDropdown()),
updateSendFrom: newFrom => dispatch(updateSendFrom(newFrom)),
setSendTokenBalance: (usersToken, selectedToken) => {
if (!usersToken) return
if (!usersToken) return
const tokenBalance = calcTokenBalance({ usersToken, selectedToken })
dispatch(setSendTokenBalance(tokenBalance))
const tokenBalance = calcTokenBalance({ usersToken, selectedToken })
dispatch(setSendTokenBalance(tokenBalance))
},
}
}

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

@ -1,8 +1,8 @@
import { connect } from 'react-redux'
import {
getConversionRate,
getCurrentCurrency,
getGasTotal,
getConversionRate,
getCurrentCurrency,
getGasTotal,
} from '../../send.selectors.js'
import { getGasLoadingError, gasFeeIsInError } from './send-gas-row.selectors.js'
import { showModal } from '../../../../actions'

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

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

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

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

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

@ -285,11 +285,10 @@ describe('send utils', () => {
[
{
value: 123,
fromNumericBase: 'dec',
fromNumericBase: 'hex',
},
{
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 PropTypes from 'prop-types'
import classnames from 'classnames'
import CurrencyDisplay from '../currency-display'
export default class TokenBalance extends PureComponent {
static propTypes = {
@ -12,12 +12,14 @@ export default class TokenBalance extends PureComponent {
}
render () {
const { className, string, withSymbol, symbol } = this.props
const { className, string, symbol } = this.props
return (
<div className={classnames('hide-text-overflow', className)}>
{ string + (withSymbol ? ` ${symbol}` : '') }
</div>
<CurrencyDisplay
className={className}
displayValue={string}
suffix={symbol}
/>
)
}
}

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

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

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

@ -6,6 +6,12 @@
height: 54px;
min-width: 0;
@media screen and (max-width: $break-small) {
flex-direction: column;
height: initial;
width: 100%;
}
&__balance {
margin: 0 12px;
display: flex;
@ -15,17 +21,8 @@
@media screen and (max-width: $break-small) {
align-items: center;
margin: 16px 0;
}
}
&__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;
padding: 0 16px;
max-width: 100%;
}
}
@ -34,6 +31,7 @@
@media screen and (max-width: $break-small) {
font-size: 1.75rem;
width: 100%;
}
}
@ -51,6 +49,7 @@
@media screen and (max-width: $break-small) {
flex-direction: column;
width: 100%;
}
}
@ -71,9 +70,4 @@
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
? (
<TokenBalance
token={selectedToken}
withSymbol
className="transaction-view-balance__token-balance"
/>
<div className="transaction-view-balance__balance">
<TokenBalance
token={selectedToken}
withSymbol
className="transaction-view-balance__primary-balance"
/>
</div>
) : (
<div className="transaction-view-balance__balance">
<UserPreferencedCurrencyDisplay

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

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

@ -62,7 +62,7 @@ const toSpecifiedDenomination = {
}
const baseChange = {
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)),
}

@ -3,6 +3,7 @@
background-color: #FFFFFF;
box-shadow: 0 0 7px 0 rgba(0,0,0,0.08);
z-index: 25;
height: 100%;
&__header {
display: flex;
@ -186,22 +187,8 @@
}
&__connect-btn {
background-color: #259De5;
color: #fff;
border: none;
width: 315px;
min-height: 54px;
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;
margin: 20px;
}
&__connect-btn.disabled {
@ -490,29 +477,8 @@
justify-content: space-between;
}
&__button {
width: 150px;
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;
&__button:not(:last-child) {
margin-right: 16px;
}
}

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

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

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

@ -109,7 +109,7 @@ export function tokenInfoGetter () {
export function calcTokenAmount (value, decimals) {
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 = []) {

Loading…
Cancel
Save