diff options
author | kumavis <kumavis@users.noreply.github.com> | 2016-05-20 08:06:03 +0800 |
---|---|---|
committer | kumavis <kumavis@users.noreply.github.com> | 2016-05-20 08:06:03 +0800 |
commit | 9daf170b98f71f4845fe0c71faad22dc32514d1b (patch) | |
tree | 73cf15ffbffba708d8c32264226b31dc0a8ecb0e | |
parent | f86a1bdcb07e98ce740109f13b130afb82f35b3a (diff) | |
parent | 47540ad0b3c92df8061bb9c73159670ca2bc03ba (diff) | |
download | tangerine-wallet-browser-9daf170b98f71f4845fe0c71faad22dc32514d1b.tar tangerine-wallet-browser-9daf170b98f71f4845fe0c71faad22dc32514d1b.tar.gz tangerine-wallet-browser-9daf170b98f71f4845fe0c71faad22dc32514d1b.tar.bz2 tangerine-wallet-browser-9daf170b98f71f4845fe0c71faad22dc32514d1b.tar.lz tangerine-wallet-browser-9daf170b98f71f4845fe0c71faad22dc32514d1b.tar.xz tangerine-wallet-browser-9daf170b98f71f4845fe0c71faad22dc32514d1b.tar.zst tangerine-wallet-browser-9daf170b98f71f4845fe0c71faad22dc32514d1b.zip |
Merge pull request #192 from MetaMask/ZeroValueTxs
Zero value txs
-rw-r--r-- | CHANGELOG.md | 8 | ||||
-rw-r--r-- | test/unit/util_test.js | 68 | ||||
-rw-r--r-- | ui/app/account-detail.js | 5 | ||||
-rw-r--r-- | ui/app/send.js | 20 | ||||
-rw-r--r-- | ui/app/util.js | 37 |
5 files changed, 120 insertions, 18 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 13cff9927..8681c9517 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,11 @@ ## Current Master -- UI Overhaul per Vlad Todirut's designs -- Replaced identicons with jazzicons -- Fixed glitchy transitions +- UI Overhaul per Vlad Todirut's designs. +- Replaced identicons with jazzicons. +- Fixed glitchy transitions. +- Added support for capitalization-based address checksums. +- Send value is no longer limited by javascript number precision, and is always in ETH. ## 1.8.4 2016-05-13 diff --git a/test/unit/util_test.js b/test/unit/util_test.js index 3f46d4e9b..b091d5bc7 100644 --- a/test/unit/util_test.js +++ b/test/unit/util_test.js @@ -17,6 +17,53 @@ describe('util', function() { this.sinon.restore() }) + describe('addressSummary', function() { + it('should add case-sensitive checksum', function() { + var address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825' + var result = util.addressSummary(address) + assert.equal(result, '0xFDEa65C8...b825') + }) + }) + + describe('isValidAddress', function() { + it('should allow 40-char non-prefixed hex', function() { + var address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b825' + var result = util.isValidAddress(address) + assert.ok(result) + }) + + it('should allow 42-char non-prefixed hex', function() { + var address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825' + var result = util.isValidAddress(address) + assert.ok(result) + }) + + it('should not allow less non hex-prefixed', function() { + var address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b85' + var result = util.isValidAddress(address) + assert.ok(!result) + }) + + it('should not allow less hex-prefixed', function() { + var address = '0xfdea65ce26263f6d9a1b5de9555d2931a33b85' + var result = util.isValidAddress(address) + assert.ok(!result) + }) + + it('should recognize correct capitalized checksum', function() { + var address = '0xFDEa65C8e26263F6d9A1B5de9555D2931A33b825' + var result = util.isValidAddress(address) + assert.ok(result) + }) + + it('should recognize incorrect capitalized checksum', function() { + var address = '0xFDea65C8e26263F6d9A1B5de9555D2931A33b825' + var result = util.isValidAddress(address) + assert.ok(!result) + }) + + }) + describe('numericBalance', function() { it('should return a BN 0 if given nothing', function() { @@ -112,8 +159,29 @@ describe('util', function() { }) }) + describe('normalizeEthStringToWei', function() { + it('should convert decimal eth to pure wei BN', function() { + var input = '1.23456789' + var output = util.normalizeEthStringToWei(input) + assert.equal(output.toString(10), '1234567890000000000') + }) + + it('should convert 1 to expected wei', function() { + var input = '1' + var output = util.normalizeEthStringToWei(input) + assert.equal(output.toString(10), ethInWei) + }) + }) + describe('#normalizeNumberToWei', function() { + it('should handle a simple use case', function() { + var input = 0.0002 + var output = util.normalizeNumberToWei(input, 'ether') + var str = output.toString(10) + assert.equal(str, '200000000000000') + }) + it('should convert a kwei number to the appropriate equivalent wei', function() { var result = util.normalizeNumberToWei(1.111, 'kwei') assert.equal(result.toString(10), '1111', 'accepts decimals') diff --git a/ui/app/account-detail.js b/ui/app/account-detail.js index 263e48441..489392473 100644 --- a/ui/app/account-detail.js +++ b/ui/app/account-detail.js @@ -13,6 +13,7 @@ const Identicon = require('./components/identicon') const EtherBalance = require('./components/eth-balance') const transactionList = require('./components/transaction-list') const ExportAccountView = require('./components/account-export') +const ethUtil = require('ethereumjs-util') module.exports = connect(mapStateToProps)(AccountDetailScreen) @@ -110,7 +111,7 @@ AccountDetailScreen.prototype.render = function() { }), h('i.fa.fa-clipboard.fa-md.cursor-pointer.color-orange', { - onClick: () => copyToClipboard(selected), + onClick: () => copyToClipboard(ethUtil.toChecksumAddress(selected)), }), ]), @@ -133,7 +134,7 @@ AccountDetailScreen.prototype.render = function() { }, 'SEND ETH'), ]), - + ]), // subview (tx history, pk export confirm) diff --git a/ui/app/send.js b/ui/app/send.js index 52e56132c..ba4e5bfff 100644 --- a/ui/app/send.js +++ b/ui/app/send.js @@ -206,20 +206,21 @@ SendTransactionScreen.prototype.back = function() { this.props.dispatch(actions.backToAccountDetail(address)) } -SendTransactionScreen.prototype.onSubmit = function(event) { - var recipient = document.querySelector('input[name="address"]').value +SendTransactionScreen.prototype.onSubmit = function() { - var inputAmount = parseFloat(document.querySelector('input[name="amount"]').value) - var value = util.normalizeNumberToWei(inputAmount, 'ether') - - var balance = this.props.balance + const recipient = document.querySelector('input[name="address"]').value + const input = document.querySelector('input[name="amount"]').value + const value = util.normalizeEthStringToWei(input) + const txData = document.querySelector('input[name="txData"]').value + const balance = this.props.balance if (value.gt(balance)) { var message = 'Insufficient funds.' return this.props.dispatch(actions.displayWarning(message)) } - if (recipient.length !== 42) { - var message = 'Recipient address is the incorrect length.' + + if ((!util.isValidAddress(recipient) && !txData) || (!recipient && !txData)) { + var message = 'Recipient address is invalid.' return this.props.dispatch(actions.displayWarning(message)) } @@ -227,12 +228,11 @@ SendTransactionScreen.prototype.onSubmit = function(event) { this.props.dispatch(actions.showLoadingIndication()) var txParams = { - to: recipient, from: this.props.address, value: '0x' + value.toString(16), } - var txData = document.querySelector('input[name="txData"]').value + if (recipient) txParams.to = ethUtil.addHexPrefix(recipient) if (txData) txParams.data = txData this.props.dispatch(actions.signTx(txParams)) diff --git a/ui/app/util.js b/ui/app/util.js index 0f3f191aa..81a029350 100644 --- a/ui/app/util.js +++ b/ui/app/util.js @@ -21,6 +21,8 @@ for (var currency in valueTable) { module.exports = { valuesFor: valuesFor, addressSummary: addressSummary, + isAllOneCase: isAllOneCase, + isValidAddress: isValidAddress, numericBalance: numericBalance, parseBalance: parseBalance, formatBalance: formatBalance, @@ -29,6 +31,7 @@ module.exports = { ethToWei: ethToWei, weiToEth: weiToEth, normalizeToWei: normalizeToWei, + normalizeEthStringToWei: normalizeEthStringToWei, normalizeNumberToWei: normalizeNumberToWei, valueTable: valueTable, bnTable: bnTable, @@ -42,7 +45,21 @@ function valuesFor(obj) { } function addressSummary(address) { - return address ? address.slice(0,2+8)+'...'+address.slice(-4) : '...' + if (!address) return '' + var checked = ethUtil.toChecksumAddress(address) + return checked ? checked.slice(0,2+8)+'...'+checked.slice(-4) : '...' +} + +function isValidAddress(address) { + var prefixed = ethUtil.addHexPrefix(address) + return isAllOneCase(prefixed) && ethUtil.isValidAddress(prefixed) || ethUtil.isValidChecksumAddress(prefixed) +} + +function isAllOneCase(address) { + if (!address) return true + var lower = address.toLowerCase() + var upper = address.toUpperCase() + return address === lower || address === upper } // Takes wei Hex, returns wei BN, even if input is null @@ -106,9 +123,23 @@ function normalizeToWei(amount, currency) { return amount } -var multiple = new ethUtil.BN('1000', 10) +function normalizeEthStringToWei(str) { + const parts = str.split('.') + let eth = new ethUtil.BN(parts[0], 10).mul(bnTable.wei) + if (parts[1]) { + var decimal = parts[1] + while(decimal.length < 18) { + decimal += '0' + } + const decimalBN = new ethUtil.BN(decimal, 10) + eth = eth.add(decimalBN) + } + return eth +} + +var multiple = new ethUtil.BN('10000', 10) function normalizeNumberToWei(n, currency) { - var enlarged = n * 1000 + var enlarged = n * 10000 var amount = new ethUtil.BN(String(enlarged), 10) return normalizeToWei(amount, currency).div(multiple) } |