diff --git a/test/unit/util_test.js b/test/unit/util_test.js index 3f46d4e9b..020fad783 100644 --- a/test/unit/util_test.js +++ b/test/unit/util_test.js @@ -17,6 +17,52 @@ 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() { 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 67dd15f81..044311b94 100644 --- a/ui/app/send.js +++ b/ui/app/send.js @@ -219,7 +219,7 @@ SendTransactionScreen.prototype.onSubmit = function() { return this.props.dispatch(actions.displayWarning(message)) } - if ((recipient.length !== 42 && !txData) || (!recipient && !txData)) { + if ((util.isValidAddress(recipient) && !txData) || (!recipient && !txData)) { var message = 'Recipient address is invalid.' return this.props.dispatch(actions.displayWarning(message)) } diff --git a/ui/app/util.js b/ui/app/util.js index 0f3f191aa..d8a0313ea 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, @@ -42,7 +44,19 @@ function valuesFor(obj) { } function addressSummary(address) { - return address ? address.slice(0,2+8)+'...'+address.slice(-4) : '...' + 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) { + var lower = address.toLowerCase() + var upper = address.toUpperCase() + return address === lower || address === upper } // Takes wei Hex, returns wei BN, even if input is null