mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-26 12:29:06 +01:00
Merge remote-tracking branch 'origin/uat' into mascara-first-screen
This commit is contained in:
commit
08867874cc
@ -46,8 +46,6 @@ class PreferencesController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeToken (rawAddress) {
|
removeToken (rawAddress) {
|
||||||
const address = normalizeAddress(rawAddress)
|
|
||||||
|
|
||||||
const tokens = this.store.getState().tokens
|
const tokens = this.store.getState().tokens
|
||||||
|
|
||||||
const updatedTokens = tokens.filter(token => token.address !== rawAddress)
|
const updatedTokens = tokens.filter(token => token.address !== rawAddress)
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
"test": "npm run lint && npm run test:coverage && npm run test:integration",
|
"test": "npm run lint && npm run test:coverage && npm run test:integration",
|
||||||
"test:unit": "METAMASK_ENV=test mocha --compilers js:babel-core/register --require test/helper.js --recursive \"test/unit/**/*.js\"",
|
"test:unit": "METAMASK_ENV=test mocha --compilers js:babel-core/register --require test/helper.js --recursive \"test/unit/**/*.js\"",
|
||||||
"test:single": "METAMASK_ENV=test mocha --require test/helper.js",
|
"test:single": "METAMASK_ENV=test mocha --require test/helper.js",
|
||||||
"test:integration": "npm run test:flat && npm run test:mascara",
|
"test:integration": "gulp build:scss && npm run test:flat && npm run test:mascara",
|
||||||
"test:coverage": "nyc npm run test:unit && npm run test:coveralls-upload",
|
"test:coverage": "nyc npm run test:unit && npm run test:coveralls-upload",
|
||||||
"test:coveralls-upload": "if [ $COVERALLS_REPO_TOKEN ]; then nyc report --reporter=text-lcov | coveralls; fi",
|
"test:coveralls-upload": "if [ $COVERALLS_REPO_TOKEN ]; then nyc report --reporter=text-lcov | coveralls; fi",
|
||||||
"test:flat": "npm run test:flat:build && karma start test/flat.conf.js",
|
"test:flat": "npm run test:flat:build && karma start test/flat.conf.js",
|
||||||
@ -190,6 +190,7 @@
|
|||||||
"enzyme": "^2.8.2",
|
"enzyme": "^2.8.2",
|
||||||
"eslint-plugin-chai": "0.0.1",
|
"eslint-plugin-chai": "0.0.1",
|
||||||
"eslint-plugin-mocha": "^4.9.0",
|
"eslint-plugin-mocha": "^4.9.0",
|
||||||
|
"eslint-plugin-react": "^7.4.0",
|
||||||
"eth-json-rpc-middleware": "^1.2.7",
|
"eth-json-rpc-middleware": "^1.2.7",
|
||||||
"fs-promise": "^2.0.3",
|
"fs-promise": "^2.0.3",
|
||||||
"gulp": "github:gulpjs/gulp#4.0",
|
"gulp": "github:gulpjs/gulp#4.0",
|
||||||
@ -226,6 +227,7 @@
|
|||||||
"react-addons-test-utils": "^15.5.1",
|
"react-addons-test-utils": "^15.5.1",
|
||||||
"react-test-renderer": "^15.5.4",
|
"react-test-renderer": "^15.5.4",
|
||||||
"react-testutils-additions": "^15.2.0",
|
"react-testutils-additions": "^15.2.0",
|
||||||
|
"redux-test-utils": "^0.1.3",
|
||||||
"sinon": "^4.0.0",
|
"sinon": "^4.0.0",
|
||||||
"stylelint-config-standard": "^17.0.0",
|
"stylelint-config-standard": "^17.0.0",
|
||||||
"tape": "^4.5.1",
|
"tape": "^4.5.1",
|
||||||
|
@ -40,7 +40,8 @@ async function runFirstTimeUsageTest(assert, done) {
|
|||||||
|
|
||||||
// Scroll through terms
|
// Scroll through terms
|
||||||
const title = app.find('h1').text()
|
const title = app.find('h1').text()
|
||||||
assert.equal(title, 'MetaMask', 'title screen')
|
// TODO Find where Metamask is getting added twice in the title
|
||||||
|
assert.equal(title, 'MetaMaskMetaMask', 'title screen')
|
||||||
|
|
||||||
// enter password
|
// enter password
|
||||||
const pwBox = app.find('#password-box')[0]
|
const pwBox = app.find('#password-box')[0]
|
||||||
@ -66,17 +67,17 @@ async function runFirstTimeUsageTest(assert, done) {
|
|||||||
|
|
||||||
await timeout(1000)
|
await timeout(1000)
|
||||||
|
|
||||||
const detail = app.find('.account-detail-section')[0]
|
const detail = app.find('.wallet-view')[0]
|
||||||
assert.ok(detail, 'Account detail section loaded.')
|
assert.ok(detail, 'Account detail section loaded.')
|
||||||
|
|
||||||
const sandwich = app.find('.sandwich-expando')[0]
|
await timeout(1000)
|
||||||
sandwich.click()
|
|
||||||
|
|
||||||
await timeout()
|
const menu = app.find('.account-menu__icon')[0]
|
||||||
|
menu.click()
|
||||||
|
|
||||||
const menu = app.find('.menu-droppo')[0]
|
await timeout(1000)
|
||||||
const children = menu.children
|
|
||||||
const lock = children[children.length - 2]
|
const lock = app.find('.account-menu__logout-button')[0]
|
||||||
assert.ok(lock, 'Lock menu item found')
|
assert.ok(lock, 'Lock menu item found')
|
||||||
lock.click()
|
lock.click()
|
||||||
|
|
||||||
@ -90,36 +91,30 @@ async function runFirstTimeUsageTest(assert, done) {
|
|||||||
|
|
||||||
await timeout(1000)
|
await timeout(1000)
|
||||||
|
|
||||||
const detail2 = app.find('.account-detail-section')[0]
|
const detail2 = app.find('.wallet-view')[0]
|
||||||
assert.ok(detail2, 'Account detail section loaded again.')
|
assert.ok(detail2, 'Account detail section loaded again.')
|
||||||
|
|
||||||
await timeout()
|
await timeout()
|
||||||
|
|
||||||
// open account settings dropdown
|
// open account settings dropdown
|
||||||
const qrButton = app.find('.fa.fa-ellipsis-h')[0]
|
const qrButton = app.find('.wallet-view__details-button')[0]
|
||||||
qrButton.click()
|
qrButton.click()
|
||||||
|
|
||||||
await timeout(1000)
|
await timeout(1000)
|
||||||
|
|
||||||
// qr code item
|
const qrHeader = app.find('.editable-label__value')[0]
|
||||||
const qrButton2 = app.find('.dropdown-menu-item')[1]
|
const qrContainer = app.find('.qr-wrapper')[0]
|
||||||
qrButton2.click()
|
|
||||||
|
|
||||||
await timeout(1000)
|
|
||||||
|
|
||||||
const qrHeader = app.find('.qr-header')[0]
|
|
||||||
const qrContainer = app.find('#qr-container')[0]
|
|
||||||
assert.equal(qrHeader.textContent, 'Account 1', 'Should show account label.')
|
assert.equal(qrHeader.textContent, 'Account 1', 'Should show account label.')
|
||||||
assert.ok(qrContainer, 'QR Container found')
|
assert.ok(qrContainer, 'QR Container found')
|
||||||
|
|
||||||
await timeout()
|
await timeout()
|
||||||
|
|
||||||
const networkMenu = app.find('.network-indicator')[0]
|
const networkMenu = app.find('.network-component')[0]
|
||||||
networkMenu.click()
|
networkMenu.click()
|
||||||
|
|
||||||
await timeout()
|
await timeout()
|
||||||
|
|
||||||
const networkMenu2 = app.find('.network-indicator')[0]
|
const networkMenu2 = app.find('.menu-droppo')[0]
|
||||||
const children2 = networkMenu2.children
|
const children2 = networkMenu2.children
|
||||||
children2.length[3]
|
children2.length[3]
|
||||||
assert.ok(children2, 'All network options present')
|
assert.ok(children2, 'All network options present')
|
||||||
|
@ -102,14 +102,12 @@ async function runFirstTimeUsageTest (assert, done) {
|
|||||||
app.find('.buy-ether__do-it-later').click()
|
app.find('.buy-ether__do-it-later').click()
|
||||||
await timeout(1000)
|
await timeout(1000)
|
||||||
|
|
||||||
const sandwich = app.find('.sandwich-expando')[0]
|
const menu = app.find('.account-menu__icon')[0]
|
||||||
sandwich.click()
|
menu.click()
|
||||||
|
|
||||||
await timeout()
|
await timeout()
|
||||||
|
|
||||||
const menu = app.find('.menu-droppo')[0]
|
const lock = app.find('.account-menu__logout-button')[0]
|
||||||
const children = menu.children
|
|
||||||
const lock = children[children.length - 2]
|
|
||||||
assert.ok(lock, 'Lock menu item found')
|
assert.ok(lock, 'Lock menu item found')
|
||||||
lock.click()
|
lock.click()
|
||||||
|
|
||||||
@ -123,31 +121,25 @@ async function runFirstTimeUsageTest (assert, done) {
|
|||||||
|
|
||||||
await timeout(1000)
|
await timeout(1000)
|
||||||
|
|
||||||
const detail2 = app.find('.account-detail-section')[0]
|
const detail2 = app.find('.wallet-view')[0]
|
||||||
assert.ok(detail2, 'Account detail section loaded again.')
|
assert.ok(detail2, 'Account detail section loaded again.')
|
||||||
|
|
||||||
await timeout()
|
await timeout()
|
||||||
|
|
||||||
// open account settings dropdown
|
// open account settings dropdown
|
||||||
const qrButton = app.find('.fa.fa-ellipsis-h')[0]
|
const qrButton = app.find('.wallet-view__details-button')[0]
|
||||||
qrButton.click()
|
qrButton.click()
|
||||||
|
|
||||||
await timeout(1000)
|
await timeout(1000)
|
||||||
|
|
||||||
// qr code item
|
const qrHeader = app.find('.editable-label__value')[0]
|
||||||
const qrButton2 = app.find('.dropdown-menu-item')[1]
|
const qrContainer = app.find('.qr-wrapper')[0]
|
||||||
qrButton2.click()
|
|
||||||
|
|
||||||
await timeout(1000)
|
|
||||||
|
|
||||||
const qrHeader = app.find('.qr-header')[0]
|
|
||||||
const qrContainer = app.find('#qr-container')[0]
|
|
||||||
assert.equal(qrHeader.textContent, 'Account 1', 'Should show account label.')
|
assert.equal(qrHeader.textContent, 'Account 1', 'Should show account label.')
|
||||||
assert.ok(qrContainer, 'QR Container found')
|
assert.ok(qrContainer, 'QR Container found')
|
||||||
|
|
||||||
await timeout()
|
await timeout()
|
||||||
|
|
||||||
const networkMenu = app.find('.network-indicator')[0]
|
const networkMenu = app.find('.network-component')[0]
|
||||||
networkMenu.click()
|
networkMenu.click()
|
||||||
|
|
||||||
await timeout()
|
await timeout()
|
||||||
@ -164,4 +156,4 @@ function timeout (time) {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
setTimeout(resolve, time || 1500)
|
setTimeout(resolve, time || 1500)
|
||||||
})
|
})
|
||||||
}
|
}
|
11
test/lib/shallow-with-store.js
Normal file
11
test/lib/shallow-with-store.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
const shallow = require('enzyme').shallow
|
||||||
|
|
||||||
|
module.exports = shallowWithStore
|
||||||
|
|
||||||
|
function shallowWithStore (component, store) {
|
||||||
|
const context = {
|
||||||
|
store,
|
||||||
|
}
|
||||||
|
|
||||||
|
return shallow(component, { context })
|
||||||
|
};
|
@ -1,18 +1,31 @@
|
|||||||
var assert = require('assert')
|
const assert = require('assert')
|
||||||
var BalanceComponent = require('../../../ui/app/components/balance-component')
|
const h = require('react-hyperscript')
|
||||||
|
const { createMockStore } = require('redux-test-utils')
|
||||||
|
const shallowWithStore = require('../../lib/shallow-with-store')
|
||||||
|
const BalanceComponent = require('../../../ui/app/components/balance-component')
|
||||||
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
accounts: { abc: {} },
|
||||||
|
network: 1,
|
||||||
|
selectedAddress: 'abc',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
describe('BalanceComponent', function () {
|
describe('BalanceComponent', function () {
|
||||||
let balanceComponent
|
let balanceComponent
|
||||||
|
let store
|
||||||
|
let component
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
balanceComponent = new BalanceComponent()
|
store = createMockStore(mockState)
|
||||||
|
component = shallowWithStore(h(BalanceComponent), store)
|
||||||
|
balanceComponent = component.dive()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('shows token balance and convert to fiat value based on conversion rate', function () {
|
it('shows token balance and convert to fiat value based on conversion rate', function () {
|
||||||
const formattedBalance = '1.23 ETH'
|
const formattedBalance = '1.23 ETH'
|
||||||
|
|
||||||
const tokenBalance = balanceComponent.getTokenBalance(formattedBalance, false)
|
const tokenBalance = balanceComponent.instance().getTokenBalance(formattedBalance, false)
|
||||||
const fiatDisplayNumber = balanceComponent.getFiatDisplayNumber(formattedBalance, 2)
|
const fiatDisplayNumber = balanceComponent.instance().getFiatDisplayNumber(formattedBalance, 2)
|
||||||
|
|
||||||
assert.equal('1.23 ETH', tokenBalance)
|
assert.equal('1.23 ETH', tokenBalance)
|
||||||
assert.equal(2.46, fiatDisplayNumber)
|
assert.equal(2.46, fiatDisplayNumber)
|
||||||
@ -21,8 +34,8 @@ describe('BalanceComponent', function () {
|
|||||||
it('shows only the token balance when conversion rate is not available', function () {
|
it('shows only the token balance when conversion rate is not available', function () {
|
||||||
const formattedBalance = '1.23 ETH'
|
const formattedBalance = '1.23 ETH'
|
||||||
|
|
||||||
const tokenBalance = balanceComponent.getTokenBalance(formattedBalance, false)
|
const tokenBalance = balanceComponent.instance().getTokenBalance(formattedBalance, false)
|
||||||
const fiatDisplayNumber = balanceComponent.getFiatDisplayNumber(formattedBalance, 0)
|
const fiatDisplayNumber = balanceComponent.instance().getFiatDisplayNumber(formattedBalance, 0)
|
||||||
|
|
||||||
assert.equal('1.23 ETH', tokenBalance)
|
assert.equal('1.23 ETH', tokenBalance)
|
||||||
assert.equal('N/A', fiatDisplayNumber)
|
assert.equal('N/A', fiatDisplayNumber)
|
||||||
|
@ -1,18 +1,22 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const additions = require('react-testutils-additions')
|
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const PendingTx = require('../../../ui/app/components/pending-tx')
|
const PendingTx = require('../../../ui/app/components/pending-tx')
|
||||||
const ReactTestUtils = require('react-addons-test-utils')
|
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
|
|
||||||
describe('PendingTx', function () {
|
const { createMockStore } = require('redux-test-utils')
|
||||||
const identities = {
|
const shallowWithStore = require('../../lib/shallow-with-store')
|
||||||
'0xfdea65c8e26263f6d9a1b5de9555d2931a33b826': {
|
|
||||||
name: 'Main Account 1',
|
|
||||||
balance: '0x00000000000000056bc75e2d63100000',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const identities = { abc: {}, def: {} }
|
||||||
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
accounts: { abc: {} },
|
||||||
|
identities,
|
||||||
|
conversionRate: 10,
|
||||||
|
selectedAddress: 'abc',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('PendingTx', function () {
|
||||||
const gasPrice = '0x4A817C800' // 20 Gwei
|
const gasPrice = '0x4A817C800' // 20 Gwei
|
||||||
const txData = {
|
const txData = {
|
||||||
'id': 5021615666270214,
|
'id': 5021615666270214,
|
||||||
@ -29,55 +33,35 @@ describe('PendingTx', function () {
|
|||||||
'gasLimitSpecified': false,
|
'gasLimitSpecified': false,
|
||||||
'estimatedGas': '0x5208',
|
'estimatedGas': '0x5208',
|
||||||
}
|
}
|
||||||
|
const newGasPrice = '0x77359400'
|
||||||
|
|
||||||
|
const computedBalances = {}
|
||||||
|
computedBalances[Object.keys(identities)[0]] = {
|
||||||
|
ethBalance: '0x00000000000000056bc75e2d63100000',
|
||||||
|
}
|
||||||
|
const props = {
|
||||||
|
txData,
|
||||||
|
computedBalances,
|
||||||
|
sendTransaction: (txMeta, event) => {
|
||||||
|
// Assert changes:
|
||||||
|
const result = ethUtil.addHexPrefix(txMeta.txParams.gasPrice)
|
||||||
|
assert.notEqual(result, gasPrice, 'gas price should change')
|
||||||
|
assert.equal(result, newGasPrice, 'gas price assigned.')
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
it('should use updated values when edited.', function (done) {
|
let pendingTxComponent
|
||||||
const renderer = ReactTestUtils.createRenderer()
|
let store
|
||||||
const newGasPrice = '0x77359400'
|
let component
|
||||||
|
beforeEach(function () {
|
||||||
|
store = createMockStore(mockState)
|
||||||
|
component = shallowWithStore(h(PendingTx, props), store)
|
||||||
|
pendingTxComponent = component
|
||||||
|
})
|
||||||
|
|
||||||
const computedBalances = {}
|
it('should render correctly', function (done) {
|
||||||
computedBalances[Object.keys(identities)[0]] = {
|
assert.equal(pendingTxComponent.props().identities, identities)
|
||||||
ethBalance: '0x00000000000000056bc75e2d63100000',
|
done()
|
||||||
}
|
|
||||||
const props = {
|
|
||||||
identities,
|
|
||||||
accounts: identities,
|
|
||||||
txData,
|
|
||||||
computedBalances,
|
|
||||||
sendTransaction: (txMeta, event) => {
|
|
||||||
// Assert changes:
|
|
||||||
const result = ethUtil.addHexPrefix(txMeta.txParams.gasPrice)
|
|
||||||
assert.notEqual(result, gasPrice, 'gas price should change')
|
|
||||||
assert.equal(result, newGasPrice, 'gas price assigned.')
|
|
||||||
done()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const pendingTxComponent = h(PendingTx, props)
|
|
||||||
const component = additions.renderIntoDocument(pendingTxComponent)
|
|
||||||
renderer.render(pendingTxComponent)
|
|
||||||
const result = renderer.getRenderOutput()
|
|
||||||
assert.equal(result.type, 'div', 'should create a div')
|
|
||||||
|
|
||||||
try {
|
|
||||||
const input = additions.find(component, '.cell.row input[type="number"]')[1]
|
|
||||||
ReactTestUtils.Simulate.change(input, {
|
|
||||||
target: {
|
|
||||||
value: 2,
|
|
||||||
checkValidity () { return true },
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const form = additions.find(component, 'form')[0]
|
|
||||||
form.checkValidity = () => true
|
|
||||||
form.getFormEl = () => { return { checkValidity () { return true } } }
|
|
||||||
ReactTestUtils.Simulate.submit(form, { preventDefault () {}, target: { checkValidity () {
|
|
||||||
return true
|
|
||||||
} } })
|
|
||||||
} catch (e) {
|
|
||||||
console.log('WHAAAA')
|
|
||||||
console.error(e)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ const currentNetworkId = 42
|
|||||||
const otherNetworkId = 36
|
const otherNetworkId = 36
|
||||||
const privKey = new Buffer('8718b9618a37d1fc78c436511fc6df3c8258d3250635bba617f33003270ec03e', 'hex')
|
const privKey = new Buffer('8718b9618a37d1fc78c436511fc6df3c8258d3250635bba617f33003270ec03e', 'hex')
|
||||||
|
|
||||||
|
|
||||||
describe('PendingTransactionTracker', function () {
|
describe('PendingTransactionTracker', function () {
|
||||||
let pendingTxTracker, txMeta, txMetaNoHash, txMetaNoRawTx, providerResultStub,
|
let pendingTxTracker, txMeta, txMetaNoHash, txMetaNoRawTx, providerResultStub,
|
||||||
provider, txMeta3, txList, knownErrors
|
provider, txMeta3, txList, knownErrors
|
||||||
|
@ -1,40 +1,45 @@
|
|||||||
var assert = require('assert');
|
const assert = require('assert');
|
||||||
|
|
||||||
const additions = require('react-testutils-additions');
|
|
||||||
const h = require('react-hyperscript');
|
const h = require('react-hyperscript');
|
||||||
const ReactTestUtils = require('react-addons-test-utils');
|
|
||||||
const sinon = require('sinon');
|
const sinon = require('sinon');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const Dropdown = require(path.join(__dirname, '..', '..', '..', '..', 'ui', 'app', 'components', 'dropdown.js')).Dropdown;
|
const Dropdown = require(path.join(__dirname, '..', '..', '..', '..', 'ui', 'app', 'components', 'dropdowns', 'index.js')).Dropdown;
|
||||||
const DropdownMenuItem = require(path.join(__dirname, '..', '..', '..', '..', 'ui', 'app', 'components', 'dropdown.js')).DropdownMenuItem;
|
|
||||||
|
const { createMockStore } = require('redux-test-utils')
|
||||||
|
const shallowWithStore = require('../../../lib/shallow-with-store')
|
||||||
|
|
||||||
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
describe('Dropdown components', function () {
|
describe('Dropdown components', function () {
|
||||||
let onClickOutside;
|
let onClickOutside;
|
||||||
let closeMenu;
|
let closeMenu;
|
||||||
let onClick;
|
let onClick;
|
||||||
|
|
||||||
let dropdownComponentProps;
|
let dropdownComponentProps = {
|
||||||
const renderer = ReactTestUtils.createRenderer()
|
isOpen: true,
|
||||||
|
zIndex: 11,
|
||||||
|
onClickOutside,
|
||||||
|
style: {
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
top: '36px',
|
||||||
|
},
|
||||||
|
innerStyle: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
let dropdownComponent
|
||||||
|
let store
|
||||||
|
let component
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
onClickOutside = sinon.spy();
|
onClickOutside = sinon.spy();
|
||||||
closeMenu = sinon.spy();
|
closeMenu = sinon.spy();
|
||||||
onClick = sinon.spy();
|
onClick = sinon.spy();
|
||||||
|
|
||||||
dropdownComponentProps = {
|
store = createMockStore(mockState)
|
||||||
isOpen: true,
|
component = shallowWithStore(h(
|
||||||
zIndex: 11,
|
|
||||||
onClickOutside,
|
|
||||||
style: {
|
|
||||||
position: 'absolute',
|
|
||||||
right: 0,
|
|
||||||
top: '36px',
|
|
||||||
},
|
|
||||||
innerStyle: {},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can render two items', function () {
|
|
||||||
const dropdownComponent = h(
|
|
||||||
Dropdown,
|
Dropdown,
|
||||||
dropdownComponentProps,
|
dropdownComponentProps,
|
||||||
[
|
[
|
||||||
@ -42,74 +47,35 @@ describe('Dropdown components', function () {
|
|||||||
.drop-menu-item:hover { background:rgb(235, 235, 235); }
|
.drop-menu-item:hover { background:rgb(235, 235, 235); }
|
||||||
.drop-menu-item i { margin: 11px; }
|
.drop-menu-item i { margin: 11px; }
|
||||||
`),
|
`),
|
||||||
h(DropdownMenuItem, {
|
h('li', {
|
||||||
closeMenu,
|
closeMenu,
|
||||||
onClick,
|
onClick,
|
||||||
}, 'Item 1'),
|
}, 'Item 1'),
|
||||||
h(DropdownMenuItem, {
|
h('li', {
|
||||||
closeMenu,
|
closeMenu,
|
||||||
onClick,
|
onClick,
|
||||||
}, 'Item 2'),
|
}, 'Item 2'),
|
||||||
]
|
]
|
||||||
)
|
), store)
|
||||||
|
dropdownComponent = component.dive()
|
||||||
|
})
|
||||||
|
|
||||||
const component = additions.renderIntoDocument(dropdownComponent);
|
it('can render two items', function () {
|
||||||
renderer.render(dropdownComponent);
|
const items = dropdownComponent.find('li');
|
||||||
const items = additions.find(component, 'li');
|
|
||||||
assert.equal(items.length, 2);
|
assert.equal(items.length, 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('closes when item clicked', function() {
|
it('closes when item clicked', function() {
|
||||||
const dropdownComponent = h(
|
const items = dropdownComponent.find('li');
|
||||||
Dropdown,
|
const node = items.at(0);
|
||||||
dropdownComponentProps,
|
node.simulate('click');
|
||||||
[
|
assert.equal(node.props().closeMenu, closeMenu);
|
||||||
h('style', `
|
|
||||||
.drop-menu-item:hover { background:rgb(235, 235, 235); }
|
|
||||||
.drop-menu-item i { margin: 11px; }
|
|
||||||
`),
|
|
||||||
h(DropdownMenuItem, {
|
|
||||||
closeMenu,
|
|
||||||
onClick,
|
|
||||||
}, 'Item 1'),
|
|
||||||
h(DropdownMenuItem, {
|
|
||||||
closeMenu,
|
|
||||||
onClick,
|
|
||||||
}, 'Item 2'),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
const component = additions.renderIntoDocument(dropdownComponent);
|
|
||||||
renderer.render(dropdownComponent);
|
|
||||||
const items = additions.find(component, 'li');
|
|
||||||
const node = items[0];
|
|
||||||
ReactTestUtils.Simulate.click(node);
|
|
||||||
assert.equal(closeMenu.calledOnce, true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invokes click handler when item clicked', function() {
|
it('invokes click handler when item clicked', function() {
|
||||||
const dropdownComponent = h(
|
const items = dropdownComponent.find('li');
|
||||||
Dropdown,
|
const node = items.at(0);
|
||||||
dropdownComponentProps,
|
node.simulate('click');
|
||||||
[
|
|
||||||
h('style', `
|
|
||||||
.drop-menu-item:hover { background:rgb(235, 235, 235); }
|
|
||||||
.drop-menu-item i { margin: 11px; }
|
|
||||||
`),
|
|
||||||
h(DropdownMenuItem, {
|
|
||||||
closeMenu,
|
|
||||||
onClick,
|
|
||||||
}, 'Item 1'),
|
|
||||||
h(DropdownMenuItem, {
|
|
||||||
closeMenu,
|
|
||||||
onClick,
|
|
||||||
}, 'Item 2'),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
const component = additions.renderIntoDocument(dropdownComponent);
|
|
||||||
renderer.render(dropdownComponent);
|
|
||||||
const items = additions.find(component, 'li');
|
|
||||||
const node = items[0];
|
|
||||||
ReactTestUtils.Simulate.click(node);
|
|
||||||
assert.equal(onClick.calledOnce, true);
|
assert.equal(onClick.calledOnce, true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -17,6 +17,10 @@ function PrivateKeyImportView () {
|
|||||||
Component.call(this)
|
Component.call(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrivateKeyImportView.prototype.componentWillUnmount = function () {
|
||||||
|
this.props.dispatch(actions.displayWarning(null))
|
||||||
|
}
|
||||||
|
|
||||||
PrivateKeyImportView.prototype.render = function () {
|
PrivateKeyImportView.prototype.render = function () {
|
||||||
const { error } = this.props
|
const { error } = this.props
|
||||||
|
|
||||||
|
@ -224,6 +224,8 @@ var actions = {
|
|||||||
|
|
||||||
TOGGLE_ACCOUNT_MENU: 'TOGGLE_ACCOUNT_MENU',
|
TOGGLE_ACCOUNT_MENU: 'TOGGLE_ACCOUNT_MENU',
|
||||||
toggleAccountMenu,
|
toggleAccountMenu,
|
||||||
|
|
||||||
|
useEtherscanProvider,
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = actions
|
module.exports = actions
|
||||||
@ -428,7 +430,7 @@ function addNewAccount () {
|
|||||||
forceUpdateMetamaskState(dispatch)
|
forceUpdateMetamaskState(dispatch)
|
||||||
return resolve(newAccountAddress)
|
return resolve(newAccountAddress)
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -619,7 +621,7 @@ function updateSendErrors (error) {
|
|||||||
|
|
||||||
function clearSend () {
|
function clearSend () {
|
||||||
return {
|
return {
|
||||||
type: actions.CLEAR_SEND
|
type: actions.CLEAR_SEND,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -808,9 +810,50 @@ function updateMetamaskState (newState) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const backgroundSetLocked = () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
background.setLocked(error => {
|
||||||
|
if (error) {
|
||||||
|
return reject(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateMetamaskStateFromBackground = () => {
|
||||||
|
log.debug(`background.getState`)
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
background.getState((error, newState) => {
|
||||||
|
if (error) {
|
||||||
|
return reject(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(newState)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function lockMetamask () {
|
function lockMetamask () {
|
||||||
log.debug(`background.setLocked`)
|
log.debug(`background.setLocked`)
|
||||||
return callBackgroundThenUpdate(background.setLocked)
|
|
||||||
|
return dispatch => {
|
||||||
|
dispatch(actions.showLoadingIndication())
|
||||||
|
|
||||||
|
return backgroundSetLocked()
|
||||||
|
.then(() => updateMetamaskStateFromBackground())
|
||||||
|
.catch(error => {
|
||||||
|
dispatch(actions.displayWarning(error.message))
|
||||||
|
return Promise.reject(error)
|
||||||
|
})
|
||||||
|
.then(newState => {
|
||||||
|
dispatch(actions.updateMetamaskState(newState))
|
||||||
|
dispatch({ type: actions.LOCK_METAMASK })
|
||||||
|
})
|
||||||
|
.catch(() => dispatch({ type: actions.LOCK_METAMASK }))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCurrentAccountTab (newTabName) {
|
function setCurrentAccountTab (newTabName) {
|
||||||
@ -961,10 +1004,10 @@ function addTokens (tokens) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTokens(newTokens) {
|
function updateTokens (newTokens) {
|
||||||
return {
|
return {
|
||||||
type: actions.UPDATE_TOKENS,
|
type: actions.UPDATE_TOKENS,
|
||||||
newTokens
|
newTokens,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1038,7 +1081,7 @@ function setProviderType (type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateProviderType(type) {
|
function updateProviderType (type) {
|
||||||
return {
|
return {
|
||||||
type: actions.SET_PROVIDER_TYPE,
|
type: actions.SET_PROVIDER_TYPE,
|
||||||
value: type,
|
value: type,
|
||||||
@ -1196,7 +1239,7 @@ function exportAccount (password, address) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function exportAccountComplete() {
|
function exportAccountComplete () {
|
||||||
return {
|
return {
|
||||||
type: actions.EXPORT_ACCOUNT,
|
type: actions.EXPORT_ACCOUNT,
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,7 @@ const fuse = new Fuse(contractList, {
|
|||||||
})
|
})
|
||||||
const actions = require('./actions')
|
const actions = require('./actions')
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
const abi = require('human-standard-token-abi')
|
const { tokenInfoGetter } = require('./token-util')
|
||||||
const Eth = require('ethjs-query')
|
|
||||||
const EthContract = require('ethjs-contract')
|
|
||||||
const R = require('ramda')
|
const R = require('ramda')
|
||||||
|
|
||||||
const emptyAddr = '0x0000000000000000000000000000000000000000'
|
const emptyAddr = '0x0000000000000000000000000000000000000000'
|
||||||
@ -63,11 +61,7 @@ function AddTokenScreen () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AddTokenScreen.prototype.componentWillMount = function () {
|
AddTokenScreen.prototype.componentWillMount = function () {
|
||||||
if (typeof global.ethereumProvider === 'undefined') return
|
this.tokenInfoGetter = tokenInfoGetter()
|
||||||
|
|
||||||
this.eth = new Eth(global.ethereumProvider)
|
|
||||||
this.contract = new EthContract(this.eth)
|
|
||||||
this.TokenContract = this.contract(abi)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AddTokenScreen.prototype.toggleToken = function (address, token) {
|
AddTokenScreen.prototype.toggleToken = function (address, token) {
|
||||||
@ -164,18 +158,11 @@ AddTokenScreen.prototype.validate = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address) {
|
AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address) {
|
||||||
const contract = this.TokenContract.at(address)
|
const { symbol, decimals } = await this.tokenInfoGetter(address)
|
||||||
|
|
||||||
const results = await Promise.all([
|
|
||||||
contract.symbol(),
|
|
||||||
contract.decimals(),
|
|
||||||
])
|
|
||||||
|
|
||||||
const [ symbol, decimals ] = results
|
|
||||||
if (symbol && decimals) {
|
if (symbol && decimals) {
|
||||||
this.setState({
|
this.setState({
|
||||||
customSymbol: symbol[0],
|
customSymbol: symbol,
|
||||||
customDecimals: decimals[0].toString(),
|
customDecimals: decimals.toString(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ const inherits = require('util').inherits
|
|||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
const connect = require('react-redux').connect
|
const connect = require('react-redux').connect
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const { checkFeatureToggle } = require('../lib/feature-toggle-utils')
|
|
||||||
const actions = require('./actions')
|
const actions = require('./actions')
|
||||||
// mascara
|
// mascara
|
||||||
const MascaraFirstTime = require('../../mascara/src/app/first-time').default
|
const MascaraFirstTime = require('../../mascara/src/app/first-time').default
|
||||||
@ -12,9 +11,7 @@ const InitializeMenuScreen = require('./first-time/init-menu')
|
|||||||
const NewKeyChainScreen = require('./new-keychain')
|
const NewKeyChainScreen = require('./new-keychain')
|
||||||
// accounts
|
// accounts
|
||||||
const MainContainer = require('./main-container')
|
const MainContainer = require('./main-container')
|
||||||
const SendTransactionScreen = require('./send')
|
|
||||||
const SendTransactionScreen2 = require('./components/send/send-v2-container')
|
const SendTransactionScreen2 = require('./components/send/send-v2-container')
|
||||||
const SendTokenScreen = require('./components/send-token')
|
|
||||||
const ConfirmTxScreen = require('./conf-tx')
|
const ConfirmTxScreen = require('./conf-tx')
|
||||||
// notice
|
// notice
|
||||||
const NoticeScreen = require('./components/notice')
|
const NoticeScreen = require('./components/notice')
|
||||||
@ -27,7 +24,6 @@ const WalletView = require('./components/wallet-view')
|
|||||||
const Settings = require('./settings')
|
const Settings = require('./settings')
|
||||||
const AddTokenScreen = require('./add-token')
|
const AddTokenScreen = require('./add-token')
|
||||||
const Import = require('./accounts/import')
|
const Import = require('./accounts/import')
|
||||||
const InfoScreen = require('./info')
|
|
||||||
const Loading = require('./components/loading')
|
const Loading = require('./components/loading')
|
||||||
const NetworkIndicator = require('./components/network')
|
const NetworkIndicator = require('./components/network')
|
||||||
const Identicon = require('./components/identicon')
|
const Identicon = require('./components/identicon')
|
||||||
@ -38,6 +34,7 @@ const RevealSeedConfirmation = require('./keychains/hd/recover-seed/confirmation
|
|||||||
const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
|
const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
|
||||||
const NetworkDropdown = require('./components/dropdowns/network-dropdown')
|
const NetworkDropdown = require('./components/dropdowns/network-dropdown')
|
||||||
const AccountMenu = require('./components/account-menu')
|
const AccountMenu = require('./components/account-menu')
|
||||||
|
const QrView = require('./components/qr-code')
|
||||||
|
|
||||||
// Global Modals
|
// Global Modals
|
||||||
const Modal = require('./components/modals/index').Modal
|
const Modal = require('./components/modals/index').Modal
|
||||||
@ -148,7 +145,7 @@ App.prototype.render = function () {
|
|||||||
(isLoading || isLoadingNetwork) && h(Loading, {
|
(isLoading || isLoadingNetwork) && h(Loading, {
|
||||||
loadingMessage: loadMessage,
|
loadingMessage: loadMessage,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// this.renderLoadingIndicator({ isLoading, isLoadingNetwork, loadMessage }),
|
// this.renderLoadingIndicator({ isLoading, isLoadingNetwork, loadMessage }),
|
||||||
|
|
||||||
// content
|
// content
|
||||||
@ -228,8 +225,6 @@ App.prototype.renderAppBar = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const props = this.props
|
const props = this.props
|
||||||
const state = this.state || {}
|
|
||||||
const isNetworkMenuOpen = state.isNetworkMenuOpen || false
|
|
||||||
const {isMascara, isOnboarding} = props
|
const {isMascara, isOnboarding} = props
|
||||||
|
|
||||||
// Do not render header if user is in mascara onboarding
|
// Do not render header if user is in mascara onboarding
|
||||||
|
@ -32,6 +32,7 @@ function mapDispatchToProps (dispatch) {
|
|||||||
},
|
},
|
||||||
lockMetamask: () => {
|
lockMetamask: () => {
|
||||||
dispatch(actions.lockMetamask())
|
dispatch(actions.lockMetamask())
|
||||||
|
dispatch(actions.displayWarning(null))
|
||||||
dispatch(actions.toggleAccountMenu())
|
dispatch(actions.toggleAccountMenu())
|
||||||
},
|
},
|
||||||
showConfigPage: () => {
|
showConfigPage: () => {
|
||||||
|
@ -2,7 +2,7 @@ const Component = require('react').Component
|
|||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const InputNumber = require('../input-number.js')
|
const InputNumber = require('../input-number.js')
|
||||||
const GasSlider = require('./gas-slider.js')
|
// const GasSlider = require('./gas-slider.js')
|
||||||
|
|
||||||
module.exports = GasModalCard
|
module.exports = GasModalCard
|
||||||
|
|
||||||
@ -13,8 +13,7 @@ function GasModalCard () {
|
|||||||
|
|
||||||
GasModalCard.prototype.render = function () {
|
GasModalCard.prototype.render = function () {
|
||||||
const {
|
const {
|
||||||
memo,
|
// memo,
|
||||||
identities,
|
|
||||||
onChange,
|
onChange,
|
||||||
unitLabel,
|
unitLabel,
|
||||||
value,
|
value,
|
||||||
@ -22,7 +21,7 @@ GasModalCard.prototype.render = function () {
|
|||||||
// max,
|
// max,
|
||||||
step,
|
step,
|
||||||
title,
|
title,
|
||||||
copy
|
copy,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
return h('div.send-v2__gas-modal-card', [
|
return h('div.send-v2__gas-modal-card', [
|
||||||
@ -48,8 +47,8 @@ GasModalCard.prototype.render = function () {
|
|||||||
// min,
|
// min,
|
||||||
// onChange,
|
// onChange,
|
||||||
// }),
|
// }),
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,50 +1,50 @@
|
|||||||
const Component = require('react').Component
|
// const Component = require('react').Component
|
||||||
const h = require('react-hyperscript')
|
// const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
// const inherits = require('util').inherits
|
||||||
|
|
||||||
module.exports = GasSlider
|
// module.exports = GasSlider
|
||||||
|
|
||||||
inherits(GasSlider, Component)
|
// inherits(GasSlider, Component)
|
||||||
function GasSlider () {
|
// function GasSlider () {
|
||||||
Component.call(this)
|
// Component.call(this)
|
||||||
}
|
// }
|
||||||
|
|
||||||
GasSlider.prototype.render = function () {
|
// GasSlider.prototype.render = function () {
|
||||||
const {
|
// const {
|
||||||
memo,
|
// memo,
|
||||||
identities,
|
// identities,
|
||||||
onChange,
|
// onChange,
|
||||||
unitLabel,
|
// unitLabel,
|
||||||
value,
|
// value,
|
||||||
id,
|
// id,
|
||||||
step,
|
// step,
|
||||||
max,
|
// max,
|
||||||
min,
|
// min,
|
||||||
} = this.props
|
// } = this.props
|
||||||
|
|
||||||
return h('div.gas-slider', [
|
// return h('div.gas-slider', [
|
||||||
|
|
||||||
h('input.gas-slider__input', {
|
// h('input.gas-slider__input', {
|
||||||
type: 'range',
|
// type: 'range',
|
||||||
step,
|
// step,
|
||||||
max,
|
// max,
|
||||||
min,
|
// min,
|
||||||
value,
|
// value,
|
||||||
id: 'gasSlider',
|
// id: 'gasSlider',
|
||||||
onChange: event => onChange(event.target.value),
|
// onChange: event => onChange(event.target.value),
|
||||||
}, []),
|
// }, []),
|
||||||
|
|
||||||
h('div.gas-slider__bar', [
|
// h('div.gas-slider__bar', [
|
||||||
|
|
||||||
h('div.gas-slider__low'),
|
// h('div.gas-slider__low'),
|
||||||
|
|
||||||
h('div.gas-slider__mid'),
|
// h('div.gas-slider__mid'),
|
||||||
|
|
||||||
h('div.gas-slider__high'),
|
// h('div.gas-slider__high'),
|
||||||
|
|
||||||
]),
|
// ]),
|
||||||
|
|
||||||
])
|
// ])
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ function mapDispatchToProps (dispatch) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOriginalState(props) {
|
function getOriginalState (props) {
|
||||||
const gasPrice = props.gasPrice || MIN_GAS_PRICE_DEC
|
const gasPrice = props.gasPrice || MIN_GAS_PRICE_DEC
|
||||||
const gasLimit = props.gasLimit || MIN_GAS_LIMIT_DEC
|
const gasLimit = props.gasLimit || MIN_GAS_LIMIT_DEC
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) {
|
|||||||
updateGasPrice,
|
updateGasPrice,
|
||||||
updateGasLimit,
|
updateGasLimit,
|
||||||
hideModal,
|
hideModal,
|
||||||
updateGasTotal
|
updateGasTotal,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
updateGasPrice(gasPrice)
|
updateGasPrice(gasPrice)
|
||||||
@ -126,9 +126,9 @@ CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!balanceIsSufficient) {
|
if (!balanceIsSufficient) {
|
||||||
error = 'Insufficient balance for current gas total'
|
error = 'Insufficient balance for current gas total'
|
||||||
}
|
}
|
||||||
|
|
||||||
const gasLimitTooLow = gasLimit && conversionGreaterThan(
|
const gasLimitTooLow = gasLimit && conversionGreaterThan(
|
||||||
{
|
{
|
||||||
value: MIN_GAS_LIMIT_DEC,
|
value: MIN_GAS_LIMIT_DEC,
|
||||||
@ -142,7 +142,7 @@ CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (gasLimitTooLow) {
|
if (gasLimitTooLow) {
|
||||||
error = 'Gas limit must be at least 21000'
|
error = 'Gas limit must be at least 21000'
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ error })
|
this.setState({ error })
|
||||||
@ -190,7 +190,7 @@ CustomizeGasModal.prototype.convertAndSetGasPrice = function (newGasPrice) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CustomizeGasModal.prototype.render = function () {
|
CustomizeGasModal.prototype.render = function () {
|
||||||
const { hideModal, conversionRate } = this.props
|
const { hideModal } = this.props
|
||||||
const { gasPrice, gasLimit, gasTotal, error } = this.state
|
const { gasPrice, gasLimit, gasTotal, error } = this.state
|
||||||
|
|
||||||
const convertedGasPrice = conversionUtil(gasPrice, {
|
const convertedGasPrice = conversionUtil(gasPrice, {
|
||||||
@ -219,12 +219,12 @@ CustomizeGasModal.prototype.render = function () {
|
|||||||
]),
|
]),
|
||||||
|
|
||||||
h('div.send-v2__customize-gas__body', {}, [
|
h('div.send-v2__customize-gas__body', {}, [
|
||||||
|
|
||||||
h(GasModalCard, {
|
h(GasModalCard, {
|
||||||
value: convertedGasPrice,
|
value: convertedGasPrice,
|
||||||
min: MIN_GAS_PRICE_GWEI,
|
min: MIN_GAS_PRICE_GWEI,
|
||||||
// max: 1000,
|
// max: 1000,
|
||||||
step: 1,
|
step: MIN_GAS_PRICE_GWEI,
|
||||||
onChange: value => this.convertAndSetGasPrice(value),
|
onChange: value => this.convertAndSetGasPrice(value),
|
||||||
title: 'Gas Price (GWEI)',
|
title: 'Gas Price (GWEI)',
|
||||||
copy: 'We calculate the suggested gas prices based on network success rates.',
|
copy: 'We calculate the suggested gas prices based on network success rates.',
|
||||||
@ -247,7 +247,7 @@ CustomizeGasModal.prototype.render = function () {
|
|||||||
error && h('div.send-v2__customize-gas__error-message', [
|
error && h('div.send-v2__customize-gas__error-message', [
|
||||||
error,
|
error,
|
||||||
]),
|
]),
|
||||||
|
|
||||||
h('div.send-v2__customize-gas__revert', {
|
h('div.send-v2__customize-gas__revert', {
|
||||||
onClick: () => this.revert(),
|
onClick: () => this.revert(),
|
||||||
}, ['Revert']),
|
}, ['Revert']),
|
||||||
@ -260,7 +260,7 @@ CustomizeGasModal.prototype.render = function () {
|
|||||||
h(`div.send-v2__customize-gas__save${error ? '__error' : ''}`, {
|
h(`div.send-v2__customize-gas__save${error ? '__error' : ''}`, {
|
||||||
onClick: () => !error && this.save(gasPrice, gasLimit, gasTotal),
|
onClick: () => !error && this.save(gasPrice, gasLimit, gasTotal),
|
||||||
}, ['SAVE']),
|
}, ['SAVE']),
|
||||||
])
|
]),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const Identicon = require('../identicon')
|
|
||||||
const AccountListItem = require('../send/account-list-item')
|
const AccountListItem = require('../send/account-list-item')
|
||||||
|
|
||||||
module.exports = AccountDropdownMini
|
module.exports = AccountDropdownMini
|
||||||
@ -38,13 +37,13 @@ AccountDropdownMini.prototype.renderDropdown = function () {
|
|||||||
...accounts.map(account => h(AccountListItem, {
|
...accounts.map(account => h(AccountListItem, {
|
||||||
account,
|
account,
|
||||||
displayBalance: false,
|
displayBalance: false,
|
||||||
displayAddress: false,
|
displayAddress: false,
|
||||||
handleClick: () => {
|
handleClick: () => {
|
||||||
onSelect(account)
|
onSelect(account)
|
||||||
closeDropdown()
|
closeDropdown()
|
||||||
},
|
},
|
||||||
icon: this.getListItemIcon(account, selectedAccount),
|
icon: this.getListItemIcon(account, selectedAccount),
|
||||||
}))
|
})),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
|
|
||||||
@ -53,10 +52,8 @@ AccountDropdownMini.prototype.renderDropdown = function () {
|
|||||||
|
|
||||||
AccountDropdownMini.prototype.render = function () {
|
AccountDropdownMini.prototype.render = function () {
|
||||||
const {
|
const {
|
||||||
accounts,
|
|
||||||
selectedAccount,
|
selectedAccount,
|
||||||
openDropdown,
|
openDropdown,
|
||||||
closeDropdown,
|
|
||||||
dropdownOpen,
|
dropdownOpen,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
@ -67,12 +64,12 @@ AccountDropdownMini.prototype.render = function () {
|
|||||||
handleClick: openDropdown,
|
handleClick: openDropdown,
|
||||||
displayBalance: false,
|
displayBalance: false,
|
||||||
displayAddress: false,
|
displayAddress: false,
|
||||||
icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } })
|
icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } }),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
dropdownOpen && this.renderDropdown(),
|
dropdownOpen && this.renderDropdown(),
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ AccountOptionsDropdown.prototype.render = function () {
|
|||||||
return h(AccountDropdowns, {
|
return h(AccountDropdowns, {
|
||||||
enableAccountOptions: true,
|
enableAccountOptions: true,
|
||||||
enableAccountsSelector: false,
|
enableAccountsSelector: false,
|
||||||
selected: selectedAddress,
|
selected,
|
||||||
network,
|
network,
|
||||||
identities,
|
identities,
|
||||||
style: style || {},
|
style: style || {},
|
||||||
|
@ -19,7 +19,7 @@ AccountSelectionDropdown.prototype.render = function () {
|
|||||||
return h(AccountDropdowns, {
|
return h(AccountDropdowns, {
|
||||||
enableAccountOptions: false,
|
enableAccountOptions: false,
|
||||||
enableAccountsSelector: true,
|
enableAccountsSelector: true,
|
||||||
selected: selectedAddress,
|
selected,
|
||||||
network,
|
network,
|
||||||
identities,
|
identities,
|
||||||
style: style || {},
|
style: style || {},
|
||||||
|
@ -425,6 +425,21 @@ AccountDropdowns.propTypes = {
|
|||||||
identities: PropTypes.objectOf(PropTypes.object),
|
identities: PropTypes.objectOf(PropTypes.object),
|
||||||
selected: PropTypes.string,
|
selected: PropTypes.string,
|
||||||
keyrings: PropTypes.array,
|
keyrings: PropTypes.array,
|
||||||
|
accounts: PropTypes.object,
|
||||||
|
menuItemStyles: PropTypes.object,
|
||||||
|
actions: PropTypes.object,
|
||||||
|
// actions.showAccountDetail: ,
|
||||||
|
useCssTransition: PropTypes.bool,
|
||||||
|
innerStyle: PropTypes.object,
|
||||||
|
sidebarOpen: PropTypes.bool,
|
||||||
|
dropdownWrapperStyle: PropTypes.string,
|
||||||
|
// actions.showAccountDetailModal: ,
|
||||||
|
network: PropTypes.number,
|
||||||
|
// actions.showExportPrivateKeyModal: ,
|
||||||
|
style: PropTypes.object,
|
||||||
|
enableAccountsSelector: PropTypes.bool,
|
||||||
|
enableAccountOption: PropTypes.bool,
|
||||||
|
enableAccountOptions: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
@ -68,6 +68,7 @@ Dropdown.propTypes = {
|
|||||||
onClickOutside: PropTypes.func,
|
onClickOutside: PropTypes.func,
|
||||||
innerStyle: PropTypes.object,
|
innerStyle: PropTypes.object,
|
||||||
useCssTransition: PropTypes.bool,
|
useCssTransition: PropTypes.bool,
|
||||||
|
containerClassName: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
class DropdownMenuItem extends Component {
|
class DropdownMenuItem extends Component {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
const { Component, PropTypes } = require('react')
|
const { Component } = require('react')
|
||||||
|
const PropTypes = require('react').PropTypes
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const classnames = require('classnames')
|
const classnames = require('classnames')
|
||||||
const R = require('ramda')
|
const R = require('ramda')
|
||||||
|
@ -10,7 +10,7 @@ function mapDispatchToProps (dispatch) {
|
|||||||
return {
|
return {
|
||||||
showHideTokenConfirmationModal: (token) => {
|
showHideTokenConfirmationModal: (token) => {
|
||||||
dispatch(actions.showModal({ name: 'HIDE_TOKEN_CONFIRMATION', token }))
|
dispatch(actions.showModal({ name: 'HIDE_TOKEN_CONFIRMATION', token }))
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,14 +36,14 @@ TokenMenuDropdown.prototype.render = function () {
|
|||||||
}),
|
}),
|
||||||
h('div.token-menu-dropdown__container', {}, [
|
h('div.token-menu-dropdown__container', {}, [
|
||||||
h('div.token-menu-dropdown__options', {}, [
|
h('div.token-menu-dropdown__options', {}, [
|
||||||
|
|
||||||
h('div.token-menu-dropdown__option', {
|
h('div.token-menu-dropdown__option', {
|
||||||
onClick: (e) => {
|
onClick: (e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
showHideTokenConfirmationModal(this.props.token)
|
showHideTokenConfirmationModal(this.props.token)
|
||||||
this.props.onClose()
|
this.props.onClose()
|
||||||
},
|
},
|
||||||
}, 'Hide Token')
|
}, 'Hide Token'),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const { addCurrencies } = require('../conversion-util')
|
const {
|
||||||
|
addCurrencies,
|
||||||
|
conversionGTE,
|
||||||
|
conversionLTE,
|
||||||
|
toNegative,
|
||||||
|
} = require('../conversion-util')
|
||||||
|
|
||||||
module.exports = InputNumber
|
module.exports = InputNumber
|
||||||
|
|
||||||
@ -17,8 +22,21 @@ InputNumber.prototype.setValue = function (newValue) {
|
|||||||
|
|
||||||
newValue = Number(fixed ? newValue.toFixed(4) : newValue)
|
newValue = Number(fixed ? newValue.toFixed(4) : newValue)
|
||||||
|
|
||||||
if (newValue >= min && newValue <= max) {
|
const newValueGreaterThanMin = conversionGTE(
|
||||||
|
{ value: newValue, fromNumericBase: 'dec' },
|
||||||
|
{ value: min, fromNumericBase: 'hex' },
|
||||||
|
)
|
||||||
|
|
||||||
|
const newValueLessThanMax = conversionLTE(
|
||||||
|
{ value: newValue, fromNumericBase: 'dec' },
|
||||||
|
{ value: max, fromNumericBase: 'hex' },
|
||||||
|
)
|
||||||
|
if (newValueGreaterThanMin && newValueLessThanMax) {
|
||||||
onChange(newValue)
|
onChange(newValue)
|
||||||
|
} else if (!newValueGreaterThanMin) {
|
||||||
|
onChange(min)
|
||||||
|
} else if (!newValueLessThanMax) {
|
||||||
|
onChange(max)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +47,7 @@ InputNumber.prototype.render = function () {
|
|||||||
h('input.customize-gas-input', {
|
h('input.customize-gas-input', {
|
||||||
placeholder,
|
placeholder,
|
||||||
type: 'number',
|
type: 'number',
|
||||||
value: value,
|
value,
|
||||||
onChange: (e) => this.setValue(e.target.value),
|
onChange: (e) => this.setValue(e.target.value),
|
||||||
}),
|
}),
|
||||||
h('span.gas-tooltip-input-detail', {}, [unitLabel]),
|
h('span.gas-tooltip-input-detail', {}, [unitLabel]),
|
||||||
@ -39,7 +57,7 @@ InputNumber.prototype.render = function () {
|
|||||||
}),
|
}),
|
||||||
h('i.fa.fa-angle-down', {
|
h('i.fa.fa-angle-down', {
|
||||||
style: { cursor: 'pointer' },
|
style: { cursor: 'pointer' },
|
||||||
onClick: () => this.setValue(addCurrencies(value, step * -1)),
|
onClick: () => this.setValue(addCurrencies(value, toNegative(step))),
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
])
|
])
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const { Component } = require('react')
|
const { Component } = require('react')
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
|
const PropTypes = require('react').PropTypes
|
||||||
|
|
||||||
class LoadingIndicator extends Component {
|
class LoadingIndicator extends Component {
|
||||||
renderMessage () {
|
renderMessage () {
|
||||||
@ -35,4 +36,8 @@ class LoadingIndicator extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadingIndicator.propTypes = {
|
||||||
|
loadingMessage: PropTypes.string,
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = LoadingIndicator
|
module.exports = LoadingIndicator
|
||||||
|
@ -4,7 +4,7 @@ const inherits = require('util').inherits
|
|||||||
const connect = require('react-redux').connect
|
const connect = require('react-redux').connect
|
||||||
const actions = require('../../actions')
|
const actions = require('../../actions')
|
||||||
const AccountModalContainer = require('./account-modal-container')
|
const AccountModalContainer = require('./account-modal-container')
|
||||||
const { getSelectedIdentity, getSelectedAddress } = require('../../selectors')
|
const { getSelectedIdentity } = require('../../selectors')
|
||||||
const genAccountLink = require('../../../lib/account-link.js')
|
const genAccountLink = require('../../../lib/account-link.js')
|
||||||
const QrView = require('../qr-code')
|
const QrView = require('../qr-code')
|
||||||
const EditableLabel = require('../editable-label')
|
const EditableLabel = require('../editable-label')
|
||||||
|
@ -92,7 +92,6 @@ ExportPrivateKeyModal.prototype.renderButtons = function (privateKey, password,
|
|||||||
ExportPrivateKeyModal.prototype.render = function () {
|
ExportPrivateKeyModal.prototype.render = function () {
|
||||||
const {
|
const {
|
||||||
selectedIdentity,
|
selectedIdentity,
|
||||||
network,
|
|
||||||
warning,
|
warning,
|
||||||
showAccountDetailModal,
|
showAccountDetailModal,
|
||||||
hideModal,
|
hideModal,
|
||||||
|
@ -220,7 +220,7 @@ Modal.prototype.render = function () {
|
|||||||
|
|
||||||
const children = modal.contents
|
const children = modal.contents
|
||||||
const modalStyle = modal[isMobileView() ? 'mobileModalStyle' : 'laptopModalStyle']
|
const modalStyle = modal[isMobileView() ? 'mobileModalStyle' : 'laptopModalStyle']
|
||||||
const contentStyle = modal.contentStyle || {};
|
const contentStyle = modal.contentStyle || {}
|
||||||
|
|
||||||
return h(FadeModal,
|
return h(FadeModal,
|
||||||
{
|
{
|
||||||
|
@ -1,17 +1,88 @@
|
|||||||
const Component = require('react').Component
|
const { Component } = require('react')
|
||||||
|
const PropTypes = require('prop-types')
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
const { connect } = require('react-redux')
|
||||||
const connect = require('react-redux').connect
|
|
||||||
const actions = require('../../actions')
|
const actions = require('../../actions')
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
class NewAccountModal extends Component {
|
||||||
return {
|
constructor (props) {
|
||||||
network: state.metamask.network,
|
super(props)
|
||||||
address: state.metamask.selectedAddress,
|
const { numberOfExistingAccounts = 0 } = props
|
||||||
|
const newAccountNumber = numberOfExistingAccounts + 1
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
newAccountName: `Account ${newAccountNumber}`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { newAccountName } = this.state
|
||||||
|
|
||||||
|
return h('div', [
|
||||||
|
h('div.new-account-modal-wrapper', {
|
||||||
|
}, [
|
||||||
|
h('div.new-account-modal-header', {}, [
|
||||||
|
'New Account',
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('div.modal-close-x', {
|
||||||
|
onClick: this.props.hideModal,
|
||||||
|
}),
|
||||||
|
|
||||||
|
h('div.new-account-modal-content', {}, [
|
||||||
|
'Account Name',
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('div.new-account-input-wrapper', {}, [
|
||||||
|
h('input.new-account-input', {
|
||||||
|
value: this.state.newAccountName,
|
||||||
|
placeholder: 'E.g. My new account',
|
||||||
|
onChange: event => this.setState({ newAccountName: event.target.value }),
|
||||||
|
}, []),
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('div.new-account-modal-content.after-input', {}, [
|
||||||
|
'or',
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('div.new-account-modal-content.after-input.pointer', {
|
||||||
|
onClick: () => {
|
||||||
|
this.props.hideModal()
|
||||||
|
this.props.showImportPage()
|
||||||
|
},
|
||||||
|
}, 'Import an account'),
|
||||||
|
|
||||||
|
h('div.new-account-modal-content.button', {}, [
|
||||||
|
h('button.btn-clear', {
|
||||||
|
onClick: () => this.props.createAccount(newAccountName),
|
||||||
|
}, [
|
||||||
|
'SAVE',
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
NewAccountModal.propTypes = {
|
||||||
|
hideModal: PropTypes.func,
|
||||||
|
showImportPage: PropTypes.func,
|
||||||
|
createAccount: PropTypes.func,
|
||||||
|
numberOfExistingAccounts: PropTypes.number,
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
const { metamask: { network, selectedAddress, identities = {} } } = state
|
||||||
|
const numberOfExistingAccounts = Object.keys(identities).length
|
||||||
|
|
||||||
|
return {
|
||||||
|
network,
|
||||||
|
address: selectedAddress,
|
||||||
|
numberOfExistingAccounts,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
return {
|
return {
|
||||||
toCoinbase: (address) => {
|
toCoinbase: (address) => {
|
||||||
dispatch(actions.buyEth({ network: '1', address, amount: 0 }))
|
dispatch(actions.buyEth({ network: '1', address, amount: 0 }))
|
||||||
@ -32,60 +103,4 @@ function mapDispatchToProps (dispatch) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inherits(NewAccountModal, Component)
|
|
||||||
function NewAccountModal () {
|
|
||||||
Component.call(this)
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
newAccountName: '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(NewAccountModal)
|
module.exports = connect(mapStateToProps, mapDispatchToProps)(NewAccountModal)
|
||||||
|
|
||||||
NewAccountModal.prototype.render = function () {
|
|
||||||
const { newAccountName } = this.state
|
|
||||||
|
|
||||||
return h('div', {}, [
|
|
||||||
h('div.new-account-modal-wrapper', {
|
|
||||||
}, [
|
|
||||||
h('div.new-account-modal-header', {}, [
|
|
||||||
'New Account',
|
|
||||||
]),
|
|
||||||
|
|
||||||
h('div.modal-close-x', {
|
|
||||||
onClick: this.props.hideModal,
|
|
||||||
}),
|
|
||||||
|
|
||||||
h('div.new-account-modal-content', {}, [
|
|
||||||
'Account Name',
|
|
||||||
]),
|
|
||||||
|
|
||||||
h('div.new-account-input-wrapper', {}, [
|
|
||||||
h('input.new-account-input', {
|
|
||||||
placeholder: 'E.g. My new account',
|
|
||||||
onChange: event => this.setState({ newAccountName: event.target.value }),
|
|
||||||
}, []),
|
|
||||||
]),
|
|
||||||
|
|
||||||
h('div.new-account-modal-content.after-input', {}, [
|
|
||||||
'or',
|
|
||||||
]),
|
|
||||||
|
|
||||||
h('div.new-account-modal-content.after-input.pointer', {
|
|
||||||
onClick: () => {
|
|
||||||
this.props.hideModal()
|
|
||||||
this.props.showImportPage()
|
|
||||||
},
|
|
||||||
}, 'Import an account'),
|
|
||||||
|
|
||||||
h('div.new-account-modal-content.button', {}, [
|
|
||||||
h('button.btn-clear', {
|
|
||||||
onClick: () => this.props.createAccount(newAccountName),
|
|
||||||
}, [
|
|
||||||
'SAVE',
|
|
||||||
]),
|
|
||||||
]),
|
|
||||||
]),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
@ -35,6 +35,6 @@ ShapeshiftDepositTxModal.prototype.render = function () {
|
|||||||
}, [
|
}, [
|
||||||
h('div', {}, [
|
h('div', {}, [
|
||||||
h(QrView, {key: 'qr', Qr}),
|
h(QrView, {key: 'qr', Qr}),
|
||||||
])
|
]),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const classnames = require('classnames');
|
const classnames = require('classnames')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const NetworkDropdownIcon = require('./dropdowns/components/network-dropdown-icon')
|
const NetworkDropdownIcon = require('./dropdowns/components/network-dropdown-icon')
|
||||||
|
|
||||||
|
@ -10,9 +10,7 @@ const BN = ethUtil.BN
|
|||||||
const hexToBn = require('../../../../app/scripts/lib/hex-to-bn')
|
const hexToBn = require('../../../../app/scripts/lib/hex-to-bn')
|
||||||
const { conversionUtil } = require('../../conversion-util')
|
const { conversionUtil } = require('../../conversion-util')
|
||||||
|
|
||||||
const MIN_GAS_PRICE_GWEI_BN = new BN(1)
|
const { MIN_GAS_PRICE_HEX } = require('../send/send-constants')
|
||||||
const GWEI_FACTOR = new BN(1e9)
|
|
||||||
const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR)
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmDeployContract)
|
module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmDeployContract)
|
||||||
@ -166,7 +164,7 @@ ConfirmDeployContract.prototype.getGasFee = function () {
|
|||||||
const gasBn = hexToBn(gas)
|
const gasBn = hexToBn(gas)
|
||||||
|
|
||||||
// Gas Price
|
// Gas Price
|
||||||
const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16)
|
const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_HEX
|
||||||
const gasPriceBn = hexToBn(gasPrice)
|
const gasPriceBn = hexToBn(gasPrice)
|
||||||
|
|
||||||
const txFeeBn = gasBn.mul(gasPriceBn)
|
const txFeeBn = gasBn.mul(gasPriceBn)
|
||||||
|
@ -10,9 +10,7 @@ const BN = ethUtil.BN
|
|||||||
const hexToBn = require('../../../../app/scripts/lib/hex-to-bn')
|
const hexToBn = require('../../../../app/scripts/lib/hex-to-bn')
|
||||||
const { conversionUtil, addCurrencies } = require('../../conversion-util')
|
const { conversionUtil, addCurrencies } = require('../../conversion-util')
|
||||||
|
|
||||||
const MIN_GAS_PRICE_GWEI_BN = new BN(1)
|
const { MIN_GAS_PRICE_HEX } = require('../send/send-constants')
|
||||||
const GWEI_FACTOR = new BN(1e9)
|
|
||||||
const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR)
|
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmSendEther)
|
module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmSendEther)
|
||||||
|
|
||||||
@ -93,7 +91,7 @@ ConfirmSendEther.prototype.getGasFee = function () {
|
|||||||
// const safeGasLimit = safeGasLimitBN.toString(10)
|
// const safeGasLimit = safeGasLimitBN.toString(10)
|
||||||
|
|
||||||
// Gas Price
|
// Gas Price
|
||||||
const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16)
|
const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_HEX
|
||||||
const gasPriceBn = hexToBn(gasPrice)
|
const gasPriceBn = hexToBn(gasPrice)
|
||||||
|
|
||||||
const txFeeBn = gasBn.mul(gasPriceBn)
|
const txFeeBn = gasBn.mul(gasPriceBn)
|
||||||
|
@ -10,19 +10,15 @@ const clone = require('clone')
|
|||||||
const Identicon = require('../identicon')
|
const Identicon = require('../identicon')
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
const BN = ethUtil.BN
|
const BN = ethUtil.BN
|
||||||
const hexToBn = require('../../../../app/scripts/lib/hex-to-bn')
|
|
||||||
const {
|
const {
|
||||||
conversionUtil,
|
conversionUtil,
|
||||||
multiplyCurrencies,
|
multiplyCurrencies,
|
||||||
addCurrencies,
|
addCurrencies,
|
||||||
} = require('../../conversion-util')
|
} = require('../../conversion-util')
|
||||||
|
|
||||||
const MIN_GAS_PRICE_GWEI_BN = new BN(1)
|
const { MIN_GAS_PRICE_HEX } = require('../send/send-constants')
|
||||||
const GWEI_FACTOR = new BN(1e9)
|
|
||||||
const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR)
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
getSelectedTokenExchangeRate,
|
|
||||||
getTokenExchangeRate,
|
getTokenExchangeRate,
|
||||||
getSelectedAddress,
|
getSelectedAddress,
|
||||||
} = require('../../selectors')
|
} = require('../../selectors')
|
||||||
@ -38,7 +34,6 @@ function mapStateToProps (state, ownProps) {
|
|||||||
identities,
|
identities,
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
} = state.metamask
|
} = state.metamask
|
||||||
const accounts = state.metamask.accounts
|
|
||||||
const selectedAddress = getSelectedAddress(state)
|
const selectedAddress = getSelectedAddress(state)
|
||||||
const tokenExchangeRate = getTokenExchangeRate(state, symbol)
|
const tokenExchangeRate = getTokenExchangeRate(state, symbol)
|
||||||
|
|
||||||
@ -99,7 +94,7 @@ ConfirmSendToken.prototype.getGasFee = function () {
|
|||||||
const { decimals } = token
|
const { decimals } = token
|
||||||
|
|
||||||
const gas = txParams.gas
|
const gas = txParams.gas
|
||||||
const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16)
|
const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_HEX
|
||||||
const gasTotal = multiplyCurrencies(gas, gasPrice, {
|
const gasTotal = multiplyCurrencies(gas, gasPrice, {
|
||||||
multiplicandBase: 16,
|
multiplicandBase: 16,
|
||||||
multiplierBase: 16,
|
multiplierBase: 16,
|
||||||
@ -149,7 +144,7 @@ ConfirmSendToken.prototype.getData = function () {
|
|||||||
const { value } = params[0] || {}
|
const { value } = params[0] || {}
|
||||||
const txMeta = this.gatherTxMeta()
|
const txMeta = this.gatherTxMeta()
|
||||||
const txParams = txMeta.txParams || {}
|
const txParams = txMeta.txParams || {}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
from: {
|
from: {
|
||||||
address: txParams.from,
|
address: txParams.from,
|
||||||
@ -247,7 +242,6 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () {
|
|||||||
ConfirmSendToken.prototype.render = function () {
|
ConfirmSendToken.prototype.render = function () {
|
||||||
const { backToAccountDetail, selectedAddress } = this.props
|
const { backToAccountDetail, selectedAddress } = this.props
|
||||||
const txMeta = this.gatherTxMeta()
|
const txMeta = this.gatherTxMeta()
|
||||||
const txParams = txMeta.txParams || {}
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
from: {
|
from: {
|
||||||
|
@ -144,16 +144,15 @@ SendTokenScreen.prototype.validate = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SendTokenScreen.prototype.setErrorsFor = function (field) {
|
SendTokenScreen.prototype.setErrorsFor = function (field) {
|
||||||
const { balance, selectedToken } = this.props
|
|
||||||
const { errors: previousErrors } = this.state
|
const { errors: previousErrors } = this.state
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isValid,
|
isValid,
|
||||||
errors: newErrors
|
errors: newErrors,
|
||||||
} = this.validate()
|
} = this.validate()
|
||||||
|
|
||||||
const nextErrors = Object.assign({}, previousErrors, {
|
const nextErrors = Object.assign({}, previousErrors, {
|
||||||
[field]: newErrors[field] || null
|
[field]: newErrors[field] || null,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
@ -167,7 +166,7 @@ SendTokenScreen.prototype.setErrorsFor = function (field) {
|
|||||||
SendTokenScreen.prototype.clearErrorsFor = function (field) {
|
SendTokenScreen.prototype.clearErrorsFor = function (field) {
|
||||||
const { errors: previousErrors } = this.state
|
const { errors: previousErrors } = this.state
|
||||||
const nextErrors = Object.assign({}, previousErrors, {
|
const nextErrors = Object.assign({}, previousErrors, {
|
||||||
[field]: null
|
[field]: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -429,7 +428,7 @@ SendTokenScreen.prototype.render = function () {
|
|||||||
this.renderAmountInput(),
|
this.renderAmountInput(),
|
||||||
this.renderGasInput(),
|
this.renderGasInput(),
|
||||||
this.renderMemoInput(),
|
this.renderMemoInput(),
|
||||||
warning && h('div.send-screen-input-wrapper--error', {},
|
warning && h('div.send-screen-input-wrapper--error', {},
|
||||||
h('div.send-screen-input-wrapper__error-message', [
|
h('div.send-screen-input-wrapper__error-message', [
|
||||||
warning,
|
warning,
|
||||||
])
|
])
|
||||||
|
@ -68,4 +68,4 @@ AccountListItem.prototype.render = function () {
|
|||||||
}, name),
|
}, name),
|
||||||
|
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const Identicon = require('../identicon')
|
|
||||||
const { conversionUtil, multiplyCurrencies } = require('../../conversion-util')
|
const { conversionUtil, multiplyCurrencies } = require('../../conversion-util')
|
||||||
|
|
||||||
module.exports = CurrencyDisplay
|
module.exports = CurrencyDisplay
|
||||||
@ -48,8 +47,6 @@ CurrencyDisplay.prototype.render = function () {
|
|||||||
conversionRate,
|
conversionRate,
|
||||||
primaryCurrency,
|
primaryCurrency,
|
||||||
convertedCurrency,
|
convertedCurrency,
|
||||||
convertedPrefix = '',
|
|
||||||
placeholder = '0',
|
|
||||||
readOnly = false,
|
readOnly = false,
|
||||||
inError = false,
|
inError = false,
|
||||||
value: initValue,
|
value: initValue,
|
||||||
@ -74,7 +71,7 @@ CurrencyDisplay.prototype.render = function () {
|
|||||||
conversionRate,
|
conversionRate,
|
||||||
})
|
})
|
||||||
|
|
||||||
const inputSizeMultiplier = readOnly ? 1 : 1.2;
|
const inputSizeMultiplier = readOnly ? 1 : 1.2
|
||||||
|
|
||||||
return h('div', {
|
return h('div', {
|
||||||
className,
|
className,
|
||||||
@ -98,15 +95,13 @@ CurrencyDisplay.prototype.render = function () {
|
|||||||
|
|
||||||
if (newValue === '') {
|
if (newValue === '') {
|
||||||
newValue = '0'
|
newValue = '0'
|
||||||
}
|
} else if (newValue.match(/^0[1-9]$/)) {
|
||||||
else if (newValue.match(/^0[1-9]$/)) {
|
|
||||||
newValue = newValue.match(/[1-9]/)[0]
|
newValue = newValue.match(/[1-9]/)[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newValue && !isValidInput(newValue)) {
|
if (newValue && !isValidInput(newValue)) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
validate(this.getAmount(newValue))
|
validate(this.getAmount(newValue))
|
||||||
this.setState({ value: newValue })
|
this.setState({ value: newValue })
|
||||||
}
|
}
|
||||||
@ -125,6 +120,6 @@ CurrencyDisplay.prototype.render = function () {
|
|||||||
}, `${convertedValue} ${convertedCurrency.toUpperCase()}`),
|
}, `${convertedValue} ${convertedCurrency.toUpperCase()}`),
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,8 +30,8 @@ EthFeeDisplay.prototype.render = function () {
|
|||||||
color: '#5d5d5d',
|
color: '#5d5d5d',
|
||||||
fontSize: '16px',
|
fontSize: '16px',
|
||||||
fontFamily: 'DIN OT',
|
fontFamily: 'DIN OT',
|
||||||
lineHeight: '22.4px'
|
lineHeight: '22.4px',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const Identicon = require('../identicon')
|
|
||||||
const AccountListItem = require('./account-list-item')
|
const AccountListItem = require('./account-list-item')
|
||||||
|
|
||||||
module.exports = FromDropdown
|
module.exports = FromDropdown
|
||||||
@ -36,13 +35,13 @@ FromDropdown.prototype.renderDropdown = function () {
|
|||||||
h('div.send-v2__from-dropdown__list', {}, [
|
h('div.send-v2__from-dropdown__list', {}, [
|
||||||
|
|
||||||
...accounts.map(account => h(AccountListItem, {
|
...accounts.map(account => h(AccountListItem, {
|
||||||
account,
|
account,
|
||||||
handleClick: () => {
|
handleClick: () => {
|
||||||
onSelect(account)
|
onSelect(account)
|
||||||
closeDropdown()
|
closeDropdown()
|
||||||
},
|
},
|
||||||
icon: this.getListItemIcon(account, selectedAccount),
|
icon: this.getListItemIcon(account, selectedAccount),
|
||||||
}))
|
})),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
|
|
||||||
@ -51,10 +50,8 @@ FromDropdown.prototype.renderDropdown = function () {
|
|||||||
|
|
||||||
FromDropdown.prototype.render = function () {
|
FromDropdown.prototype.render = function () {
|
||||||
const {
|
const {
|
||||||
accounts,
|
|
||||||
selectedAccount,
|
selectedAccount,
|
||||||
openDropdown,
|
openDropdown,
|
||||||
closeDropdown,
|
|
||||||
dropdownOpen,
|
dropdownOpen,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
@ -63,12 +60,12 @@ FromDropdown.prototype.render = function () {
|
|||||||
h(AccountListItem, {
|
h(AccountListItem, {
|
||||||
account: selectedAccount,
|
account: selectedAccount,
|
||||||
handleClick: openDropdown,
|
handleClick: openDropdown,
|
||||||
icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } })
|
icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } }),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
dropdownOpen && this.renderDropdown(),
|
dropdownOpen && this.renderDropdown(),
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,21 +23,20 @@ GasFeeDisplay.prototype.render = function () {
|
|||||||
|
|
||||||
gasTotal
|
gasTotal
|
||||||
? h(CurrencyDisplay, {
|
? h(CurrencyDisplay, {
|
||||||
primaryCurrency: 'ETH',
|
primaryCurrency,
|
||||||
convertedCurrency,
|
convertedCurrency,
|
||||||
value: gasTotal,
|
value: gasTotal,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
convertedPrefix: '$',
|
convertedPrefix: '$',
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
})
|
})
|
||||||
: h('div.currency-display', 'Loading...')
|
: h('div.currency-display', 'Loading...'),
|
||||||
,
|
|
||||||
|
|
||||||
h('div.send-v2__sliders-icon-container', {
|
h('div.send-v2__sliders-icon-container', {
|
||||||
onClick,
|
onClick,
|
||||||
}, [
|
}, [
|
||||||
h('i.fa.fa-sliders.send-v2__sliders-icon'),
|
h('i.fa.fa-sliders.send-v2__sliders-icon'),
|
||||||
])
|
]),
|
||||||
|
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
@ -1,33 +1,33 @@
|
|||||||
const Component = require('react').Component
|
// const Component = require('react').Component
|
||||||
const h = require('react-hyperscript')
|
// const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
// const inherits = require('util').inherits
|
||||||
const Identicon = require('../identicon')
|
// const Identicon = require('../identicon')
|
||||||
|
|
||||||
module.exports = MemoTextArea
|
// module.exports = MemoTextArea
|
||||||
|
|
||||||
inherits(MemoTextArea, Component)
|
// inherits(MemoTextArea, Component)
|
||||||
function MemoTextArea () {
|
// function MemoTextArea () {
|
||||||
Component.call(this)
|
// Component.call(this)
|
||||||
}
|
// }
|
||||||
|
|
||||||
MemoTextArea.prototype.render = function () {
|
// MemoTextArea.prototype.render = function () {
|
||||||
const { memo, identities, onChange } = this.props
|
// const { memo, identities, onChange } = this.props
|
||||||
|
|
||||||
return h('div.send-v2__memo-text-area', [
|
// return h('div.send-v2__memo-text-area', [
|
||||||
|
|
||||||
h('textarea.send-v2__memo-text-area__input', {
|
// h('textarea.send-v2__memo-text-area__input', {
|
||||||
placeholder: 'Optional',
|
// placeholder: 'Optional',
|
||||||
value: memo,
|
// value: memo,
|
||||||
onChange,
|
// onChange,
|
||||||
// onBlur: () => {
|
// // onBlur: () => {
|
||||||
// this.setErrorsFor('memo')
|
// // this.setErrorsFor('memo')
|
||||||
// },
|
// // },
|
||||||
onFocus: event => {
|
// onFocus: event => {
|
||||||
// this.clearErrorsFor('memo')
|
// // this.clearErrorsFor('memo')
|
||||||
},
|
// },
|
||||||
}),
|
// }),
|
||||||
|
|
||||||
])
|
// ])
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
const Identicon = require('../identicon')
|
const ethUtil = require('ethereumjs-util')
|
||||||
const { multiplyCurrencies } = require('../../conversion-util')
|
const { conversionUtil, multiplyCurrencies } = require('../../conversion-util')
|
||||||
|
|
||||||
const MIN_GAS_PRICE_GWEI = '1'
|
const MIN_GAS_PRICE_HEX = (100000000).toString(16)
|
||||||
const GWEI_FACTOR = '1e9'
|
const MIN_GAS_PRICE_DEC = '100000000'
|
||||||
const MIN_GAS_PRICE_HEX = multiplyCurrencies(GWEI_FACTOR, MIN_GAS_PRICE_GWEI, {
|
|
||||||
multiplicandBase: 16,
|
|
||||||
multiplierBase: 16,
|
|
||||||
toNumericBase: 'hex',
|
|
||||||
})
|
|
||||||
const MIN_GAS_PRICE_DEC = multiplyCurrencies(GWEI_FACTOR, MIN_GAS_PRICE_GWEI, {
|
|
||||||
multiplicandBase: 16,
|
|
||||||
multiplierBase: 16,
|
|
||||||
toNumericBase: 'dec',
|
|
||||||
})
|
|
||||||
const MIN_GAS_LIMIT_HEX = (21000).toString(16)
|
const MIN_GAS_LIMIT_HEX = (21000).toString(16)
|
||||||
const MIN_GAS_LIMIT_DEC = 21000
|
const MIN_GAS_LIMIT_DEC = 21000
|
||||||
|
|
||||||
|
const MIN_GAS_PRICE_GWEI = ethUtil.addHexPrefix(conversionUtil(MIN_GAS_PRICE_HEX, {
|
||||||
|
fromDenomination: 'WEI',
|
||||||
|
toDenomination: 'GWEI',
|
||||||
|
fromNumericBase: 'hex',
|
||||||
|
toNumericBase: 'hex',
|
||||||
|
}))
|
||||||
|
|
||||||
const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT_HEX, MIN_GAS_PRICE_HEX, {
|
const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT_HEX, MIN_GAS_PRICE_HEX, {
|
||||||
toNumericBase: 'hex',
|
toNumericBase: 'hex',
|
||||||
multiplicandBase: 16,
|
multiplicandBase: 16,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const { addCurrencies, conversionGreaterThan } = require('../../conversion-util')
|
const { addCurrencies, conversionGreaterThan } = require('../../conversion-util')
|
||||||
|
|
||||||
function isBalanceSufficient({
|
function isBalanceSufficient ({
|
||||||
amount,
|
amount,
|
||||||
gasTotal,
|
gasTotal,
|
||||||
balance,
|
balance,
|
||||||
@ -27,7 +27,6 @@ function isBalanceSufficient({
|
|||||||
fromNumericBase: 'hex',
|
fromNumericBase: 'hex',
|
||||||
conversionRate: amountConversionRate,
|
conversionRate: amountConversionRate,
|
||||||
fromCurrency: selectedToken || primaryCurrency,
|
fromCurrency: selectedToken || primaryCurrency,
|
||||||
conversionRate: amountConversionRate,
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,4 +35,4 @@ function isBalanceSufficient({
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
isBalanceSufficient,
|
isBalanceSufficient,
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,12 @@ const actions = require('../../actions')
|
|||||||
const abi = require('ethereumjs-abi')
|
const abi = require('ethereumjs-abi')
|
||||||
const SendEther = require('../../send-v2')
|
const SendEther = require('../../send-v2')
|
||||||
|
|
||||||
const { multiplyCurrencies } = require('../../conversion-util')
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
accountsWithSendEtherInfoSelector,
|
accountsWithSendEtherInfoSelector,
|
||||||
getCurrentAccountWithSendEtherInfo,
|
getCurrentAccountWithSendEtherInfo,
|
||||||
conversionRateSelector,
|
conversionRateSelector,
|
||||||
getSelectedToken,
|
getSelectedToken,
|
||||||
getSelectedTokenExchangeRate,
|
|
||||||
getSelectedAddress,
|
getSelectedAddress,
|
||||||
getGasPrice,
|
|
||||||
getGasLimit,
|
|
||||||
getAddressBook,
|
getAddressBook,
|
||||||
getSendFrom,
|
getSendFrom,
|
||||||
getCurrentCurrency,
|
getCurrentCurrency,
|
||||||
@ -26,12 +21,11 @@ function mapStateToProps (state) {
|
|||||||
const fromAccounts = accountsWithSendEtherInfoSelector(state)
|
const fromAccounts = accountsWithSendEtherInfoSelector(state)
|
||||||
const selectedAddress = getSelectedAddress(state)
|
const selectedAddress = getSelectedAddress(state)
|
||||||
const selectedToken = getSelectedToken(state)
|
const selectedToken = getSelectedToken(state)
|
||||||
const tokenExchangeRates = state.metamask.tokenExchangeRates
|
|
||||||
const conversionRate = conversionRateSelector(state)
|
const conversionRate = conversionRateSelector(state)
|
||||||
|
|
||||||
let data;
|
let data
|
||||||
let primaryCurrency;
|
let primaryCurrency
|
||||||
let tokenToFiatRate;
|
let tokenToFiatRate
|
||||||
if (selectedToken) {
|
if (selectedToken) {
|
||||||
data = Array.prototype.map.call(
|
data = Array.prototype.map.call(
|
||||||
abi.rawEncode(['address', 'uint256'], [selectedAddress, '0x0']),
|
abi.rawEncode(['address', 'uint256'], [selectedAddress, '0x0']),
|
||||||
@ -76,6 +70,6 @@ function mapDispatchToProps (dispatch) {
|
|||||||
updateSendMemo: newMemo => dispatch(actions.updateSendMemo(newMemo)),
|
updateSendMemo: newMemo => dispatch(actions.updateSendMemo(newMemo)),
|
||||||
updateSendErrors: newError => dispatch(actions.updateSendErrors(newError)),
|
updateSendErrors: newError => dispatch(actions.updateSendErrors(newError)),
|
||||||
goHome: () => dispatch(actions.goHome()),
|
goHome: () => dispatch(actions.goHome()),
|
||||||
clearSend: () => dispatch(actions.clearSend())
|
clearSend: () => dispatch(actions.clearSend()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const Identicon = require('../identicon')
|
|
||||||
const AccountListItem = require('./account-list-item')
|
const AccountListItem = require('./account-list-item')
|
||||||
|
|
||||||
module.exports = ToAutoComplete
|
module.exports = ToAutoComplete
|
||||||
@ -23,7 +22,6 @@ ToAutoComplete.prototype.getListItemIcon = function (listItemAddress, toAddress)
|
|||||||
|
|
||||||
ToAutoComplete.prototype.renderDropdown = function () {
|
ToAutoComplete.prototype.renderDropdown = function () {
|
||||||
const {
|
const {
|
||||||
accounts,
|
|
||||||
closeDropdown,
|
closeDropdown,
|
||||||
onChange,
|
onChange,
|
||||||
to,
|
to,
|
||||||
@ -39,15 +37,15 @@ ToAutoComplete.prototype.renderDropdown = function () {
|
|||||||
h('div.send-v2__from-dropdown__list', {}, [
|
h('div.send-v2__from-dropdown__list', {}, [
|
||||||
|
|
||||||
...accountsToRender.map(account => h(AccountListItem, {
|
...accountsToRender.map(account => h(AccountListItem, {
|
||||||
account,
|
account,
|
||||||
handleClick: () => {
|
handleClick: () => {
|
||||||
onChange(account.address)
|
onChange(account.address)
|
||||||
closeDropdown()
|
closeDropdown()
|
||||||
},
|
},
|
||||||
icon: this.getListItemIcon(account.address, to),
|
icon: this.getListItemIcon(account.address, to),
|
||||||
displayBalance: false,
|
displayBalance: false,
|
||||||
displayAddress: true,
|
displayAddress: true,
|
||||||
}))
|
})),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
|
|
||||||
@ -69,8 +67,7 @@ ToAutoComplete.prototype.handleInputEvent = function (event = {}, cb) {
|
|||||||
this.setState({ accountsToRender: [] })
|
this.setState({ accountsToRender: [] })
|
||||||
event.target && event.target.select()
|
event.target && event.target.select()
|
||||||
closeDropdown()
|
closeDropdown()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
this.setState({ accountsToRender: matchingAccounts })
|
this.setState({ accountsToRender: matchingAccounts })
|
||||||
openDropdown()
|
openDropdown()
|
||||||
}
|
}
|
||||||
@ -86,9 +83,6 @@ ToAutoComplete.prototype.componentDidUpdate = function (nextProps, nextState) {
|
|||||||
ToAutoComplete.prototype.render = function () {
|
ToAutoComplete.prototype.render = function () {
|
||||||
const {
|
const {
|
||||||
to,
|
to,
|
||||||
accounts,
|
|
||||||
openDropdown,
|
|
||||||
closeDropdown,
|
|
||||||
dropdownOpen,
|
dropdownOpen,
|
||||||
onChange,
|
onChange,
|
||||||
inError,
|
inError,
|
||||||
@ -98,13 +92,13 @@ ToAutoComplete.prototype.render = function () {
|
|||||||
|
|
||||||
h('input.send-v2__to-autocomplete__input', {
|
h('input.send-v2__to-autocomplete__input', {
|
||||||
placeholder: 'Recipient Address',
|
placeholder: 'Recipient Address',
|
||||||
className: inError ? `send-v2__error-border` : '',
|
className: inError ? `send-v2__error-border` : '',
|
||||||
value: to,
|
value: to,
|
||||||
onChange: event => onChange(event.target.value),
|
onChange: event => onChange(event.target.value),
|
||||||
onFocus: event => this.handleInputEvent(event),
|
onFocus: event => this.handleInputEvent(event),
|
||||||
style: {
|
style: {
|
||||||
borderColor: inError ? 'red' : null,
|
borderColor: inError ? 'red' : null,
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
!to && h(`i.fa.fa-caret-down.fa-lg.send-v2__to-autocomplete__down-caret`, {
|
!to && h(`i.fa.fa-caret-down.fa-lg.send-v2__to-autocomplete__down-caret`, {
|
||||||
|
@ -28,8 +28,8 @@ USDFeeDisplay.prototype.render = function () {
|
|||||||
color: '#5d5d5d',
|
color: '#5d5d5d',
|
||||||
fontSize: '16px',
|
fontSize: '16px',
|
||||||
fontFamily: 'DIN OT',
|
fontFamily: 'DIN OT',
|
||||||
lineHeight: '22.4px'
|
lineHeight: '22.4px',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,9 +4,9 @@ const inherits = require('util').inherits
|
|||||||
const Identicon = require('./identicon')
|
const Identicon = require('./identicon')
|
||||||
const connect = require('react-redux').connect
|
const connect = require('react-redux').connect
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
const PendingTxDetails = require('./pending-personal-msg-details')
|
const classnames = require('classnames')
|
||||||
|
|
||||||
const AccountDropdownMini = require('./dropdowns/account-dropdown-mini')
|
const AccountDropdownMini = require('./dropdowns/account-dropdown-mini')
|
||||||
const BinaryRenderer = require('./binary-renderer')
|
|
||||||
|
|
||||||
const actions = require('../actions')
|
const actions = require('../actions')
|
||||||
const { conversionUtil } = require('../conversion-util')
|
const { conversionUtil } = require('../conversion-util')
|
||||||
@ -27,13 +27,13 @@ function mapStateToProps (state) {
|
|||||||
requester: null,
|
requester: null,
|
||||||
requesterAddress: null,
|
requesterAddress: null,
|
||||||
accounts: accountsWithSendEtherInfoSelector(state),
|
accounts: accountsWithSendEtherInfoSelector(state),
|
||||||
conversionRate: conversionRateSelector(state)
|
conversionRate: conversionRateSelector(state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
function mapDispatchToProps (dispatch) {
|
||||||
return {
|
return {
|
||||||
goHome: () => dispatch(actions.goHome())
|
goHome: () => dispatch(actions.goHome()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ SignatureRequest.prototype.renderAccountDropdown = function () {
|
|||||||
dropdownOpen: accountDropdownOpen,
|
dropdownOpen: accountDropdownOpen,
|
||||||
openDropdown: () => this.setState({ accountDropdownOpen: true }),
|
openDropdown: () => this.setState({ accountDropdownOpen: true }),
|
||||||
closeDropdown: () => this.setState({ accountDropdownOpen: false }),
|
closeDropdown: () => this.setState({ accountDropdownOpen: false }),
|
||||||
})
|
}),
|
||||||
|
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
@ -113,7 +113,7 @@ SignatureRequest.prototype.renderAccountInfo = function () {
|
|||||||
return h('div.request-signature__account-info', [
|
return h('div.request-signature__account-info', [
|
||||||
|
|
||||||
this.renderAccountDropdown(),
|
this.renderAccountDropdown(),
|
||||||
|
|
||||||
this.renderRequestIcon(),
|
this.renderRequestIcon(),
|
||||||
|
|
||||||
this.renderBalance(),
|
this.renderBalance(),
|
||||||
@ -128,18 +128,16 @@ SignatureRequest.prototype.renderRequestIcon = function () {
|
|||||||
h(Identicon, {
|
h(Identicon, {
|
||||||
diameter: 40,
|
diameter: 40,
|
||||||
address: requesterAddress,
|
address: requesterAddress,
|
||||||
})
|
}),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
SignatureRequest.prototype.renderRequestInfo = function () {
|
SignatureRequest.prototype.renderRequestInfo = function () {
|
||||||
const { requester } = this.props
|
|
||||||
|
|
||||||
return h('div.request-signature__request-info', [
|
return h('div.request-signature__request-info', [
|
||||||
|
|
||||||
h('div.request-signature__headline', [
|
h('div.request-signature__headline', [
|
||||||
`Your signature is being requested`,
|
`Your signature is being requested`,
|
||||||
])
|
]),
|
||||||
|
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
@ -163,11 +161,9 @@ SignatureRequest.prototype.renderBody = function () {
|
|||||||
|
|
||||||
if (type === 'personal_sign') {
|
if (type === 'personal_sign') {
|
||||||
rows = [{ name: 'Message', value: this.msgHexToText(data) }]
|
rows = [{ name: 'Message', value: this.msgHexToText(data) }]
|
||||||
}
|
} else if (type === 'eth_signTypedData') {
|
||||||
else if (type === 'eth_signTypedData') {
|
|
||||||
rows = data
|
rows = data
|
||||||
}
|
} else if (type === 'eth_sign') {
|
||||||
else if (type === 'eth_sign') {
|
|
||||||
rows = [{ name: 'Message', value: data }]
|
rows = [{ name: 'Message', value: data }]
|
||||||
notice = `Signing this message can have
|
notice = `Signing this message can have
|
||||||
dangerous side effects. Only sign messages from
|
dangerous side effects. Only sign messages from
|
||||||
@ -181,13 +177,18 @@ SignatureRequest.prototype.renderBody = function () {
|
|||||||
|
|
||||||
this.renderRequestInfo(),
|
this.renderRequestInfo(),
|
||||||
|
|
||||||
h('div.request-signature__notice', [notice]),
|
h('div.request-signature__notice', {
|
||||||
|
className: classnames({
|
||||||
|
'request-signature__notice': type === 'personal_sign' || type === 'eth_signTypedData',
|
||||||
|
'request-signature__warning': type === 'eth_sign',
|
||||||
|
}),
|
||||||
|
}, [notice]),
|
||||||
|
|
||||||
h('div.request-signature__rows', [
|
h('div.request-signature__rows', [
|
||||||
|
|
||||||
...rows.map(({ name, value }) => {
|
...rows.map(({ name, value }) => {
|
||||||
return h('div.request-signature__row', [
|
return h('div.request-signature__row', [
|
||||||
h('div.request-signature__row-title', [`${name}:`]),
|
h('div.request-signature__row-title', [`${name}:`]),
|
||||||
h('div.request-signature__row-value', value),
|
h('div.request-signature__row-value', value),
|
||||||
])
|
])
|
||||||
}),
|
}),
|
||||||
@ -199,7 +200,6 @@ SignatureRequest.prototype.renderBody = function () {
|
|||||||
|
|
||||||
SignatureRequest.prototype.renderFooter = function () {
|
SignatureRequest.prototype.renderFooter = function () {
|
||||||
const {
|
const {
|
||||||
goHome,
|
|
||||||
signPersonalMessage,
|
signPersonalMessage,
|
||||||
signTypedMessage,
|
signTypedMessage,
|
||||||
cancelPersonalMessage,
|
cancelPersonalMessage,
|
||||||
@ -216,12 +216,10 @@ SignatureRequest.prototype.renderFooter = function () {
|
|||||||
if (type === 'personal_sign') {
|
if (type === 'personal_sign') {
|
||||||
cancel = cancelPersonalMessage
|
cancel = cancelPersonalMessage
|
||||||
sign = signPersonalMessage
|
sign = signPersonalMessage
|
||||||
}
|
} else if (type === 'eth_signTypedData') {
|
||||||
else if (type === 'eth_signTypedData') {
|
|
||||||
cancel = cancelTypedMessage
|
cancel = cancelTypedMessage
|
||||||
sign = signTypedMessage
|
sign = signTypedMessage
|
||||||
}
|
} else if (type === 'eth_sign') {
|
||||||
else if (type === 'eth_sign') {
|
|
||||||
cancel = cancelMessage
|
cancel = cancelMessage
|
||||||
sign = signMessage
|
sign = signMessage
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const { Component } = require('react')
|
const { Component } = require('react')
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
|
const PropTypes = require('react').PropTypes
|
||||||
const classnames = require('classnames')
|
const classnames = require('classnames')
|
||||||
|
|
||||||
class TabBar extends Component {
|
class TabBar extends Component {
|
||||||
@ -37,4 +38,10 @@ class TabBar extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TabBar.propTypes = {
|
||||||
|
defaultTab: PropTypes.string,
|
||||||
|
tabs: PropTypes.array,
|
||||||
|
tabSelected: PropTypes.func,
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = TabBar
|
module.exports = TabBar
|
||||||
|
@ -6,7 +6,7 @@ const Identicon = require('./identicon')
|
|||||||
const prefixForNetwork = require('../../lib/etherscan-prefix-for-network')
|
const prefixForNetwork = require('../../lib/etherscan-prefix-for-network')
|
||||||
const selectors = require('../selectors')
|
const selectors = require('../selectors')
|
||||||
const actions = require('../actions')
|
const actions = require('../actions')
|
||||||
const { conversionUtil } = require('../conversion-util')
|
const { conversionUtil, multiplyCurrencies } = require('../conversion-util')
|
||||||
|
|
||||||
const TokenMenuDropdown = require('./dropdowns/token-menu-dropdown.js')
|
const TokenMenuDropdown = require('./dropdowns/token-menu-dropdown.js')
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ function mapStateToProps (state) {
|
|||||||
selectedTokenAddress: state.metamask.selectedTokenAddress,
|
selectedTokenAddress: state.metamask.selectedTokenAddress,
|
||||||
userAddress: selectors.getSelectedAddress(state),
|
userAddress: selectors.getSelectedAddress(state),
|
||||||
tokenExchangeRates: state.metamask.tokenExchangeRates,
|
tokenExchangeRates: state.metamask.tokenExchangeRates,
|
||||||
ethToUSDRate: state.metamask.conversionRate,
|
conversionRate: state.metamask.conversionRate,
|
||||||
sidebarOpen: state.appState.sidebarOpen,
|
sidebarOpen: state.appState.sidebarOpen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,32 +61,36 @@ TokenCell.prototype.render = function () {
|
|||||||
setSelectedToken,
|
setSelectedToken,
|
||||||
selectedTokenAddress,
|
selectedTokenAddress,
|
||||||
tokenExchangeRates,
|
tokenExchangeRates,
|
||||||
ethToUSDRate,
|
conversionRate,
|
||||||
hideSidebar,
|
hideSidebar,
|
||||||
sidebarOpen,
|
sidebarOpen,
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
// userAddress,
|
// userAddress,
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
const pair = `${symbol.toLowerCase()}_eth`;
|
|
||||||
|
|
||||||
let currentTokenToEthRate;
|
const pair = `${symbol.toLowerCase()}_eth`
|
||||||
let currentTokenInFiat;
|
|
||||||
let formattedUSD = ''
|
let currentTokenToFiatRate
|
||||||
|
let currentTokenInFiat
|
||||||
|
let formattedFiat = ''
|
||||||
|
|
||||||
if (tokenExchangeRates[pair]) {
|
if (tokenExchangeRates[pair]) {
|
||||||
currentTokenToEthRate = tokenExchangeRates[pair].rate;
|
currentTokenToFiatRate = multiplyCurrencies(
|
||||||
|
tokenExchangeRates[pair].rate,
|
||||||
|
conversionRate
|
||||||
|
)
|
||||||
currentTokenInFiat = conversionUtil(string, {
|
currentTokenInFiat = conversionUtil(string, {
|
||||||
fromNumericBase: 'dec',
|
fromNumericBase: 'dec',
|
||||||
fromCurrency: symbol,
|
fromCurrency: symbol,
|
||||||
toCurrency: 'USD',
|
toCurrency: currentCurrency.toUpperCase(),
|
||||||
numberOfDecimals: 2,
|
numberOfDecimals: 2,
|
||||||
conversionRate: currentTokenToEthRate,
|
conversionRate: currentTokenToFiatRate,
|
||||||
ethToUSDRate,
|
|
||||||
})
|
})
|
||||||
formattedUSD = `${currentTokenInFiat} ${currentCurrency.toUpperCase()}`;
|
formattedFiat = `${currentTokenInFiat} ${currentCurrency.toUpperCase()}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const showFiat = Boolean(currentTokenInFiat) && currentCurrency.toUpperCase() !== symbol
|
||||||
|
|
||||||
return (
|
return (
|
||||||
h('div.token-list-item', {
|
h('div.token-list-item', {
|
||||||
className: `token-list-item ${selectedTokenAddress === address ? 'token-list-item--active' : ''}`,
|
className: `token-list-item ${selectedTokenAddress === address ? 'token-list-item--active' : ''}`,
|
||||||
@ -108,9 +112,9 @@ TokenCell.prototype.render = function () {
|
|||||||
h('h.token-list-item__balance-wrapper', null, [
|
h('h.token-list-item__balance-wrapper', null, [
|
||||||
h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`),
|
h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`),
|
||||||
|
|
||||||
h('div.token-list-item__fiat-amount', {
|
showFiat && h('div.token-list-item__fiat-amount', {
|
||||||
style: {},
|
style: {},
|
||||||
}, formattedUSD),
|
}, formattedFiat),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
h('i.fa.fa-ellipsis-h.fa-lg.token-list-item__ellipsis.cursor-pointer', {
|
h('i.fa.fa-ellipsis-h.fa-lg.token-list-item__ellipsis.cursor-pointer', {
|
||||||
|
@ -3,7 +3,6 @@ const h = require('react-hyperscript')
|
|||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const TokenTracker = require('eth-token-tracker')
|
const TokenTracker = require('eth-token-tracker')
|
||||||
const TokenCell = require('./token-cell.js')
|
const TokenCell = require('./token-cell.js')
|
||||||
const normalizeAddress = require('eth-sig-util').normalize
|
|
||||||
const connect = require('react-redux').connect
|
const connect = require('react-redux').connect
|
||||||
const selectors = require('../selectors')
|
const selectors = require('../selectors')
|
||||||
|
|
||||||
@ -38,6 +37,7 @@ function TokenList () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TokenList.prototype.render = function () {
|
TokenList.prototype.render = function () {
|
||||||
|
const { userAddress } = this.props
|
||||||
const state = this.state
|
const state = this.state
|
||||||
const { tokens, isLoading, error } = state
|
const { tokens, isLoading, error } = state
|
||||||
|
|
||||||
@ -162,15 +162,15 @@ TokenList.prototype.componentWillUnmount = function () {
|
|||||||
this.tracker.stop()
|
this.tracker.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
function uniqueMergeTokens (tokensA, tokensB = []) {
|
// function uniqueMergeTokens (tokensA, tokensB = []) {
|
||||||
const uniqueAddresses = []
|
// const uniqueAddresses = []
|
||||||
const result = []
|
// const result = []
|
||||||
tokensA.concat(tokensB).forEach((token) => {
|
// tokensA.concat(tokensB).forEach((token) => {
|
||||||
const normal = normalizeAddress(token.address)
|
// const normal = normalizeAddress(token.address)
|
||||||
if (!uniqueAddresses.includes(normal)) {
|
// if (!uniqueAddresses.includes(normal)) {
|
||||||
uniqueAddresses.push(normal)
|
// uniqueAddresses.push(normal)
|
||||||
result.push(token)
|
// result.push(token)
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
return result
|
// return result
|
||||||
}
|
// }
|
||||||
|
@ -142,7 +142,7 @@ function formatDate (date) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderErrorOrWarning (transaction) {
|
function renderErrorOrWarning (transaction) {
|
||||||
const { status, err, warning } = transaction
|
const { status } = transaction
|
||||||
|
|
||||||
// show rejected
|
// show rejected
|
||||||
if (status === 'rejected') {
|
if (status === 'rejected') {
|
||||||
@ -151,31 +151,31 @@ function renderErrorOrWarning (transaction) {
|
|||||||
if (transaction.err || transaction.warning) {
|
if (transaction.err || transaction.warning) {
|
||||||
const { err, warning = {} } = transaction
|
const { err, warning = {} } = transaction
|
||||||
const errFirst = !!((err && warning) || err)
|
const errFirst = !!((err && warning) || err)
|
||||||
const message = errFirst ? err.message : warning.message
|
|
||||||
|
|
||||||
errFirst ? err.message : warning.message
|
errFirst ? err.message : warning.message
|
||||||
|
|
||||||
// show error
|
// show error
|
||||||
if (err) {
|
if (err) {
|
||||||
const message = err.message || ''
|
const message = err.message || ''
|
||||||
return (
|
return (
|
||||||
h(Tooltip, {
|
h(Tooltip, {
|
||||||
title: message,
|
title: message,
|
||||||
position: 'bottom',
|
position: 'bottom',
|
||||||
}, [
|
}, [
|
||||||
h(`span.error`, ` (Failed)`),
|
h(`span.error`, ` (Failed)`),
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// show warning
|
// show warning
|
||||||
if (warning) {
|
if (warning) {
|
||||||
const message = warning.message
|
const message = warning.message
|
||||||
return h(Tooltip, {
|
return h(Tooltip, {
|
||||||
title: message,
|
title: message,
|
||||||
position: 'bottom',
|
position: 'bottom',
|
||||||
}, [
|
}, [
|
||||||
h(`span.warning`, ` (Warning)`),
|
h(`span.warning`, ` (Warning)`),
|
||||||
])
|
])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,10 @@ const classnames = require('classnames')
|
|||||||
const abi = require('human-standard-token-abi')
|
const abi = require('human-standard-token-abi')
|
||||||
const abiDecoder = require('abi-decoder')
|
const abiDecoder = require('abi-decoder')
|
||||||
abiDecoder.addABI(abi)
|
abiDecoder.addABI(abi)
|
||||||
const prefixForNetwork = require('../../lib/etherscan-prefix-for-network')
|
|
||||||
const Identicon = require('./identicon')
|
const Identicon = require('./identicon')
|
||||||
|
const contractMap = require('eth-contract-metadata')
|
||||||
|
|
||||||
const { conversionUtil } = require('../conversion-util')
|
const { conversionUtil, multiplyCurrencies } = require('../conversion-util')
|
||||||
|
|
||||||
const { getCurrentCurrency } = require('../selectors')
|
const { getCurrentCurrency } = require('../selectors')
|
||||||
|
|
||||||
@ -19,12 +19,31 @@ function mapStateToProps (state) {
|
|||||||
return {
|
return {
|
||||||
tokens: state.metamask.tokens,
|
tokens: state.metamask.tokens,
|
||||||
currentCurrency: getCurrentCurrency(state),
|
currentCurrency: getCurrentCurrency(state),
|
||||||
|
tokenExchangeRates: state.metamask.tokenExchangeRates,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inherits(TxListItem, Component)
|
inherits(TxListItem, Component)
|
||||||
function TxListItem () {
|
function TxListItem () {
|
||||||
Component.call(this)
|
Component.call(this)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
total: null,
|
||||||
|
fiatTotal: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TxListItem.prototype.componentDidMount = async function () {
|
||||||
|
const { txParams = {} } = this.props
|
||||||
|
|
||||||
|
const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data)
|
||||||
|
const { name: txDataName } = decodedData || {}
|
||||||
|
|
||||||
|
const { total, fiatTotal } = txDataName === 'transfer'
|
||||||
|
? await this.getSendTokenTotal()
|
||||||
|
: this.getSendEtherTotal()
|
||||||
|
|
||||||
|
this.setState({ total, fiatTotal })
|
||||||
}
|
}
|
||||||
|
|
||||||
TxListItem.prototype.getAddressText = function () {
|
TxListItem.prototype.getAddressText = function () {
|
||||||
@ -84,23 +103,67 @@ TxListItem.prototype.getSendEtherTotal = function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TxListItem.prototype.getSendTokenTotal = function () {
|
TxListItem.prototype.getTokenInfo = async function () {
|
||||||
|
const { txParams = {}, tokenInfoGetter, tokens } = this.props
|
||||||
|
const toAddress = txParams.to
|
||||||
|
|
||||||
|
let decimals
|
||||||
|
let symbol
|
||||||
|
|
||||||
|
({ decimals, symbol } = tokens.filter(({ address }) => address === toAddress)[0] || {})
|
||||||
|
|
||||||
|
if (!decimals && !symbol) {
|
||||||
|
({ decimals, symbol } = contractMap[toAddress] || {})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!decimals && !symbol) {
|
||||||
|
({ decimals, symbol } = await tokenInfoGetter(toAddress))
|
||||||
|
}
|
||||||
|
|
||||||
|
return { decimals, symbol }
|
||||||
|
}
|
||||||
|
|
||||||
|
TxListItem.prototype.getSendTokenTotal = async function () {
|
||||||
const {
|
const {
|
||||||
txParams = {},
|
txParams = {},
|
||||||
tokens,
|
conversionRate,
|
||||||
|
tokenExchangeRates,
|
||||||
|
currentCurrency,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const toAddress = txParams.to
|
|
||||||
const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data)
|
const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data)
|
||||||
const { params = [] } = decodedData || {}
|
const { params = [] } = decodedData || {}
|
||||||
const { value } = params[1] || {}
|
const { value } = params[1] || {}
|
||||||
const { decimals, symbol } = tokens.filter(({ address }) => address === toAddress)[0] || {}
|
const { decimals, symbol } = await this.getTokenInfo()
|
||||||
|
|
||||||
const multiplier = Math.pow(10, Number(decimals || 0))
|
const multiplier = Math.pow(10, Number(decimals || 0))
|
||||||
const total = Number(value / multiplier)
|
const total = Number(value / multiplier)
|
||||||
|
|
||||||
|
const pair = symbol && `${symbol.toLowerCase()}_eth`
|
||||||
|
|
||||||
|
let tokenToFiatRate
|
||||||
|
let totalInFiat
|
||||||
|
|
||||||
|
if (tokenExchangeRates[pair]) {
|
||||||
|
tokenToFiatRate = multiplyCurrencies(
|
||||||
|
tokenExchangeRates[pair].rate,
|
||||||
|
conversionRate
|
||||||
|
)
|
||||||
|
|
||||||
|
totalInFiat = conversionUtil(total, {
|
||||||
|
fromNumericBase: 'dec',
|
||||||
|
toNumericBase: 'dec',
|
||||||
|
fromCurrency: symbol,
|
||||||
|
toCurrency: currentCurrency,
|
||||||
|
numberOfDecimals: 2,
|
||||||
|
conversionRate: tokenToFiatRate,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const showFiat = Boolean(totalInFiat) && currentCurrency.toUpperCase() !== symbol
|
||||||
|
|
||||||
return {
|
return {
|
||||||
total: `${total} ${symbol}`,
|
total: `${total} ${symbol}`,
|
||||||
|
fiatTotal: showFiat && `${totalInFiat} ${currentCurrency.toUpperCase()}`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,15 +175,8 @@ TxListItem.prototype.render = function () {
|
|||||||
dateString,
|
dateString,
|
||||||
address,
|
address,
|
||||||
className,
|
className,
|
||||||
txParams = {},
|
|
||||||
} = this.props
|
} = this.props
|
||||||
|
const { total, fiatTotal } = this.state
|
||||||
const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data)
|
|
||||||
const { name: txDataName } = decodedData || {}
|
|
||||||
|
|
||||||
const { total, fiatTotal } = txDataName === 'transfer'
|
|
||||||
? this.getSendTokenTotal()
|
|
||||||
: this.getSendEtherTotal()
|
|
||||||
|
|
||||||
return h(`div${className || ''}`, {
|
return h(`div${className || ''}`, {
|
||||||
key: transActionId,
|
key: transActionId,
|
||||||
@ -182,10 +238,10 @@ TxListItem.prototype.render = function () {
|
|||||||
}),
|
}),
|
||||||
}, total),
|
}, total),
|
||||||
|
|
||||||
h('span.tx-list-fiat-value', fiatTotal),
|
fiatTotal && h('span.tx-list-fiat-value', fiatTotal),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
]) // holding on icon from design
|
]), // holding on icon from design
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,10 @@ const prefixForNetwork = require('../../lib/etherscan-prefix-for-network')
|
|||||||
const selectors = require('../selectors')
|
const selectors = require('../selectors')
|
||||||
const TxListItem = require('./tx-list-item')
|
const TxListItem = require('./tx-list-item')
|
||||||
const ShiftListItem = require('./shift-list-item')
|
const ShiftListItem = require('./shift-list-item')
|
||||||
const { formatBalance, formatDate } = require('../util')
|
const { formatDate } = require('../util')
|
||||||
const { showConfTxPage } = require('../actions')
|
const { showConfTxPage } = require('../actions')
|
||||||
const classnames = require('classnames')
|
const classnames = require('classnames')
|
||||||
|
const { tokenInfoGetter } = require('../token-util')
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(TxList)
|
module.exports = connect(mapStateToProps, mapDispatchToProps)(TxList)
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ function mapStateToProps (state) {
|
|||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
function mapDispatchToProps (dispatch) {
|
||||||
return {
|
return {
|
||||||
showConfTxPage: ({ id }) => dispatch(showConfTxPage({ id }))
|
showConfTxPage: ({ id }) => dispatch(showConfTxPage({ id })),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,10 +31,11 @@ function TxList () {
|
|||||||
Component.call(this)
|
Component.call(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TxList.prototype.componentWillMount = function () {
|
||||||
|
this.tokenInfoGetter = tokenInfoGetter()
|
||||||
|
}
|
||||||
|
|
||||||
TxList.prototype.render = function () {
|
TxList.prototype.render = function () {
|
||||||
|
|
||||||
const { txsToRender, showConfTxPage } = this.props
|
|
||||||
|
|
||||||
return h('div.flex-column.tx-list-container', {}, [
|
return h('div.flex-column.tx-list-container', {}, [
|
||||||
|
|
||||||
h('div.flex-row.tx-list-header-wrapper', [
|
h('div.flex-row.tx-list-header-wrapper', [
|
||||||
@ -93,15 +95,15 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa
|
|||||||
txParams: transaction.txParams,
|
txParams: transaction.txParams,
|
||||||
transactionStatus,
|
transactionStatus,
|
||||||
transActionId,
|
transActionId,
|
||||||
key: transActionId,
|
|
||||||
dateString,
|
dateString,
|
||||||
address,
|
address,
|
||||||
transactionAmount,
|
transactionAmount,
|
||||||
transactionHash,
|
transactionHash,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
|
tokenInfoGetter: this.tokenInfoGetter,
|
||||||
}
|
}
|
||||||
|
|
||||||
const isUnapproved = transactionStatus === 'unapproved';
|
const isUnapproved = transactionStatus === 'unapproved'
|
||||||
|
|
||||||
if (isUnapproved) {
|
if (isUnapproved) {
|
||||||
opts.onClick = () => showConfTxPage({id: transActionId})
|
opts.onClick = () => showConfTxPage({id: transActionId})
|
||||||
|
@ -114,14 +114,14 @@ ConfirmTxScreen.prototype.render = function () {
|
|||||||
function currentTxView (opts) {
|
function currentTxView (opts) {
|
||||||
log.info('rendering current tx view')
|
log.info('rendering current tx view')
|
||||||
const { txData } = opts
|
const { txData } = opts
|
||||||
const { txParams, msgParams, type } = txData
|
const { txParams, msgParams } = txData
|
||||||
|
|
||||||
if (txParams) {
|
if (txParams) {
|
||||||
log.debug('txParams detected, rendering pending tx')
|
log.debug('txParams detected, rendering pending tx')
|
||||||
return h(PendingTx, opts)
|
return h(PendingTx, opts)
|
||||||
} else if (msgParams) {
|
} else if (msgParams) {
|
||||||
log.debug('msgParams detected, rendering pending msg')
|
log.debug('msgParams detected, rendering pending msg')
|
||||||
|
|
||||||
return h(SignatureRequest, opts)
|
return h(SignatureRequest, opts)
|
||||||
|
|
||||||
// if (type === 'eth_sign') {
|
// if (type === 'eth_sign') {
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
* @param {string} [options.fromDenomination = 'WEI'] The denomination of the passed value
|
* @param {string} [options.fromDenomination = 'WEI'] The denomination of the passed value
|
||||||
* @param {number} [options.numberOfDecimals] The desired number of in the result
|
* @param {number} [options.numberOfDecimals] The desired number of in the result
|
||||||
* @param {number} [options.conversionRate] The rate to use to make the fromCurrency -> toCurrency conversion
|
* @param {number} [options.conversionRate] The rate to use to make the fromCurrency -> toCurrency conversion
|
||||||
* @param {number} [options.ethToUSDRate] If present, a second conversion - at ethToUSDRate - happens after conversionRate is applied.
|
|
||||||
* @returns {(number | string | BN)}
|
* @returns {(number | string | BN)}
|
||||||
*
|
*
|
||||||
* The utility passes value along with the options as a single object to the `converter` function.
|
* The utility passes value along with the options as a single object to the `converter` function.
|
||||||
@ -23,6 +22,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const BigNumber = require('bignumber.js')
|
const BigNumber = require('bignumber.js')
|
||||||
|
const ethUtil = require('ethereumjs-util')
|
||||||
|
const BN = ethUtil.BN
|
||||||
const R = require('ramda')
|
const R = require('ramda')
|
||||||
const { stripHexPrefix } = require('ethereumjs-util')
|
const { stripHexPrefix } = require('ethereumjs-util')
|
||||||
|
|
||||||
@ -38,6 +39,7 @@ const BIG_NUMBER_GWEI_MULTIPLIER = new BigNumber('1000000000')
|
|||||||
const convert = R.invoker(1, 'times')
|
const convert = R.invoker(1, 'times')
|
||||||
const round = R.invoker(2, 'round')(R.__, BigNumber.ROUND_DOWN)
|
const round = R.invoker(2, 'round')(R.__, BigNumber.ROUND_DOWN)
|
||||||
const invertConversionRate = conversionRate => () => new BigNumber(1.0).div(conversionRate)
|
const invertConversionRate = conversionRate => () => new BigNumber(1.0).div(conversionRate)
|
||||||
|
const decToBigNumberViaString = n => R.pipe(String, toBigNumber['dec'])
|
||||||
|
|
||||||
// Setter Maps
|
// Setter Maps
|
||||||
const toBigNumber = {
|
const toBigNumber = {
|
||||||
@ -51,7 +53,7 @@ const toNormalizedDenomination = {
|
|||||||
}
|
}
|
||||||
const toSpecifiedDenomination = {
|
const toSpecifiedDenomination = {
|
||||||
WEI: bigNumber => bigNumber.times(BIG_NUMBER_WEI_MULTIPLIER).round(),
|
WEI: bigNumber => bigNumber.times(BIG_NUMBER_WEI_MULTIPLIER).round(),
|
||||||
GWEI: bigNumber => bigNumber.times(BIG_NUMBER_GWEI_MULTIPLIER).round(),
|
GWEI: bigNumber => bigNumber.times(BIG_NUMBER_GWEI_MULTIPLIER).round(1),
|
||||||
}
|
}
|
||||||
const baseChange = {
|
const baseChange = {
|
||||||
hex: n => n.toString(16),
|
hex: n => n.toString(16),
|
||||||
@ -95,16 +97,16 @@ const whenPropApplySetterMap = (prop, setterMap) => whenPredSetWithPropAndSetter
|
|||||||
|
|
||||||
// Conversion utility function
|
// Conversion utility function
|
||||||
const converter = R.pipe(
|
const converter = R.pipe(
|
||||||
|
whenPredSetCRWithPropAndSetter(R.prop('conversionRate'), 'conversionRate', decToBigNumberViaString),
|
||||||
whenPredSetCRWithPropAndSetter(R.prop('invertConversionRate'), 'conversionRate', invertConversionRate),
|
whenPredSetCRWithPropAndSetter(R.prop('invertConversionRate'), 'conversionRate', invertConversionRate),
|
||||||
whenPropApplySetterMap('fromNumericBase', toBigNumber),
|
whenPropApplySetterMap('fromNumericBase', toBigNumber),
|
||||||
whenPropApplySetterMap('fromDenomination', toNormalizedDenomination),
|
whenPropApplySetterMap('fromDenomination', toNormalizedDenomination),
|
||||||
whenPredSetWithPropAndSetter(fromAndToCurrencyPropsNotEqual, 'conversionRate', convert),
|
whenPredSetWithPropAndSetter(fromAndToCurrencyPropsNotEqual, 'conversionRate', convert),
|
||||||
whenPropApplySetterMap('toDenomination', toSpecifiedDenomination),
|
whenPropApplySetterMap('toDenomination', toSpecifiedDenomination),
|
||||||
whenPredSetWithPropAndSetter(R.prop('ethToUSDRate'), 'ethToUSDRate', convert),
|
|
||||||
whenPredSetWithPropAndSetter(R.prop('numberOfDecimals'), 'numberOfDecimals', round),
|
whenPredSetWithPropAndSetter(R.prop('numberOfDecimals'), 'numberOfDecimals', round),
|
||||||
whenPropApplySetterMap('toNumericBase', baseChange),
|
whenPropApplySetterMap('toNumericBase', baseChange),
|
||||||
R.view(R.lensProp('value'))
|
R.view(R.lensProp('value'))
|
||||||
);
|
)
|
||||||
|
|
||||||
const conversionUtil = (value, {
|
const conversionUtil = (value, {
|
||||||
fromCurrency = null,
|
fromCurrency = null,
|
||||||
@ -115,7 +117,6 @@ const conversionUtil = (value, {
|
|||||||
toDenomination,
|
toDenomination,
|
||||||
numberOfDecimals,
|
numberOfDecimals,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
ethToUSDRate,
|
|
||||||
invertConversionRate,
|
invertConversionRate,
|
||||||
}) => converter({
|
}) => converter({
|
||||||
fromCurrency,
|
fromCurrency,
|
||||||
@ -126,18 +127,17 @@ const conversionUtil = (value, {
|
|||||||
toDenomination,
|
toDenomination,
|
||||||
numberOfDecimals,
|
numberOfDecimals,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
ethToUSDRate,
|
|
||||||
invertConversionRate,
|
invertConversionRate,
|
||||||
value: value || '0',
|
value: value || '0',
|
||||||
});
|
})
|
||||||
|
|
||||||
const addCurrencies = (a, b, options = {}) => {
|
const addCurrencies = (a, b, options = {}) => {
|
||||||
const {
|
const {
|
||||||
aBase,
|
aBase,
|
||||||
bBase,
|
bBase,
|
||||||
...conversionOptions,
|
...conversionOptions
|
||||||
} = options
|
} = options
|
||||||
const value = (new BigNumber(a, aBase)).add(b, bBase);
|
const value = (new BigNumber(a, aBase)).add(b, bBase)
|
||||||
|
|
||||||
return converter({
|
return converter({
|
||||||
value,
|
value,
|
||||||
@ -149,10 +149,13 @@ const multiplyCurrencies = (a, b, options = {}) => {
|
|||||||
const {
|
const {
|
||||||
multiplicandBase,
|
multiplicandBase,
|
||||||
multiplierBase,
|
multiplierBase,
|
||||||
...conversionOptions,
|
...conversionOptions
|
||||||
} = options
|
} = options
|
||||||
|
|
||||||
const value = (new BigNumber(a, multiplicandBase)).times(b, multiplierBase);
|
const bigNumberA = new BigNumber(String(a), multiplicandBase)
|
||||||
|
const bigNumberB = new BigNumber(String(b), multiplierBase)
|
||||||
|
|
||||||
|
const value = bigNumberA.times(bigNumberB)
|
||||||
|
|
||||||
return converter({
|
return converter({
|
||||||
value,
|
value,
|
||||||
@ -162,16 +165,41 @@ const multiplyCurrencies = (a, b, options = {}) => {
|
|||||||
|
|
||||||
const conversionGreaterThan = (
|
const conversionGreaterThan = (
|
||||||
{ ...firstProps },
|
{ ...firstProps },
|
||||||
{ ...secondProps },
|
{ ...secondProps },
|
||||||
) => {
|
) => {
|
||||||
const firstValue = converter({ ...firstProps })
|
const firstValue = converter({ ...firstProps })
|
||||||
const secondValue = converter({ ...secondProps })
|
const secondValue = converter({ ...secondProps })
|
||||||
return firstValue.gt(secondValue)
|
return firstValue.gt(secondValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const conversionGTE = (
|
||||||
|
{ ...firstProps },
|
||||||
|
{ ...secondProps },
|
||||||
|
) => {
|
||||||
|
const firstValue = converter({ ...firstProps })
|
||||||
|
const secondValue = converter({ ...secondProps })
|
||||||
|
return firstValue.greaterThanOrEqualTo(secondValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
const conversionLTE = (
|
||||||
|
{ ...firstProps },
|
||||||
|
{ ...secondProps },
|
||||||
|
) => {
|
||||||
|
const firstValue = converter({ ...firstProps })
|
||||||
|
const secondValue = converter({ ...secondProps })
|
||||||
|
return firstValue.lessThanOrEqualTo(secondValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
const toNegative = (n, options = {}) => {
|
||||||
|
return multiplyCurrencies(n, -1, options)
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
conversionUtil,
|
conversionUtil,
|
||||||
addCurrencies,
|
addCurrencies,
|
||||||
multiplyCurrencies,
|
multiplyCurrencies,
|
||||||
conversionGreaterThan,
|
conversionGreaterThan,
|
||||||
}
|
conversionGTE,
|
||||||
|
conversionLTE,
|
||||||
|
toNegative,
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
width: 250px;
|
width: 250px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
border: 1px solid $alto;
|
||||||
|
|
||||||
&--error {
|
&--error {
|
||||||
border: 1px solid $monzo;
|
border: 1px solid $monzo;
|
||||||
|
@ -131,8 +131,8 @@
|
|||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__notice {
|
&__notice,
|
||||||
color: #9B9B9B;
|
&__warning {
|
||||||
font-family: "Avenir Next";
|
font-family: "Avenir Next";
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 19px;
|
line-height: 19px;
|
||||||
@ -142,6 +142,14 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__notice {
|
||||||
|
color: $dusty-gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__warning {
|
||||||
|
color: $crimson;
|
||||||
|
}
|
||||||
|
|
||||||
&__rows {
|
&__rows {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
@ -37,11 +37,7 @@ MainContainer.prototype.render = function () {
|
|||||||
break
|
break
|
||||||
case 'config':
|
case 'config':
|
||||||
log.debug('rendering config screen from unlock screen.')
|
log.debug('rendering config screen from unlock screen.')
|
||||||
contents = {
|
return h(Settings, {key: 'config'})
|
||||||
component: Settings,
|
|
||||||
key: 'config',
|
|
||||||
}
|
|
||||||
break
|
|
||||||
default:
|
default:
|
||||||
log.debug('rendering locked screen')
|
log.debug('rendering locked screen')
|
||||||
contents = {
|
contents = {
|
||||||
|
@ -44,7 +44,7 @@ function reduceApp (state, action) {
|
|||||||
},
|
},
|
||||||
previousModalState: {
|
previousModalState: {
|
||||||
name: null,
|
name: null,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
sidebarOpen: false,
|
sidebarOpen: false,
|
||||||
networkDropdownOpen: false,
|
networkDropdownOpen: false,
|
||||||
@ -100,7 +100,7 @@ function reduceApp (state, action) {
|
|||||||
state.appState.modal,
|
state.appState.modal,
|
||||||
{ open: false },
|
{ open: false },
|
||||||
{ modalState: { name: null } },
|
{ modalState: { name: null } },
|
||||||
{ previousModalState: appState.modal.modalState},
|
{ previousModalState: appState.modal.modalState},
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ function reduceMetamask (state, action) {
|
|||||||
errors: {
|
errors: {
|
||||||
...metamaskState.send.errors,
|
...metamaskState.send.errors,
|
||||||
...action.value,
|
...action.value,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
const { inherits } = require('util')
|
const { inherits } = require('util')
|
||||||
const PersistentForm = require('../lib/persistent-form')
|
const PersistentForm = require('../lib/persistent-form')
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const connect = require('react-redux').connect
|
|
||||||
const classnames = require('classnames')
|
|
||||||
|
|
||||||
const Identicon = require('./components/identicon')
|
const Identicon = require('./components/identicon')
|
||||||
const FromDropdown = require('./components/send/from-dropdown')
|
const FromDropdown = require('./components/send/from-dropdown')
|
||||||
@ -13,12 +11,9 @@ const GasFeeDisplay = require('./components/send/gas-fee-display-v2')
|
|||||||
|
|
||||||
const { MIN_GAS_TOTAL } = require('./components/send/send-constants')
|
const { MIN_GAS_TOTAL } = require('./components/send/send-constants')
|
||||||
|
|
||||||
const { showModal } = require('./actions')
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
multiplyCurrencies,
|
multiplyCurrencies,
|
||||||
conversionGreaterThan,
|
conversionGreaterThan,
|
||||||
addCurrencies,
|
|
||||||
} = require('./conversion-util')
|
} = require('./conversion-util')
|
||||||
const {
|
const {
|
||||||
isBalanceSufficient,
|
isBalanceSufficient,
|
||||||
@ -99,7 +94,7 @@ SendTransactionScreen.prototype.renderHeaderIcon = function () {
|
|||||||
diameter: 40,
|
diameter: 40,
|
||||||
address: selectedToken.address,
|
address: selectedToken.address,
|
||||||
})
|
})
|
||||||
: h('img.send-v2__send-header-icon', { src: '../images/eth_logo.svg' })
|
: h('img.send-v2__send-header-icon', { src: '../images/eth_logo.svg' }),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,12 +135,12 @@ SendTransactionScreen.prototype.renderHeader = function () {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
SendTransactionScreen.prototype.renderErrorMessage = function(errorType) {
|
SendTransactionScreen.prototype.renderErrorMessage = function (errorType) {
|
||||||
const { errors } = this.props
|
const { errors } = this.props
|
||||||
const errorMessage = errors[errorType];
|
const errorMessage = errors[errorType]
|
||||||
|
|
||||||
return errorMessage
|
return errorMessage
|
||||||
? h('div.send-v2__error', [ errorMessage ] )
|
? h('div.send-v2__error', [ errorMessage ])
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +149,6 @@ SendTransactionScreen.prototype.renderFromRow = function () {
|
|||||||
from,
|
from,
|
||||||
fromAccounts,
|
fromAccounts,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
setSelectedAddress,
|
|
||||||
updateSendFrom,
|
updateSendFrom,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
@ -243,7 +237,6 @@ SendTransactionScreen.prototype.validateAmount = function (value) {
|
|||||||
amountConversionRate,
|
amountConversionRate,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
primaryCurrency,
|
primaryCurrency,
|
||||||
toCurrency,
|
|
||||||
selectedToken,
|
selectedToken,
|
||||||
gasTotal,
|
gasTotal,
|
||||||
} = this.props
|
} = this.props
|
||||||
@ -440,7 +433,6 @@ SendTransactionScreen.prototype.onSubmit = function (event) {
|
|||||||
signTokenTx,
|
signTokenTx,
|
||||||
signTx,
|
signTx,
|
||||||
selectedToken,
|
selectedToken,
|
||||||
toAccounts,
|
|
||||||
clearSend,
|
clearSend,
|
||||||
errors: { amount: amountError, to: toError },
|
errors: { amount: amountError, to: toError },
|
||||||
} = this.props
|
} = this.props
|
||||||
|
1094
ui/app/send.js
1094
ui/app/send.js
File diff suppressed because it is too large
Load Diff
36
ui/app/token-util.js
Normal file
36
ui/app/token-util.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
const abi = require('human-standard-token-abi')
|
||||||
|
const Eth = require('ethjs-query')
|
||||||
|
const EthContract = require('ethjs-contract')
|
||||||
|
|
||||||
|
const tokenInfoGetter = function () {
|
||||||
|
if (typeof global.ethereumProvider === 'undefined') return
|
||||||
|
|
||||||
|
const eth = new Eth(global.ethereumProvider)
|
||||||
|
const contract = new EthContract(eth)
|
||||||
|
const TokenContract = contract(abi)
|
||||||
|
|
||||||
|
const tokens = {}
|
||||||
|
|
||||||
|
return async (address) => {
|
||||||
|
if (tokens[address]) {
|
||||||
|
return tokens[address]
|
||||||
|
}
|
||||||
|
|
||||||
|
const contract = TokenContract.at(address)
|
||||||
|
|
||||||
|
const result = await Promise.all([
|
||||||
|
contract.symbol(),
|
||||||
|
contract.decimals(),
|
||||||
|
])
|
||||||
|
|
||||||
|
const [ symbol = [], decimals = [] ] = result
|
||||||
|
|
||||||
|
tokens[address] = { symbol: symbol[0], decimals: decimals[0] }
|
||||||
|
|
||||||
|
return tokens[address]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
tokenInfoGetter,
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user