mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge branch 'master' into uiFixes
This commit is contained in:
commit
2c2fcd60bf
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,3 +10,4 @@ package
|
|||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
builds/
|
builds/
|
||||||
|
notes.txt
|
||||||
|
@ -2,9 +2,16 @@
|
|||||||
|
|
||||||
## Current Master
|
## Current Master
|
||||||
|
|
||||||
|
- Show network status in title bar
|
||||||
|
- Added seed word recovery to config screen.
|
||||||
|
- Clicking network status indicator now reveals a provider menu.
|
||||||
|
|
||||||
|
## 2.2.0 2016-06-02
|
||||||
|
|
||||||
- Redesigned init, vault create, vault restore and seed confirmation screens.
|
- Redesigned init, vault create, vault restore and seed confirmation screens.
|
||||||
- Added pending transactions to transaction list on account screen.
|
- Added pending transactions to transaction list on account screen.
|
||||||
- Clicking a pending transaction takes you back to the transaction approval screen.
|
- Clicking a pending transaction takes you back to the transaction approval screen.
|
||||||
|
- Update provider-engine to fix intermittent out of gas errors.
|
||||||
|
|
||||||
## 2.1.0 2016-05-26
|
## 2.1.0 2016-05-26
|
||||||
|
|
||||||
|
BIN
app/images/ethereum-network.jpg
Normal file
BIN
app/images/ethereum-network.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
app/images/morden-test-network.jpg
Normal file
BIN
app/images/morden-test-network.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
app/images/no-connection.jpg
Normal file
BIN
app/images/no-connection.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.8 KiB |
BIN
app/images/unknown-private-network.jpg
Normal file
BIN
app/images/unknown-private-network.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "__MSG_appName__",
|
"name": "__MSG_appName__",
|
||||||
"short_name": "Metamask",
|
"short_name": "Metamask",
|
||||||
"version": "2.1.0",
|
"version": "2.2.0",
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"description": "__MSG_appDescription__",
|
"description": "__MSG_appDescription__",
|
||||||
"icons": {
|
"icons": {
|
||||||
|
@ -76,13 +76,20 @@ var providerOpts = {
|
|||||||
var provider = MetaMaskProvider(providerOpts)
|
var provider = MetaMaskProvider(providerOpts)
|
||||||
var web3 = new Web3(provider)
|
var web3 = new Web3(provider)
|
||||||
idStore.web3 = web3
|
idStore.web3 = web3
|
||||||
idStore.getNetwork(3)
|
idStore.getNetwork()
|
||||||
|
|
||||||
// log new blocks
|
// log new blocks
|
||||||
provider.on('block', function(block){
|
provider.on('block', function(block){
|
||||||
console.log('BLOCK CHANGED:', '#'+block.number.toString('hex'), '0x'+block.hash.toString('hex'))
|
console.log('BLOCK CHANGED:', '#'+block.number.toString('hex'), '0x'+block.hash.toString('hex'))
|
||||||
|
|
||||||
|
// Check network when restoring connectivity:
|
||||||
|
if (idStore._currentState.network === 'loading') {
|
||||||
|
idStore.getNetwork()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
provider.on('error', idStore.getNetwork.bind(idStore))
|
||||||
|
|
||||||
var ethStore = new EthStore(provider)
|
var ethStore = new EthStore(provider)
|
||||||
idStore.setStore(ethStore)
|
idStore.setStore(ethStore)
|
||||||
|
|
||||||
@ -145,7 +152,7 @@ function setupPublicConfig(stream){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupProviderConnection(stream, originDomain){
|
function setupProviderConnection(stream, originDomain){
|
||||||
|
|
||||||
stream.on('data', function onRpcRequest(payload){
|
stream.on('data', function onRpcRequest(payload){
|
||||||
// Append origin to rpc payload
|
// Append origin to rpc payload
|
||||||
payload.origin = originDomain
|
payload.origin = originDomain
|
||||||
@ -195,6 +202,8 @@ function setupControllerConnection(stream){
|
|||||||
exportAccount: idStore.exportAccount.bind(idStore),
|
exportAccount: idStore.exportAccount.bind(idStore),
|
||||||
revealAccount: idStore.revealAccount.bind(idStore),
|
revealAccount: idStore.revealAccount.bind(idStore),
|
||||||
saveAccountLabel: idStore.saveAccountLabel.bind(idStore),
|
saveAccountLabel: idStore.saveAccountLabel.bind(idStore),
|
||||||
|
tryPassword: idStore.tryPassword.bind(idStore),
|
||||||
|
recoverSeed: idStore.recoverSeed.bind(idStore),
|
||||||
})
|
})
|
||||||
stream.pipe(dnode).pipe(stream)
|
stream.pipe(dnode).pipe(stream)
|
||||||
dnode.on('remote', function(remote){
|
dnode.on('remote', function(remote){
|
||||||
@ -246,7 +255,7 @@ function newUnsignedTransaction(txParams, cb){
|
|||||||
})
|
})
|
||||||
var txId = idStore.addUnconfirmedTransaction(txParams, cb)
|
var txId = idStore.addUnconfirmedTransaction(txParams, cb)
|
||||||
} else {
|
} else {
|
||||||
addUnconfirmedTx(txParams, cb)
|
addUnconfirmedTx(txParams, cb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +267,7 @@ function newUnsignedMessage(msgParams, cb){
|
|||||||
})
|
})
|
||||||
var msgId = idStore.addUnconfirmedMessage(msgParams, cb)
|
var msgId = idStore.addUnconfirmedMessage(msgParams, cb)
|
||||||
} else {
|
} else {
|
||||||
addUnconfirmedMsg(msgParams, cb)
|
addUnconfirmedMsg(msgParams, cb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,13 +299,13 @@ function addUnconfirmedMsg(msgParams, cb){
|
|||||||
function setRpcTarget(rpcTarget){
|
function setRpcTarget(rpcTarget){
|
||||||
configManager.setRpcTarget(rpcTarget)
|
configManager.setRpcTarget(rpcTarget)
|
||||||
chrome.runtime.reload()
|
chrome.runtime.reload()
|
||||||
idStore.getNetwork(3) // 3 retry attempts
|
idStore.getNetwork()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setProviderType(type) {
|
function setProviderType(type) {
|
||||||
configManager.setProviderType(type)
|
configManager.setProviderType(type)
|
||||||
chrome.runtime.reload()
|
chrome.runtime.reload()
|
||||||
idStore.getNetwork(3)
|
idStore.getNetwork()
|
||||||
}
|
}
|
||||||
|
|
||||||
function useEtherscanProvider() {
|
function useEtherscanProvider() {
|
||||||
|
@ -59,6 +59,13 @@ IdentityStore.prototype.createNewVault = function(password, entropy, cb){
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IdentityStore.prototype.recoverSeed = function(cb){
|
||||||
|
configManager.setShowSeedWords(true)
|
||||||
|
if (!this._idmgmt) return cb(new Error('Unauthenticated. Please sign in.'))
|
||||||
|
var seedWords = this._idmgmt.getSeed()
|
||||||
|
cb(null, seedWords)
|
||||||
|
}
|
||||||
|
|
||||||
IdentityStore.prototype.recoverFromSeed = function(password, seed, cb){
|
IdentityStore.prototype.recoverFromSeed = function(password, seed, cb){
|
||||||
this._createIdmgmt(password, seed, null, (err) => {
|
this._createIdmgmt(password, seed, null, (err) => {
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
@ -130,16 +137,22 @@ IdentityStore.prototype.revealAccount = function(cb) {
|
|||||||
cb(null)
|
cb(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype.getNetwork = function(tries) {
|
IdentityStore.prototype.getNetwork = function(err) {
|
||||||
if (tries === 0) {
|
|
||||||
this._currentState.network = 'error'
|
if (err) {
|
||||||
return
|
this._currentState.network = 'loading'
|
||||||
|
this._didUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.web3.version.getNetwork((err, network) => {
|
this.web3.version.getNetwork((err, network) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return this.getNetwork(tries - 1, cb)
|
this._currentState.network = 'loading'
|
||||||
|
return this._didUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('web3.getNetwork returned ' + network)
|
||||||
this._currentState.network = network
|
this._currentState.network = network
|
||||||
|
this._didUpdate()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +163,7 @@ IdentityStore.prototype.setLocked = function(cb){
|
|||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype.submitPassword = function(password, cb){
|
IdentityStore.prototype.submitPassword = function(password, cb){
|
||||||
this._tryPassword(password, (err) => {
|
this.tryPassword(password, (err) => {
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
// load identities before returning...
|
// load identities before returning...
|
||||||
this._loadIdentities()
|
this._loadIdentities()
|
||||||
@ -366,7 +379,7 @@ IdentityStore.prototype._mayBeFauceting = function(i) {
|
|||||||
// keyStore managment - unlocking + deserialization
|
// keyStore managment - unlocking + deserialization
|
||||||
//
|
//
|
||||||
|
|
||||||
IdentityStore.prototype._tryPassword = function(password, cb){
|
IdentityStore.prototype.tryPassword = function(password, cb){
|
||||||
this._createIdmgmt(password, null, null, cb)
|
this._createIdmgmt(password, null, null, cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,24 +8,35 @@ module.exports = {
|
|||||||
createMsgNotification: createMsgNotification,
|
createMsgNotification: createMsgNotification,
|
||||||
}
|
}
|
||||||
|
|
||||||
// notification button press
|
setupListeners()
|
||||||
chrome.notifications.onButtonClicked.addListener(function(notificationId, buttonIndex){
|
|
||||||
var handlers = notificationHandlers[notificationId]
|
|
||||||
if (buttonIndex === 0) {
|
|
||||||
handlers.confirm()
|
|
||||||
} else {
|
|
||||||
handlers.cancel()
|
|
||||||
}
|
|
||||||
chrome.notifications.clear(notificationId)
|
|
||||||
})
|
|
||||||
|
|
||||||
// notification teardown
|
function setupListeners(){
|
||||||
chrome.notifications.onClosed.addListener(function(notificationId){
|
|
||||||
delete notificationHandlers[notificationId]
|
// guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236
|
||||||
})
|
if (!chrome.notifications) return console.error('Chrome notifications API missing...')
|
||||||
|
|
||||||
|
// notification button press
|
||||||
|
chrome.notifications.onButtonClicked.addListener(function(notificationId, buttonIndex){
|
||||||
|
var handlers = notificationHandlers[notificationId]
|
||||||
|
if (buttonIndex === 0) {
|
||||||
|
handlers.confirm()
|
||||||
|
} else {
|
||||||
|
handlers.cancel()
|
||||||
|
}
|
||||||
|
chrome.notifications.clear(notificationId)
|
||||||
|
})
|
||||||
|
|
||||||
|
// notification teardown
|
||||||
|
chrome.notifications.onClosed.addListener(function(notificationId){
|
||||||
|
delete notificationHandlers[notificationId]
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// creation helper
|
// creation helper
|
||||||
function createUnlockRequestNotification(opts){
|
function createUnlockRequestNotification(opts){
|
||||||
|
// guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236
|
||||||
|
if (!chrome.notifications) return console.error('Chrome notifications API missing...')
|
||||||
var message = 'An Ethereum app has requested a signature. Please unlock your account.'
|
var message = 'An Ethereum app has requested a signature. Please unlock your account.'
|
||||||
|
|
||||||
var id = createId()
|
var id = createId()
|
||||||
@ -39,6 +50,8 @@ function createUnlockRequestNotification(opts){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createTxNotification(opts){
|
function createTxNotification(opts){
|
||||||
|
// guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236
|
||||||
|
if (!chrome.notifications) return console.error('Chrome notifications API missing...')
|
||||||
var message = [
|
var message = [
|
||||||
'Submitted by '+opts.txParams.origin,
|
'Submitted by '+opts.txParams.origin,
|
||||||
'to: '+uiUtils.addressSummary(opts.txParams.to),
|
'to: '+uiUtils.addressSummary(opts.txParams.to),
|
||||||
@ -67,6 +80,8 @@ function createTxNotification(opts){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createMsgNotification(opts){
|
function createMsgNotification(opts){
|
||||||
|
// guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236
|
||||||
|
if (!chrome.notifications) return console.error('Chrome notifications API missing...')
|
||||||
var message = [
|
var message = [
|
||||||
'Submitted by '+opts.msgParams.origin,
|
'Submitted by '+opts.msgParams.origin,
|
||||||
'to be signed by: '+uiUtils.addressSummary(opts.msgParams.from),
|
'to be signed by: '+uiUtils.addressSummary(opts.msgParams.from),
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
"through2": "^2.0.1",
|
"through2": "^2.0.1",
|
||||||
"vreme": "^3.0.2",
|
"vreme": "^3.0.2",
|
||||||
"web3": "ethereum/web3.js#0.16.0",
|
"web3": "ethereum/web3.js#0.16.0",
|
||||||
"web3-provider-engine": "^7.7.0",
|
"web3-provider-engine": "^7.8.1",
|
||||||
"web3-stream-provider": "^2.0.1",
|
"web3-stream-provider": "^2.0.1",
|
||||||
"xtend": "^4.0.1"
|
"xtend": "^4.0.1"
|
||||||
},
|
},
|
||||||
|
@ -2,19 +2,9 @@ Chrome notifications allow you to show an SVG image via a data-uri
|
|||||||
|
|
||||||
Taking advantage of this might allow us to show nicely formatted notifications
|
Taking advantage of this might allow us to show nicely formatted notifications
|
||||||
|
|
||||||
Heres some utilities for preparing the data uri:
|
|
||||||
http://dopiaza.org/tools/datauri/index.php
|
|
||||||
provide text
|
|
||||||
no base64
|
|
||||||
specify mime type: image/svg+xml
|
|
||||||
result should look like:
|
|
||||||
data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%0D%0A%20%20width%3D%271000px%27%20height%3D%27500px%27%20viewBox%3D%270%200%20200%20100%27%3E%0D%0A%20%20%3Crect%20x%3D%270%27%20y%3D%270%27%20width%3D%27100%25%27%20height%3D%27100%25%27%20fill%3D%27white%27%20%2F%3E%0D%0A%20%20%3Ctext%20x%3D%270%27%20y%3D%2720%27%20font-family%3D%27monospace%27%20font-size%3D%276%27%20fill%3D%27black%27%3E%0D%0A%20%20%20%20%3Ctspan%20x%3D%270%27%20dy%3D%271.2em%27%3EDomain%3A%20https%3A%2F%2Fboardroom.to%3C%2Ftspan%3E%0D%0A%20%20%20%20%3Ctspan%20x%3D%270%27%20dy%3D%271.2em%27%3EFrom%3A%20%200xabcdef%3C%2Ftspan%3E%0D%0A%20%20%20%20%3Ctspan%20x%3D%270%27%20dy%3D%271.2em%27%3ETo%3A%20%20%20%200xfedcba%3C%2Ftspan%3E%0D%0A%20%20%20%20%3Ctspan%20x%3D%270%27%20dy%3D%271.2em%27%3EValue%3A%201.025%20Ether%3C%2Ftspan%3E%0D%0A%20%20%20%20%3Ctspan%20x%3D%270%27%20dy%3D%271.2em%27%3EGas%3A%200.025%20Ether%3C%2Ftspan%3E%0D%0A%20%20%3C%2Ftext%3E%0D%0A%3C%2Fsvg%3E
|
|
||||||
|
|
||||||
build a template using pure svg:
|
build a template using pure svg:
|
||||||
|
|
||||||
generate uri
|
```svg
|
||||||
'data:image/svg+xml;charset=utf-8,'+encodeURIComponent(svgSrc)
|
|
||||||
|
|
||||||
<svg xmlns='http://www.w3.org/2000/svg'
|
<svg xmlns='http://www.w3.org/2000/svg'
|
||||||
width='1000px' height='500px' viewBox='0 0 200 100'>
|
width='1000px' height='500px' viewBox='0 0 200 100'>
|
||||||
<rect x='0' y='0' width='100%' height='100%' fill='white' />
|
<rect x='0' y='0' width='100%' height='100%' fill='white' />
|
||||||
@ -26,9 +16,14 @@ generate uri
|
|||||||
<tspan x='0' dy='1.2em'>Gas: 0.025 Ether</tspan>
|
<tspan x='0' dy='1.2em'>Gas: 0.025 Ether</tspan>
|
||||||
</text>
|
</text>
|
||||||
</svg>
|
</svg>
|
||||||
|
```
|
||||||
|
|
||||||
|
generate uri
|
||||||
|
`'data:image/svg+xml;charset=utf-8,'+encodeURIComponent(svgSrc)`
|
||||||
|
|
||||||
or svg-embedded html:
|
or svg-embedded html:
|
||||||
|
|
||||||
|
```svg
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="500">
|
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="500">
|
||||||
<rect x='0' y='0' width='100%' height='100%' fill='white' />
|
<rect x='0' y='0' width='100%' height='100%' fill='white' />
|
||||||
<foreignObject class="node" x="46" y="22" width="200" height="300">
|
<foreignObject class="node" x="46" y="22" width="200" height="300">
|
||||||
@ -39,4 +34,5 @@ or svg-embedded html:
|
|||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</foreignObject>
|
</foreignObject>
|
||||||
</svg>
|
</svg>
|
||||||
|
```
|
||||||
|
@ -77,6 +77,13 @@ describe('util', function() {
|
|||||||
assert.ok(!result)
|
assert.ok(!result)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should recognize this sample hashed address', function() {
|
||||||
|
const address = '0x5Fda30Bb72B8Dfe20e48A00dFc108d0915BE9Bb0'
|
||||||
|
const result = util.isValidAddress(address)
|
||||||
|
const hashed = ethUtil.toChecksumAddress(address.toLowerCase())
|
||||||
|
assert.equal(hashed, address, 'example is hashed correctly')
|
||||||
|
assert.ok(result, 'is valid by our check')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('numericBalance', function() {
|
describe('numericBalance', function() {
|
||||||
|
@ -6,6 +6,8 @@ var actions = {
|
|||||||
toggleMenu: toggleMenu,
|
toggleMenu: toggleMenu,
|
||||||
SET_MENU_STATE: 'SET_MENU_STATE',
|
SET_MENU_STATE: 'SET_MENU_STATE',
|
||||||
closeMenu: closeMenu,
|
closeMenu: closeMenu,
|
||||||
|
getNetworkStatus: 'getNetworkStatus',
|
||||||
|
|
||||||
// remote state
|
// remote state
|
||||||
UPDATE_METAMASK_STATE: 'UPDATE_METAMASK_STATE',
|
UPDATE_METAMASK_STATE: 'UPDATE_METAMASK_STATE',
|
||||||
updateMetamaskState: updateMetamaskState,
|
updateMetamaskState: updateMetamaskState,
|
||||||
@ -29,6 +31,10 @@ var actions = {
|
|||||||
createNewVaultInProgress: createNewVaultInProgress,
|
createNewVaultInProgress: createNewVaultInProgress,
|
||||||
showNewVaultSeed: showNewVaultSeed,
|
showNewVaultSeed: showNewVaultSeed,
|
||||||
showInfoPage: showInfoPage,
|
showInfoPage: showInfoPage,
|
||||||
|
// seed recovery actions
|
||||||
|
REVEAL_SEED_CONFIRMATION: 'REVEAL_SEED_CONFIRMATION',
|
||||||
|
revealSeedConfirmation: revealSeedConfirmation,
|
||||||
|
requestRevealSeed: requestRevealSeed,
|
||||||
// unlock screen
|
// unlock screen
|
||||||
UNLOCK_IN_PROGRESS: 'UNLOCK_IN_PROGRESS',
|
UNLOCK_IN_PROGRESS: 'UNLOCK_IN_PROGRESS',
|
||||||
UNLOCK_FAILED: 'UNLOCK_FAILED',
|
UNLOCK_FAILED: 'UNLOCK_FAILED',
|
||||||
@ -131,6 +137,12 @@ function closeMenu() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getNetworkStatus(){
|
||||||
|
return {
|
||||||
|
type: actions.getNetworkStatus,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// async actions
|
// async actions
|
||||||
|
|
||||||
function tryUnlockMetamask(password) {
|
function tryUnlockMetamask(password) {
|
||||||
@ -155,6 +167,26 @@ function createNewVault(password, entropy) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function revealSeedConfirmation() {
|
||||||
|
return {
|
||||||
|
type: this.REVEAL_SEED_CONFIRMATION,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestRevealSeed(password) {
|
||||||
|
return (dispatch) => {
|
||||||
|
dispatch(actions.showLoadingIndication())
|
||||||
|
_accountManager.tryPassword(password, (err, seed) => {
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
if (err) return dispatch(actions.displayWarning(err.message))
|
||||||
|
_accountManager.recoverSeed((err, seed) => {
|
||||||
|
if (err) return dispatch(actions.displayWarning(err.message))
|
||||||
|
dispatch(actions.showNewVaultSeed(seed))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function recoverFromSeed(password, seed) {
|
function recoverFromSeed(password, seed) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
// dispatch(actions.createNewVaultInProgress())
|
// dispatch(actions.createNewVaultInProgress())
|
||||||
@ -402,9 +434,10 @@ function previousTx() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showConfigPage() {
|
function showConfigPage(transitionForward = true) {
|
||||||
return {
|
return {
|
||||||
type: actions.SHOW_CONFIG_PAGE,
|
type: actions.SHOW_CONFIG_PAGE,
|
||||||
|
value: transitionForward,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,12 +21,14 @@ const SendTransactionScreen = require('./send')
|
|||||||
const ConfirmTxScreen = require('./conf-tx')
|
const ConfirmTxScreen = require('./conf-tx')
|
||||||
// other views
|
// other views
|
||||||
const ConfigScreen = require('./config')
|
const ConfigScreen = require('./config')
|
||||||
|
const RevealSeedConfirmation = require('./recover-seed/confirmation')
|
||||||
const InfoScreen = require('./info')
|
const InfoScreen = require('./info')
|
||||||
const LoadingIndicator = require('./loading')
|
const LoadingIndicator = require('./loading')
|
||||||
const txHelper = require('../lib/tx-helper')
|
const txHelper = require('../lib/tx-helper')
|
||||||
const SandwichExpando = require('sandwich-expando')
|
const SandwichExpando = require('sandwich-expando')
|
||||||
const MenuDroppo = require('menu-droppo')
|
const MenuDroppo = require('menu-droppo')
|
||||||
const DropMenuItem = require('./components/drop-menu-item')
|
const DropMenuItem = require('./components/drop-menu-item')
|
||||||
|
const NetworkIndicator = require('./components/network')
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps)(App)
|
module.exports = connect(mapStateToProps)(App)
|
||||||
|
|
||||||
@ -46,14 +48,14 @@ function mapStateToProps(state) {
|
|||||||
unconfTxs: state.metamask.unconfTxs,
|
unconfTxs: state.metamask.unconfTxs,
|
||||||
unconfMsgs: state.metamask.unconfMsgs,
|
unconfMsgs: state.metamask.unconfMsgs,
|
||||||
menuOpen: state.appState.menuOpen,
|
menuOpen: state.appState.menuOpen,
|
||||||
|
network: state.metamask.network,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
App.prototype.render = function() {
|
App.prototype.render = function() {
|
||||||
// const { selectedReddit, posts, isFetching, lastUpdated } = this.props
|
var props = this.props
|
||||||
var state = this.props
|
var view = props.currentView.name
|
||||||
var view = state.currentView.name
|
var transForward = props.transForward
|
||||||
var transForward = state.transForward
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
@ -68,6 +70,7 @@ App.prototype.render = function() {
|
|||||||
|
|
||||||
// app bar
|
// app bar
|
||||||
this.renderAppBar(),
|
this.renderAppBar(),
|
||||||
|
this.renderNetworkDropdown(),
|
||||||
this.renderDropdown(),
|
this.renderDropdown(),
|
||||||
|
|
||||||
// panel content
|
// panel content
|
||||||
@ -91,7 +94,9 @@ App.prototype.render = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
App.prototype.renderAppBar = function(){
|
App.prototype.renderAppBar = function(){
|
||||||
var state = this.props
|
const props = this.props
|
||||||
|
const state = this.state || {}
|
||||||
|
const isNetworkMenuOpen = state.isNetworkMenuOpen || false
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
@ -100,30 +105,31 @@ App.prototype.renderAppBar = function(){
|
|||||||
h('.app-header.flex-row.flex-space-between', {
|
h('.app-header.flex-row.flex-space-between', {
|
||||||
style: {
|
style: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
visibility: state.isUnlocked ? 'visible' : 'none',
|
visibility: props.isUnlocked ? 'visible' : 'none',
|
||||||
background: state.isUnlocked ? 'white' : 'none',
|
background: props.isUnlocked ? 'white' : 'none',
|
||||||
height: '36px',
|
height: '36px',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
},
|
},
|
||||||
}, state.isUnlocked && [
|
}, props.isUnlocked && [
|
||||||
|
|
||||||
// mini logo
|
h(NetworkIndicator, {
|
||||||
h('img', {
|
network: this.props.network,
|
||||||
height: 24,
|
onClick:(event) => {
|
||||||
width: 24,
|
event.preventDefault()
|
||||||
src: '/images/icon-128.png',
|
event.stopPropagation()
|
||||||
|
this.setState({ isNetworkMenuOpen: !isNetworkMenuOpen })
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// metamask name
|
// metamask name
|
||||||
h('h1', 'MetaMask'),
|
h('h1', 'MetaMask'),
|
||||||
|
|
||||||
// hamburger
|
// hamburger
|
||||||
h(SandwichExpando, {
|
h(SandwichExpando, {
|
||||||
width: 16,
|
width: 16,
|
||||||
barHeight: 2,
|
barHeight: 2,
|
||||||
padding: 0,
|
padding: 0,
|
||||||
isOpen: state.menuOpen,
|
isOpen: props.menuOpen,
|
||||||
color: 'rgb(247,146,30)',
|
color: 'rgb(247,146,30)',
|
||||||
onClick: (event) => {
|
onClick: (event) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
@ -136,6 +142,56 @@ App.prototype.renderAppBar = function(){
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
App.prototype.renderNetworkDropdown = function() {
|
||||||
|
const props = this.props
|
||||||
|
const state = this.state || {}
|
||||||
|
const isOpen = state.isNetworkMenuOpen
|
||||||
|
|
||||||
|
const checked = h('i.fa.fa-check.fa-lg', { ariaHidden: true })
|
||||||
|
|
||||||
|
return h(MenuDroppo, {
|
||||||
|
isOpen,
|
||||||
|
onClickOutside:(event) => {
|
||||||
|
this.setState({ isNetworkMenuOpen: !isOpen })
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
position: 'fixed',
|
||||||
|
left: 0,
|
||||||
|
zIndex: 0,
|
||||||
|
},
|
||||||
|
innerStyle: {
|
||||||
|
background: 'white',
|
||||||
|
boxShadow: '1px 1px 2px rgba(0,0,0,0.1)',
|
||||||
|
},
|
||||||
|
}, [ // DROP MENU ITEMS
|
||||||
|
h('style', `
|
||||||
|
.drop-menu-item:hover { background:rgb(235, 235, 235); }
|
||||||
|
.drop-menu-item i { margin: 11px; }
|
||||||
|
`),
|
||||||
|
|
||||||
|
h(DropMenuItem, {
|
||||||
|
label: 'Main Ethereum Network',
|
||||||
|
closeMenu:() => this.setState({ isNetworkMenuOpen: false }),
|
||||||
|
action:() => props.dispatch(actions.setProviderType('mainnet')),
|
||||||
|
icon: h('.menu-icon.ether-icon'),
|
||||||
|
}),
|
||||||
|
|
||||||
|
h(DropMenuItem, {
|
||||||
|
label: 'Morden Test Network',
|
||||||
|
closeMenu:() => this.setState({ isNetworkMenuOpen: false }),
|
||||||
|
action:() => props.dispatch(actions.setProviderType('testnet')),
|
||||||
|
icon: h('.menu-icon.morden-icon'),
|
||||||
|
}),
|
||||||
|
|
||||||
|
h(DropMenuItem, {
|
||||||
|
label: 'Localhost 8545',
|
||||||
|
closeMenu:() => this.setState({ isNetworkMenuOpen: false }),
|
||||||
|
action:() => props.dispatch(actions.setRpcTarget('http://localhost:8545')),
|
||||||
|
icon: h('i.fa.fa-question-circle.fa-lg', { ariaHidden: true }),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
App.prototype.renderDropdown = function() {
|
App.prototype.renderDropdown = function() {
|
||||||
const props = this.props
|
const props = this.props
|
||||||
return h(MenuDroppo, {
|
return h(MenuDroppo, {
|
||||||
@ -232,6 +288,9 @@ App.prototype.renderPrimary = function(){
|
|||||||
case 'config':
|
case 'config':
|
||||||
return h(ConfigScreen, {key: 'config'})
|
return h(ConfigScreen, {key: 'config'})
|
||||||
|
|
||||||
|
case 'reveal-seed-conf':
|
||||||
|
return h(RevealSeedConfirmation, {key: 'reveal-seed-conf'})
|
||||||
|
|
||||||
case 'info':
|
case 'info':
|
||||||
return h(InfoScreen, {key: 'info'})
|
return h(InfoScreen, {key: 'info'})
|
||||||
|
|
||||||
|
65
ui/app/components/network.js
Normal file
65
ui/app/components/network.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
const Component = require('react').Component
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const inherits = require('util').inherits
|
||||||
|
|
||||||
|
module.exports = Network
|
||||||
|
|
||||||
|
inherits(Network, Component)
|
||||||
|
|
||||||
|
function Network() {
|
||||||
|
Component.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
Network.prototype.render = function() {
|
||||||
|
const state = this.props
|
||||||
|
const networkNumber = state.network
|
||||||
|
let iconName, hoverText
|
||||||
|
const imagePath = "/images/"
|
||||||
|
|
||||||
|
if (networkNumber == 'loading') {
|
||||||
|
return h('img', {
|
||||||
|
title: 'Attempting to connect to blockchain.',
|
||||||
|
style: {
|
||||||
|
width: '27px',
|
||||||
|
marginRight: '-27px'
|
||||||
|
},
|
||||||
|
src: 'images/loading.svg',
|
||||||
|
})
|
||||||
|
} else if (parseInt(networkNumber) == 1) {
|
||||||
|
hoverText = 'Main Ethereum Network'
|
||||||
|
iconName = 'ethereum-network'
|
||||||
|
}else if (parseInt(networkNumber) == 2) {
|
||||||
|
hoverText = "Morden Test Network"
|
||||||
|
iconName = 'morden-test-network'
|
||||||
|
}else {
|
||||||
|
hoverText = "Unknown Private Network"
|
||||||
|
iconName = 'unknown-private-network'
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
h('#network_component.flex-center.pointer', {
|
||||||
|
style: {
|
||||||
|
marginRight: '-27px',
|
||||||
|
marginLeft: '-3px',
|
||||||
|
},
|
||||||
|
title: hoverText,
|
||||||
|
onClick:(event) => this.props.onClick(event),
|
||||||
|
},[
|
||||||
|
function() {
|
||||||
|
switch (iconName) {
|
||||||
|
case 'ethereum-network':
|
||||||
|
return h('.menu-icon.ether-icon')
|
||||||
|
case 'morden-test-network':
|
||||||
|
return h('.menu-icon.morden-icon')
|
||||||
|
default:
|
||||||
|
return h('i.fa.fa-question-circle.fa-lg', {
|
||||||
|
ariaHidden: true,
|
||||||
|
style: {
|
||||||
|
margin: '10px',
|
||||||
|
color: 'rgb(125, 128, 130)',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
@ -78,7 +78,7 @@ ConfigScreen.prototype.render = function() {
|
|||||||
]),
|
]),
|
||||||
|
|
||||||
h('div', [
|
h('div', [
|
||||||
h('button', {
|
h('button.spaced', {
|
||||||
style: {
|
style: {
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
},
|
},
|
||||||
@ -86,11 +86,11 @@ ConfigScreen.prototype.render = function() {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
state.dispatch(actions.setProviderType('mainnet'))
|
state.dispatch(actions.setProviderType('mainnet'))
|
||||||
}
|
}
|
||||||
}, 'Use Main Network')
|
}, 'Use Main Network'),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
h('div', [
|
h('div', [
|
||||||
h('button', {
|
h('button.spaced', {
|
||||||
style: {
|
style: {
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
},
|
},
|
||||||
@ -98,11 +98,11 @@ ConfigScreen.prototype.render = function() {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
state.dispatch(actions.setProviderType('testnet'))
|
state.dispatch(actions.setProviderType('testnet'))
|
||||||
}
|
}
|
||||||
}, 'Use Morden Test Network')
|
}, 'Use Morden Test Network'),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
h('div', [
|
h('div', [
|
||||||
h('button', {
|
h('button.spaced', {
|
||||||
style: {
|
style: {
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
},
|
},
|
||||||
@ -110,7 +110,25 @@ ConfigScreen.prototype.render = function() {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
state.dispatch(actions.setRpcTarget('http://localhost:8545/'))
|
state.dispatch(actions.setRpcTarget('http://localhost:8545/'))
|
||||||
}
|
}
|
||||||
}, 'Use http://localhost:8545')
|
}, 'Use http://localhost:8545'),
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('hr.horizontal-line'),
|
||||||
|
|
||||||
|
h('div', {
|
||||||
|
style: {
|
||||||
|
marginTop: '20px',
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
h('button', {
|
||||||
|
style: {
|
||||||
|
alignSelf: 'center',
|
||||||
|
},
|
||||||
|
onClick(event) {
|
||||||
|
event.preventDefault()
|
||||||
|
state.dispatch(actions.revealSeedConfirmation())
|
||||||
|
}
|
||||||
|
}, 'Reveal Seed Words')
|
||||||
]),
|
]),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
|
@ -45,6 +45,10 @@ button {
|
|||||||
transition: transform 50ms ease-in;
|
transition: transform 50ms ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button.spaced {
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
button:hover {
|
button:hover {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
|
@ -199,3 +199,22 @@ hr.horizontal-line {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu-icon {
|
||||||
|
display: inline-block;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
margin: 13px;
|
||||||
|
}
|
||||||
|
.ether-icon {
|
||||||
|
background: rgb(0, 163, 68);
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
.morden-icon {
|
||||||
|
background: #2465E1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drop-menu-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
@ -14,7 +14,7 @@ function CreateVaultCompleteScreen() {
|
|||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
seed: state.appState.currentView.context,
|
seed: state.appState.currentView.seedWords,
|
||||||
cachedSeed: state.metamask.seedWords,
|
cachedSeed: state.metamask.seedWords,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
149
ui/app/recover-seed/confirmation.js
Normal file
149
ui/app/recover-seed/confirmation.js
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
const inherits = require('util').inherits
|
||||||
|
|
||||||
|
const Component = require('react').Component
|
||||||
|
const connect = require('react-redux').connect
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const actions = require('../actions')
|
||||||
|
|
||||||
|
module.exports = connect(mapStateToProps)(RevealSeedConfirmatoin)
|
||||||
|
|
||||||
|
|
||||||
|
inherits(RevealSeedConfirmatoin, Component)
|
||||||
|
function RevealSeedConfirmatoin() {
|
||||||
|
Component.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
warning: state.appState.warning,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RevealSeedConfirmatoin.prototype.confirmationPhrase = 'I understand'
|
||||||
|
|
||||||
|
RevealSeedConfirmatoin.prototype.render = function() {
|
||||||
|
const props = this.props
|
||||||
|
const state = this.state
|
||||||
|
|
||||||
|
return (
|
||||||
|
|
||||||
|
h('.initialize-screen.flex-column.flex-center.flex-grow', [
|
||||||
|
|
||||||
|
h('h3.flex-center.text-transform-uppercase', {
|
||||||
|
style: {
|
||||||
|
background: '#EBEBEB',
|
||||||
|
color: '#AEAEAE',
|
||||||
|
marginBottom: 24,
|
||||||
|
width: '100%',
|
||||||
|
fontSize: '20px',
|
||||||
|
padding: 6,
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
'Reveal Seed Words',
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('.div', {
|
||||||
|
style: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
padding: '20px',
|
||||||
|
justifyContent: 'center',
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
|
||||||
|
h('h4', 'Do not recover your seed words in a public place! These words can be used to steal all your accounts.'),
|
||||||
|
|
||||||
|
// confirmation
|
||||||
|
h('input.large-input.letter-spacey', {
|
||||||
|
type: 'password',
|
||||||
|
id: 'password-box',
|
||||||
|
placeholder: 'Enter your password to confirm',
|
||||||
|
onKeyPress: this.checkConfirmation.bind(this),
|
||||||
|
style: {
|
||||||
|
width: 260,
|
||||||
|
marginTop: '12px',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
h(`h4${state && state.confirmationWrong ? '.error' : ''}`, {
|
||||||
|
style: {
|
||||||
|
marginTop: '12px',
|
||||||
|
}
|
||||||
|
}, `Enter the phrase "I understand" to proceed.`),
|
||||||
|
|
||||||
|
// confirm confirmation
|
||||||
|
h('input.large-input.letter-spacey', {
|
||||||
|
type: 'text',
|
||||||
|
id: 'confirm-box',
|
||||||
|
placeholder: this.confirmationPhrase,
|
||||||
|
onKeyPress: this.checkConfirmation.bind(this),
|
||||||
|
style: {
|
||||||
|
width: 260,
|
||||||
|
marginTop: 16,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
h('.flex-row.flex-space-between', {
|
||||||
|
style: {
|
||||||
|
marginTop: 30,
|
||||||
|
width: '50%',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
// cancel
|
||||||
|
h('button.primary', {
|
||||||
|
onClick: this.goHome.bind(this),
|
||||||
|
}, 'CANCEL'),
|
||||||
|
|
||||||
|
// submit
|
||||||
|
h('button.primary', {
|
||||||
|
onClick: this.revealSeedWords.bind(this),
|
||||||
|
}, 'OK'),
|
||||||
|
|
||||||
|
]),
|
||||||
|
|
||||||
|
(props.warning) && (
|
||||||
|
h('span.error', {
|
||||||
|
style: {
|
||||||
|
margin: '20px',
|
||||||
|
}
|
||||||
|
}, props.warning.split('-'))
|
||||||
|
),
|
||||||
|
|
||||||
|
props.inProgress && (
|
||||||
|
h('span.in-progress-notification', 'Generating Seed...')
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
RevealSeedConfirmatoin.prototype.componentDidMount = function(){
|
||||||
|
document.getElementById('password-box').focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
RevealSeedConfirmatoin.prototype.goHome = function() {
|
||||||
|
this.props.dispatch(actions.showConfigPage(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// create vault
|
||||||
|
|
||||||
|
RevealSeedConfirmatoin.prototype.checkConfirmation = function(event) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.preventDefault()
|
||||||
|
this.revealSeedWords()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RevealSeedConfirmatoin.prototype.revealSeedWords = function(){
|
||||||
|
this.setState({ confirmationWrong: false })
|
||||||
|
|
||||||
|
const confirmBox = document.getElementById('confirm-box')
|
||||||
|
const confirmation = confirmBox.value
|
||||||
|
if (confirmation !== this.confirmationPhrase) {
|
||||||
|
confirmBox.value = ''
|
||||||
|
return this.setState({ confirmationWrong: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
var password = document.getElementById('password-box').value
|
||||||
|
this.props.dispatch(actions.requestRevealSeed(password))
|
||||||
|
}
|
@ -25,10 +25,11 @@ function reduceApp(state, action) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// confirm seed words
|
// confirm seed words
|
||||||
|
var seedWords = state.metamask.seedWords
|
||||||
var seedConfView = {
|
var seedConfView = {
|
||||||
name: 'createVaultComplete',
|
name: 'createVaultComplete',
|
||||||
|
seedWords,
|
||||||
}
|
}
|
||||||
var seedWords = state.metamask.seedWords
|
|
||||||
|
|
||||||
var appState = extend({
|
var appState = extend({
|
||||||
menuOpen: false,
|
menuOpen: false,
|
||||||
@ -85,7 +86,7 @@ function reduceApp(state, action) {
|
|||||||
name: 'config',
|
name: 'config',
|
||||||
context: appState.currentView.context,
|
context: appState.currentView.context,
|
||||||
},
|
},
|
||||||
transForward: true,
|
transForward: action.value,
|
||||||
})
|
})
|
||||||
|
|
||||||
case actions.SHOW_INFO_PAGE:
|
case actions.SHOW_INFO_PAGE:
|
||||||
@ -111,7 +112,7 @@ function reduceApp(state, action) {
|
|||||||
return extend(appState, {
|
return extend(appState, {
|
||||||
currentView: {
|
currentView: {
|
||||||
name: 'createVaultComplete',
|
name: 'createVaultComplete',
|
||||||
context: action.value,
|
seedWords: action.value,
|
||||||
},
|
},
|
||||||
transForward: true,
|
transForward: true,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@ -144,6 +145,18 @@ function reduceApp(state, action) {
|
|||||||
warning: null,
|
warning: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// reveal seed words
|
||||||
|
|
||||||
|
case actions.REVEAL_SEED_CONFIRMATION:
|
||||||
|
return extend(appState, {
|
||||||
|
currentView: {
|
||||||
|
name: 'reveal-seed-conf',
|
||||||
|
},
|
||||||
|
transForward: true,
|
||||||
|
warning: null,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
// accounts
|
// accounts
|
||||||
|
|
||||||
case actions.SET_SELECTED_ACCOUNT:
|
case actions.SET_SELECTED_ACCOUNT:
|
||||||
@ -198,6 +211,7 @@ function reduceApp(state, action) {
|
|||||||
return extend(appState, {
|
return extend(appState, {
|
||||||
currentView: {
|
currentView: {
|
||||||
name: seedWords ? 'createVaultComplete' : 'accounts',
|
name: seedWords ? 'createVaultComplete' : 'accounts',
|
||||||
|
seedWords,
|
||||||
},
|
},
|
||||||
transForward: true,
|
transForward: true,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
|
@ -52,7 +52,7 @@ function addressSummary(address) {
|
|||||||
|
|
||||||
function isValidAddress(address) {
|
function isValidAddress(address) {
|
||||||
var prefixed = ethUtil.addHexPrefix(address)
|
var prefixed = ethUtil.addHexPrefix(address)
|
||||||
return isAllOneCase(prefixed) && ethUtil.isValidAddress(prefixed) || ethUtil.isValidChecksumAddress(prefixed)
|
return (isAllOneCase(prefixed) && ethUtil.isValidAddress(prefixed)) || ethUtil.isValidChecksumAddress(prefixed)
|
||||||
}
|
}
|
||||||
|
|
||||||
function isAllOneCase(address) {
|
function isAllOneCase(address) {
|
||||||
|
Loading…
Reference in New Issue
Block a user