Fix conflict

feature/default_network_editable
Frankie 9 years ago
commit cf663f1104
  1. 151
      .eslintrc
  2. 1
      .nvmrc
  3. 4
      README.md
  4. 133
      app/scripts/background.js
  5. 2071
      app/scripts/chromereload.js
  6. 10
      app/scripts/contentscript.js
  7. 11
      app/scripts/inpage.js
  8. 4
      app/scripts/lib/auto-faucet.js
  9. 15
      app/scripts/lib/auto-reload.js
  10. 115
      app/scripts/lib/config-manager.js
  11. 10
      app/scripts/lib/ensnare.js
  12. 41
      app/scripts/lib/id-management.js
  13. 99
      app/scripts/lib/idStore.js
  14. 36
      app/scripts/lib/inpage-provider.js
  15. 19
      app/scripts/lib/local-message-stream.js
  16. 20
      app/scripts/lib/message-manager.js
  17. 41
      app/scripts/lib/notifications.js
  18. 13
      app/scripts/lib/obj-multiplex.js
  19. 15
      app/scripts/lib/port-stream.js
  20. 34
      app/scripts/lib/remote-store.js
  21. 17
      app/scripts/lib/stream-utils.js
  22. 4
      app/scripts/migrations/002.js
  23. 4
      app/scripts/migrations/003.js
  24. 16
      app/scripts/migrations/004.js
  25. 19
      app/scripts/popup.js
  26. 3
      circle.yml
  27. 22
      gulpfile.js
  28. 3
      package.json
  29. 9
      test/unit/linting_test.js
  30. 26
      ui/app/account-detail.js
  31. 14
      ui/app/accounts/account-panel.js
  32. 101
      ui/app/accounts/index.js
  33. 139
      ui/app/actions.js
  34. 61
      ui/app/app.js
  35. 21
      ui/app/components/account-export.js
  36. 20
      ui/app/components/account-panel.js
  37. 8
      ui/app/components/drop-menu-item.js
  38. 21
      ui/app/components/editable-label.js
  39. 5
      ui/app/components/eth-balance.js
  40. 6
      ui/app/components/identicon.js
  41. 15
      ui/app/components/mascot.js
  42. 57
      ui/app/components/network.js
  43. 9
      ui/app/components/panel.js
  44. 12
      ui/app/components/pending-msg.js
  45. 10
      ui/app/components/pending-tx.js
  46. 9
      ui/app/components/template.js
  47. 13
      ui/app/components/transaction-list-item-icon.js
  48. 30
      ui/app/components/transaction-list-item.js
  49. 25
      ui/app/components/transaction-list.js
  50. 23
      ui/app/conf-tx.js
  51. 49
      ui/app/config.js
  52. 11
      ui/app/first-time/create-vault-complete.js
  53. 17
      ui/app/first-time/create-vault.js
  54. 13
      ui/app/first-time/disclaimer.js
  55. 19
      ui/app/first-time/init-menu.js
  56. 16
      ui/app/first-time/restore-vault.js
  57. 142
      ui/app/info.js
  58. 9
      ui/app/loading.js
  59. 23
      ui/app/recover-seed/confirmation.js
  60. 7
      ui/app/reducers.js
  61. 612
      ui/app/reducers/app.js
  62. 5
      ui/app/reducers/identities.js
  63. 185
      ui/app/reducers/metamask.js
  64. 10
      ui/app/root.js
  65. 27
      ui/app/send.js
  66. 25
      ui/app/settings.js
  67. 3
      ui/app/store.js
  68. 11
      ui/app/template.js
  69. 21
      ui/app/unlock.js
  70. 99
      ui/app/util.js
  71. 19
      ui/css.js
  72. 32
      ui/example.js
  73. 19
      ui/index.js
  74. 2
      ui/lib/explorer-link.js
  75. 23
      ui/lib/icon-factory.js
  76. 2
      ui/lib/tx-helper.js

@ -0,0 +1,151 @@
{
"parserOptions": {
"ecmaVersion": 6,
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"impliedStrict": true,
"modules": true,
"blockBindings": true,
"arrowFunctions": true,
"objectLiteralShorthandMethods": true,
"objectLiteralShorthandProperties": true,
"templateStrings": true
},
},
"env": {
"es6": true,
"node": true,
"browser": true
},
"plugins": [
],
"globals": {
"chrome": true,
"document": false,
"navigator": false,
"web3": true,
"window": false
},
"rules": {
"accessor-pairs": 2,
"arrow-spacing": [2, { "before": true, "after": true }],
"block-spacing": [2, "always"],
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
"camelcase": [2, { "properties": "never" }],
"comma-dangle": [2, "always-multiline"],
"comma-spacing": [2, { "before": false, "after": true }],
"comma-style": [2, "last"],
"constructor-super": 2,
"curly": [2, "multi-line"],
"dot-location": [2, "property"],
"eol-last": 2,
"eqeqeq": [2, "allow-null"],
"generator-star-spacing": [2, { "before": true, "after": true }],
"handle-callback-err": [2, "^(err|error)$" ],
"indent": [2, 2, { "SwitchCase": 1 }],
"jsx-quotes": [2, "prefer-single"],
"key-spacing": [2, { "beforeColon": false, "afterColon": true }],
"keyword-spacing": [2, { "before": true, "after": true }],
"new-cap": [2, { "newIsCap": true, "capIsNew": false }],
"new-parens": 2,
"no-array-constructor": 2,
"no-caller": 2,
"no-class-assign": 2,
"no-cond-assign": 2,
"no-const-assign": 2,
"no-control-regex": 2,
"no-debugger": 2,
"no-delete-var": 2,
"no-dupe-args": 2,
"no-dupe-class-members": 2,
"no-dupe-keys": 2,
"no-duplicate-case": 2,
"no-duplicate-imports": 2,
"no-empty-character-class": 2,
"no-empty-pattern": 2,
"no-eval": 2,
"no-ex-assign": 2,
"no-extend-native": 2,
"no-extra-bind": 2,
"no-extra-boolean-cast": 2,
"no-extra-parens": [2, "functions"],
"no-fallthrough": 2,
"no-floating-decimal": 2,
"no-func-assign": 2,
"no-implied-eval": 2,
"no-inner-declarations": [2, "functions"],
"no-invalid-regexp": 2,
"no-irregular-whitespace": 2,
"no-iterator": 2,
"no-label-var": 2,
"no-labels": [2, { "allowLoop": false, "allowSwitch": false }],
"no-lone-blocks": 2,
"no-mixed-spaces-and-tabs": 2,
"no-multi-spaces": 2,
"no-multi-str": 2,
"no-multiple-empty-lines": [2, { "max": 1 }],
"no-native-reassign": 2,
"no-negated-in-lhs": 2,
"no-new": 2,
"no-new-func": 2,
"no-new-object": 2,
"no-new-require": 2,
"no-new-symbol": 2,
"no-new-wrappers": 2,
"no-obj-calls": 2,
"no-octal": 2,
"no-octal-escape": 2,
"no-path-concat": 2,
"no-proto": 2,
"no-redeclare": 2,
"no-regex-spaces": 2,
"no-return-assign": [2, "except-parens"],
"no-self-assign": 2,
"no-self-compare": 2,
"no-sequences": 2,
"no-shadow-restricted-names": 2,
"no-spaced-func": 2,
"no-sparse-arrays": 2,
"no-this-before-super": 2,
"no-throw-literal": 2,
"no-trailing-spaces": 2,
"no-undef": 2,
"no-undef-init": 2,
"no-unexpected-multiline": 2,
"no-unmodified-loop-condition": 2,
"no-unneeded-ternary": [2, { "defaultAssignment": false }],
"no-unreachable": 2,
"no-unsafe-finally": 2,
"no-unused-vars": [2, { "vars": "all", "args": "none" }],
"no-useless-call": 2,
"no-useless-computed-key": 2,
"no-useless-constructor": 2,
"no-useless-escape": 2,
"no-whitespace-before-property": 2,
"no-with": 2,
"one-var": [2, { "initialized": "never" }],
"operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }],
"padded-blocks": [2, "never"],
"quotes": [2, "single", "avoid-escape"],
"semi": [2, "never"],
"semi-spacing": [2, { "before": false, "after": true }],
"space-before-blocks": [1, "always"],
"space-before-function-paren": [1, "always"],
"space-in-parens": [2, "never"],
"space-infix-ops": 2,
"space-unary-ops": [2, { "words": true, "nonwords": false }],
"spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] }],
"strict": 0,
"template-curly-spacing": [2, "never"],
"use-isnan": 2,
"valid-typeof": 2,
"wrap-iife": [2, "any"],
"yield-star-spacing": [2, "both"],
"yoda": [2, "never"],
"prefer-const": 1
}
}

@ -0,0 +1 @@
6.0

@ -1,4 +1,4 @@
# Metamask Plugin [![Build Status](https://travis-ci.com/MetaMask/metamask-plugin.svg?token=3txzDGFpqQqvRCdgwTJp&branch=master)](https://travis-ci.com/MetaMask/metamask-plugin) # Metamask Plugin [![Build Status](https://circleci.com/gh/MetaMask/metamask-plugin.svg?style=shield&circle-token=a1ddcf3cd38e29267f254c9c59d556d513e3a1fd)](https://circleci.com/gh/MetaMask/metamask-plugin)
## Architecture ## Architecture
@ -54,6 +54,8 @@ Then just run `npm test`.
You can also test with a continuously watching process, via `npm run watch`. You can also test with a continuously watching process, via `npm run watch`.
You can run the linter by itself with `gulp lint`.
### Deploying the UI ### Deploying the UI
You must be authorized already on the Metamask plugin. You must be authorized already on the Metamask plugin.

@ -1,11 +1,9 @@
const urlUtil = require('url') const urlUtil = require('url')
const Dnode = require('dnode') const Dnode = require('dnode')
const eos = require('end-of-stream') const eos = require('end-of-stream')
const combineStreams = require('pumpify')
const extend = require('xtend') const extend = require('xtend')
const EthStore = require('eth-store') const EthStore = require('eth-store')
const MetaMaskProvider = require('web3-provider-engine/zero.js') const MetaMaskProvider = require('web3-provider-engine/zero.js')
const ObjectMultiplex = require('./lib/obj-multiplex')
const PortStream = require('./lib/port-stream.js') const PortStream = require('./lib/port-stream.js')
const IdentityStore = require('./lib/idStore') const IdentityStore = require('./lib/idStore')
const createUnlockRequestNotification = require('./lib/notifications.js').createUnlockRequestNotification const createUnlockRequestNotification = require('./lib/notifications.js').createUnlockRequestNotification
@ -22,7 +20,7 @@ const Web3 = require('web3')
// //
chrome.runtime.onConnect.addListener(connectRemote) chrome.runtime.onConnect.addListener(connectRemote)
function connectRemote(remotePort){ function connectRemote (remotePort) {
var isMetaMaskInternalProcess = (remotePort.name === 'popup') var isMetaMaskInternalProcess = (remotePort.name === 'popup')
var portStream = new PortStream(remotePort) var portStream = new PortStream(remotePort)
if (isMetaMaskInternalProcess) { if (isMetaMaskInternalProcess) {
@ -35,7 +33,7 @@ function connectRemote(remotePort){
} }
} }
function setupUntrustedCommunication(connectionStream, originDomain){ function setupUntrustedCommunication (connectionStream, originDomain) {
// setup multiplexing // setup multiplexing
var mx = setupMultiplex(connectionStream) var mx = setupMultiplex(connectionStream)
// connect features // connect features
@ -43,7 +41,7 @@ function setupUntrustedCommunication(connectionStream, originDomain){
setupPublicConfig(mx.createStream('publicConfig')) setupPublicConfig(mx.createStream('publicConfig'))
} }
function setupTrustedCommunication(connectionStream, originDomain){ function setupTrustedCommunication (connectionStream, originDomain) {
// setup multiplexing // setup multiplexing
var mx = setupMultiplex(connectionStream) var mx = setupMultiplex(connectionStream)
// connect features // connect features
@ -55,13 +53,12 @@ function setupTrustedCommunication(connectionStream, originDomain){
// state and network // state and network
// //
var providerConfig = configManager.getProvider()
var idStore = new IdentityStore() var idStore = new IdentityStore()
var providerOpts = { var providerOpts = {
rpcUrl: configManager.getCurrentRpcAddress(), rpcUrl: configManager.getCurrentRpcAddress(),
// account mgmt // account mgmt
getAccounts: function(cb){ getAccounts: function (cb) {
var selectedAddress = idStore.getSelectedAddress() var selectedAddress = idStore.getSelectedAddress()
var result = selectedAddress ? [selectedAddress] : [] var result = selectedAddress ? [selectedAddress] : []
cb(null, result) cb(null, result)
@ -79,8 +76,8 @@ idStore.web3 = web3
idStore.getNetwork() 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: // Check network when restoring connectivity:
if (idStore._currentState.network === 'loading') { if (idStore._currentState.network === 'loading') {
@ -93,7 +90,7 @@ provider.on('error', idStore.getNetwork.bind(idStore))
var ethStore = new EthStore(provider) var ethStore = new EthStore(provider)
idStore.setStore(ethStore) idStore.setStore(ethStore)
function getState(){ function getState () {
var state = extend( var state = extend(
ethStore.getState(), ethStore.getState(),
idStore.getState(), idStore.getState(),
@ -115,56 +112,61 @@ var initPublicState = extend(
var publicConfigStore = new HostStore(initPublicState) var publicConfigStore = new HostStore(initPublicState)
// subscribe to changes // subscribe to changes
configManager.subscribe(function(state){ configManager.subscribe(function (state) {
storeSetFromObj(publicConfigStore, configToPublic(state)) storeSetFromObj(publicConfigStore, configToPublic(state))
}) })
idStore.on('update', function(state){ idStore.on('update', function (state) {
storeSetFromObj(publicConfigStore, idStoreToPublic(state)) storeSetFromObj(publicConfigStore, idStoreToPublic(state))
}) })
// idStore substate // idStore substate
function idStoreToPublic(state){ function idStoreToPublic (state) {
return { return {
selectedAddress: state.selectedAddress, selectedAddress: state.selectedAddress,
} }
} }
// config substate // config substate
function configToPublic(state){ function configToPublic (state) {
return { return {
provider: state.provider, provider: state.provider,
} }
} }
// dump obj into store // dump obj into store
function storeSetFromObj(store, obj){ function storeSetFromObj (store, obj) {
Object.keys(obj).forEach(function(key){ Object.keys(obj).forEach(function (key) {
store.set(key, obj[key]) store.set(key, obj[key])
}) })
} }
// //
// remote features // remote features
// //
function setupPublicConfig(stream){ function setupPublicConfig (stream) {
var storeStream = publicConfigStore.createStream() var storeStream = publicConfigStore.createStream()
stream.pipe(storeStream).pipe(stream) stream.pipe(storeStream).pipe(stream)
} }
function setupProviderConnection(stream, originDomain){ function setupProviderConnection (stream, originDomain) {
// decorate all payloads with origin domain
stream.on('data', function onRpcRequest(payload){ stream.on('data', function onRpcRequest (request) {
// Append origin to rpc payload var payloads = Array.isArray(request) ? request : [request]
payload.origin = originDomain payloads.forEach(function (payload) {
// Append origin to signature request // Append origin to rpc payload
if (payload.method === 'eth_sendTransaction') { payload.origin = originDomain
payload.params[0].origin = originDomain // Append origin to signature request
} else if (payload.method === 'eth_sign') { if (payload.method === 'eth_sendTransaction') {
payload.params.push({ origin: originDomain }) payload.params[0].origin = originDomain
} } else if (payload.method === 'eth_sign') {
payload.params.push({ origin: originDomain })
}
})
// handle rpc request // handle rpc request
provider.sendAsync(payload, function onPayloadHandled(err, response){ provider.sendAsync(request, function onPayloadHandled (err, response) {
logger(null, payload, response) if (err) {
return logger(err)
}
logger(null, request, response)
try { try {
stream.write(response) stream.write(response)
} catch (err) { } catch (err) {
@ -173,54 +175,52 @@ function setupProviderConnection(stream, originDomain){
}) })
}) })
function logger(err, request, response){ function logger (err, request, response) {
if (err) return console.error(err.stack) if (err) return console.error(err.stack)
if (!request.isMetamaskInternal) { if (!request.isMetamaskInternal) {
console.log(`RPC (${originDomain}):`, request, '->', response) console.log(`RPC (${originDomain}):`, request, '->', response)
if (response.error) console.error('Error in RPC response:\n'+response.error.message) if (response.error) console.error('Error in RPC response:\n' + response.error.message)
} }
} }
} }
function setupControllerConnection(stream){ function setupControllerConnection (stream) {
var dnode = Dnode({ var dnode = Dnode({
getState: function(cb){ cb(null, getState()) }, getState: function (cb) { cb(null, getState()) },
setRpcTarget: setRpcTarget, setRpcTarget: setRpcTarget,
setProviderType: setProviderType, setProviderType: setProviderType,
useEtherscanProvider: useEtherscanProvider, useEtherscanProvider: useEtherscanProvider,
agreeToDisclaimer: agreeToDisclaimer, agreeToDisclaimer: agreeToDisclaimer,
// forward directly to idStore // forward directly to idStore
createNewVault: idStore.createNewVault.bind(idStore), createNewVault: idStore.createNewVault.bind(idStore),
recoverFromSeed: idStore.recoverFromSeed.bind(idStore), recoverFromSeed: idStore.recoverFromSeed.bind(idStore),
submitPassword: idStore.submitPassword.bind(idStore), submitPassword: idStore.submitPassword.bind(idStore),
setSelectedAddress: idStore.setSelectedAddress.bind(idStore), setSelectedAddress: idStore.setSelectedAddress.bind(idStore),
approveTransaction: idStore.approveTransaction.bind(idStore), approveTransaction: idStore.approveTransaction.bind(idStore),
cancelTransaction: idStore.cancelTransaction.bind(idStore), cancelTransaction: idStore.cancelTransaction.bind(idStore),
signMessage: idStore.signMessage.bind(idStore), signMessage: idStore.signMessage.bind(idStore),
cancelMessage: idStore.cancelMessage.bind(idStore), cancelMessage: idStore.cancelMessage.bind(idStore),
setLocked: idStore.setLocked.bind(idStore), setLocked: idStore.setLocked.bind(idStore),
clearSeedWordCache: idStore.clearSeedWordCache.bind(idStore), clearSeedWordCache: idStore.clearSeedWordCache.bind(idStore),
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), tryPassword: idStore.tryPassword.bind(idStore),
recoverSeed: idStore.recoverSeed.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) {
// push updates to popup // push updates to popup
ethStore.on('update', sendUpdate) ethStore.on('update', sendUpdate)
idStore.on('update', sendUpdate) idStore.on('update', sendUpdate)
// teardown on disconnect // teardown on disconnect
eos(stream, function unsubscribe(){ eos(stream, function unsubscribe () {
ethStore.removeListener('update', sendUpdate) ethStore.removeListener('update', sendUpdate)
}) })
function sendUpdate(){ function sendUpdate () {
var state = getState() var state = getState()
remote.sendUpdate(state) remote.sendUpdate(state)
} }
}) })
} }
@ -230,7 +230,7 @@ function setupControllerConnection(stream){
idStore.on('update', updateBadge) idStore.on('update', updateBadge)
function updateBadge(state){ function updateBadge (state) {
var label = '' var label = ''
var unconfTxs = configManager.unconfirmedTxs() var unconfTxs = configManager.unconfirmedTxs()
var unconfTxLen = Object.keys(unconfTxs).length var unconfTxLen = Object.keys(unconfTxs).length
@ -248,7 +248,7 @@ function updateBadge(state){
// Add unconfirmed Tx + Msg // Add unconfirmed Tx + Msg
// //
function newUnsignedTransaction(txParams, onTxDoneCb){ function newUnsignedTransaction (txParams, onTxDoneCb) {
var state = idStore.getState() var state = idStore.getState()
if (!state.isUnlocked) { if (!state.isUnlocked) {
createUnlockRequestNotification({ createUnlockRequestNotification({
@ -260,20 +260,19 @@ function newUnsignedTransaction(txParams, onTxDoneCb){
} }
} }
function newUnsignedMessage(msgParams, cb){ function newUnsignedMessage (msgParams, cb) {
var state = idStore.getState() var state = idStore.getState()
if (!state.isUnlocked) { if (!state.isUnlocked) {
createUnlockRequestNotification({ createUnlockRequestNotification({
title: 'Account Unlock Request', title: 'Account Unlock Request',
}) })
var msgId = idStore.addUnconfirmedMessage(msgParams, cb)
} else { } else {
addUnconfirmedMsg(msgParams, cb) addUnconfirmedMsg(msgParams, cb)
} }
} }
function addUnconfirmedTx(txParams, onTxDoneCb){ function addUnconfirmedTx (txParams, onTxDoneCb) {
idStore.addUnconfirmedTransaction(txParams, onTxDoneCb, function(err, txData){ idStore.addUnconfirmedTransaction(txParams, onTxDoneCb, function (err, txData) {
if (err) return onTxDoneCb(err) if (err) return onTxDoneCb(err)
createTxNotification({ createTxNotification({
title: 'New Unsigned Transaction', title: 'New Unsigned Transaction',
@ -284,7 +283,7 @@ function addUnconfirmedTx(txParams, onTxDoneCb){
}) })
} }
function addUnconfirmedMsg(msgParams, cb){ function addUnconfirmedMsg (msgParams, cb) {
var msgId = idStore.addUnconfirmedMessage(msgParams, cb) var msgId = idStore.addUnconfirmedMessage(msgParams, cb)
createMsgNotification({ createMsgNotification({
title: 'New Unsigned Message', title: 'New Unsigned Message',
@ -298,7 +297,7 @@ function addUnconfirmedMsg(msgParams, cb){
// config // config
// //
function agreeToDisclaimer(cb) { function agreeToDisclaimer (cb) {
try { try {
configManager.setConfirmed(true) configManager.setConfirmed(true)
cb() cb()
@ -308,23 +307,23 @@ function agreeToDisclaimer(cb) {
} }
// called from popup // called from popup
function setRpcTarget(rpcTarget){ function setRpcTarget (rpcTarget) {
configManager.setRpcTarget(rpcTarget) configManager.setRpcTarget(rpcTarget)
chrome.runtime.reload() chrome.runtime.reload()
idStore.getNetwork() idStore.getNetwork()
} }
function setProviderType(type) { function setProviderType (type) {
configManager.setProviderType(type) configManager.setProviderType(type)
chrome.runtime.reload() chrome.runtime.reload()
idStore.getNetwork() idStore.getNetwork()
} }
function useEtherscanProvider() { function useEtherscanProvider () {
configManager.useEtherscanProvider() configManager.useEtherscanProvider()
chrome.runtime.reload() chrome.runtime.reload()
} }
// util // util
function noop(){} function noop () {}

File diff suppressed because it is too large Load Diff

@ -2,12 +2,10 @@ const LocalMessageDuplexStream = require('./lib/local-message-stream.js')
const PortStream = require('./lib/port-stream.js') const PortStream = require('./lib/port-stream.js')
const ObjectMultiplex = require('./lib/obj-multiplex') const ObjectMultiplex = require('./lib/obj-multiplex')
// inject in-page script // inject in-page script
var scriptTag = document.createElement('script') var scriptTag = document.createElement('script')
scriptTag.src = chrome.extension.getURL('scripts/inpage.js') scriptTag.src = chrome.extension.getURL('scripts/inpage.js')
scriptTag.onload = function() { this.parentNode.removeChild(this) } scriptTag.onload = function () { this.parentNode.removeChild(this) }
var container = document.head || document.documentElement var container = document.head || document.documentElement
// append as first child // append as first child
container.insertBefore(scriptTag, container.children[0]) container.insertBefore(scriptTag, container.children[0])
@ -32,7 +30,7 @@ mx.pipe(pageStream)
var reloadStream = mx.createStream('reload') var reloadStream = mx.createStream('reload')
reloadStream.on('error', console.error.bind(console)) reloadStream.on('error', console.error.bind(console))
// if we lose connection with the plugin, trigger tab refresh // if we lose connection with the plugin, trigger tab refresh
pluginStream.on('close', function(){ pluginStream.on('close', function () {
reloadStream.write({ method: 'reset' }) reloadStream.write({ method: 'reset' })
}) })

@ -8,7 +8,6 @@ restoreContextAfterImports()
// remove from window // remove from window
delete window.Web3 delete window.Web3
// //
// setup plugin communication // setup plugin communication
// //
@ -27,7 +26,7 @@ var inpageProvider = new MetamaskInpageProvider(metamaskStream)
// //
var web3 = new Web3(inpageProvider) var web3 = new Web3(inpageProvider)
web3.setProvider = function(){ web3.setProvider = function () {
console.log('MetaMask - overrode web3.setProvider') console.log('MetaMask - overrode web3.setProvider')
} }
console.log('MetaMask - injected web3') console.log('MetaMask - injected web3')
@ -40,7 +39,7 @@ var reloadStream = inpageProvider.multiStream.createStream('reload')
setupDappAutoReload(web3, reloadStream) setupDappAutoReload(web3, reloadStream)
// set web3 defaultAcount // set web3 defaultAcount
inpageProvider.publicConfigStore.subscribe(function(state){ inpageProvider.publicConfigStore.subscribe(function (state) {
web3.eth.defaultAccount = state.selectedAddress web3.eth.defaultAccount = state.selectedAddress
}) })
@ -51,13 +50,13 @@ inpageProvider.publicConfigStore.subscribe(function(state){
// need to make sure we aren't affected by overlapping namespaces // need to make sure we aren't affected by overlapping namespaces
// and that we dont affect the app with our namespace // and that we dont affect the app with our namespace
// mostly a fix for web3's BigNumber if AMD's "define" is defined... // mostly a fix for web3's BigNumber if AMD's "define" is defined...
var __define = undefined var __define
function cleanContextForImports(){ function cleanContextForImports () {
__define = global.define __define = global.define
delete global.define delete global.define
} }
function restoreContextAfterImports(){ function restoreContextAfterImports () {
global.define = __define global.define = __define
} }

@ -1,11 +1,9 @@
var uri = 'https://faucet.metamask.io/' var uri = 'https://faucet.metamask.io/'
module.exports = function(address) { module.exports = function (address) {
var http = new XMLHttpRequest() var http = new XMLHttpRequest()
var data = address var data = address
http.open('POST', uri, true) http.open('POST', uri, true)
http.setRequestHeader('Content-type', 'application/rawdata') http.setRequestHeader('Content-type', 'application/rawdata')
http.send(data) http.send(data)
} }

@ -3,13 +3,11 @@ const ensnare = require('./ensnare.js')
module.exports = setupDappAutoReload module.exports = setupDappAutoReload
function setupDappAutoReload (web3, controlStream) {
function setupDappAutoReload(web3, controlStream){
// export web3 as a global, checking for usage // export web3 as a global, checking for usage
var pageIsUsingWeb3 = false var pageIsUsingWeb3 = false
var resetWasRequested = false var resetWasRequested = false
global.web3 = ensnare(web3, once(function(){ global.web3 = ensnare(web3, once(function () {
// if web3 usage happened after a reset request, trigger reset late // if web3 usage happened after a reset request, trigger reset late
if (resetWasRequested) return triggerReset() if (resetWasRequested) return triggerReset()
// mark web3 as used // mark web3 as used
@ -19,7 +17,7 @@ function setupDappAutoReload(web3, controlStream){
})) }))
// listen for reset requests from metamask // listen for reset requests from metamask
controlStream.once('data', function(){ controlStream.once('data', function () {
resetWasRequested = true resetWasRequested = true
// ignore if web3 was not used // ignore if web3 was not used
if (!pageIsUsingWeb3) return if (!pageIsUsingWeb3) return
@ -28,10 +26,9 @@ function setupDappAutoReload(web3, controlStream){
}) })
// reload the page // reload the page
function triggerReset(){ function triggerReset () {
setTimeout(function(){ setTimeout(function () {
global.location.reload() global.location.reload()
}, 500) }, 500)
} }
}
}

@ -7,7 +7,6 @@ const STORAGE_KEY = 'metamask-config'
const TESTNET_RPC = MetamaskConfig.network.testnet const TESTNET_RPC = MetamaskConfig.network.testnet
const MAINNET_RPC = MetamaskConfig.network.mainnet const MAINNET_RPC = MetamaskConfig.network.mainnet
/* The config-manager is a convenience object /* The config-manager is a convenience object
* wrapping a pojo-migrator. * wrapping a pojo-migrator.
* *
@ -16,7 +15,7 @@ const MAINNET_RPC = MetamaskConfig.network.mainnet
* particular portions of the state. * particular portions of the state.
*/ */
module.exports = ConfigManager module.exports = ConfigManager
function ConfigManager() { function ConfigManager () {
// ConfigManager is observable and will emit updates // ConfigManager is observable and will emit updates
this._subs = [] this._subs = []
@ -26,7 +25,7 @@ function ConfigManager() {
* getData(), which returns the app-consumable data object * getData(), which returns the app-consumable data object
* saveData(), which persists the app-consumable data object. * saveData(), which persists the app-consumable data object.
*/ */
this.migrator = new Migrator({ this.migrator = new Migrator({
// Migrations must start at version 1 or later. // Migrations must start at version 1 or later.
// They are objects with a `version` number // They are objects with a `version` number
@ -41,20 +40,20 @@ function ConfigManager() {
loadData: loadData, loadData: loadData,
// How to persist migrated config. // How to persist migrated config.
setData: function(data) { setData: function (data) {
window.localStorage[STORAGE_KEY] = JSON.stringify(data) window.localStorage[STORAGE_KEY] = JSON.stringify(data)
}, },
}) })
} }
ConfigManager.prototype.setConfig = function(config) { ConfigManager.prototype.setConfig = function (config) {
var data = this.migrator.getData() var data = this.migrator.getData()
data.config = config data.config = config
this.setData(data) this.setData(data)
this._emitUpdates(config) this._emitUpdates(config)
} }
ConfigManager.prototype.getConfig = function() { ConfigManager.prototype.getConfig = function () {
var data = this.migrator.getData() var data = this.migrator.getData()
if ('config' in data) { if ('config' in data) {
return data.config return data.config
@ -62,12 +61,12 @@ ConfigManager.prototype.getConfig = function() {
return { return {
provider: { provider: {
type: 'testnet', type: 'testnet',
} },
} }
} }
} }
ConfigManager.prototype.setRpcTarget = function(rpcUrl) { ConfigManager.prototype.setRpcTarget = function (rpcUrl) {
var config = this.getConfig() var config = this.getConfig()
config.provider = { config.provider = {
type: 'rpc', type: 'rpc',
@ -76,7 +75,7 @@ ConfigManager.prototype.setRpcTarget = function(rpcUrl) {
this.setConfig(config) this.setConfig(config)
} }
ConfigManager.prototype.setProviderType = function(type) { ConfigManager.prototype.setProviderType = function (type) {
var config = this.getConfig() var config = this.getConfig()
config.provider = { config.provider = {
type: type, type: type,
@ -84,7 +83,7 @@ ConfigManager.prototype.setProviderType = function(type) {
this.setConfig(config) this.setConfig(config)
} }
ConfigManager.prototype.useEtherscanProvider = function() { ConfigManager.prototype.useEtherscanProvider = function () {
var config = this.getConfig() var config = this.getConfig()
config.provider = { config.provider = {
type: 'etherscan', type: 'etherscan',
@ -92,75 +91,75 @@ ConfigManager.prototype.useEtherscanProvider = function() {
this.setConfig(config) this.setConfig(config)
} }
ConfigManager.prototype.getProvider = function() { ConfigManager.prototype.getProvider = function () {
var config = this.getConfig() var config = this.getConfig()
return config.provider return config.provider
} }
ConfigManager.prototype.setData = function(data) { ConfigManager.prototype.setData = function (data) {
this.migrator.saveData(data) this.migrator.saveData(data)
} }
ConfigManager.prototype.getData = function() { ConfigManager.prototype.getData = function () {
return this.migrator.getData() return this.migrator.getData()
} }
ConfigManager.prototype.setWallet = function(wallet) { ConfigManager.prototype.setWallet = function (wallet) {
var data = this.migrator.getData() var data = this.migrator.getData()
data.wallet = wallet data.wallet = wallet
this.setData(data) this.setData(data)
} }
ConfigManager.prototype.getSelectedAccount = function() { ConfigManager.prototype.getSelectedAccount = function () {
var config = this.getConfig() var config = this.getConfig()
return config.selectedAccount return config.selectedAccount
} }
ConfigManager.prototype.setSelectedAccount = function(address) { ConfigManager.prototype.setSelectedAccount = function (address) {
var config = this.getConfig() var config = this.getConfig()
config.selectedAccount = address config.selectedAccount = address
this.setConfig(config) this.setConfig(config)
} }
ConfigManager.prototype.getWallet = function() { ConfigManager.prototype.getWallet = function () {
return this.migrator.getData().wallet return this.migrator.getData().wallet
} }
// Takes a boolean // Takes a boolean
ConfigManager.prototype.setShowSeedWords = function(should) { ConfigManager.prototype.setShowSeedWords = function (should) {
var data = this.migrator.getData() var data = this.migrator.getData()
data.showSeedWords = should data.showSeedWords = should
this.setData(data) this.setData(data)
} }
ConfigManager.prototype.getShouldShowSeedWords = function() { ConfigManager.prototype.getShouldShowSeedWords = function () {
var data = this.migrator.getData() var data = this.migrator.getData()
return data.showSeedWords return data.showSeedWords
} }
ConfigManager.prototype.getCurrentRpcAddress = function() { ConfigManager.prototype.getCurrentRpcAddress = function () {
var provider = this.getProvider() var provider = this.getProvider()
if (!provider) return null if (!provider) return null
switch (provider.type) { switch (provider.type) {
case 'mainnet': case 'mainnet':
return MAINNET_RPC return MAINNET_RPC
case 'testnet': case 'testnet':
return TESTNET_RPC return TESTNET_RPC
default: default:
return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC
} }
} }
ConfigManager.prototype.clearWallet = function() { ConfigManager.prototype.clearWallet = function () {
var data = this.getConfig() var data = this.getConfig()
delete data.wallet delete data.wallet
this.setData(data) this.setData(data)
} }
ConfigManager.prototype.setData = function(data) { ConfigManager.prototype.setData = function (data) {
this.migrator.saveData(data) this.migrator.saveData(data)
} }
@ -168,7 +167,7 @@ ConfigManager.prototype.setData = function(data) {
// Tx // Tx
// //
ConfigManager.prototype.getTxList = function() { ConfigManager.prototype.getTxList = function () {
var data = this.migrator.getData() var data = this.migrator.getData()
if (data.transactions !== undefined) { if (data.transactions !== undefined) {
return data.transactions return data.transactions
@ -177,45 +176,45 @@ ConfigManager.prototype.getTxList = function() {
} }
} }
ConfigManager.prototype.unconfirmedTxs = function() { ConfigManager.prototype.unconfirmedTxs = function () {
var transactions = this.getTxList() var transactions = this.getTxList()
return transactions.filter(tx => tx.status === 'unconfirmed') return transactions.filter(tx => tx.status === 'unconfirmed')
.reduce((result, tx) => { result[tx.id] = tx; return result }, {}) .reduce((result, tx) => { result[tx.id] = tx; return result }, {})
} }
ConfigManager.prototype._saveTxList = function(txList) { ConfigManager.prototype._saveTxList = function (txList) {
var data = this.migrator.getData() var data = this.migrator.getData()
data.transactions = txList data.transactions = txList
this.setData(data) this.setData(data)
} }
ConfigManager.prototype.addTx = function(tx) { ConfigManager.prototype.addTx = function (tx) {
var transactions = this.getTxList() var transactions = this.getTxList()
transactions.push(tx) transactions.push(tx)
this._saveTxList(transactions) this._saveTxList(transactions)
} }
ConfigManager.prototype.getTx = function(txId) { ConfigManager.prototype.getTx = function (txId) {
var transactions = this.getTxList() var transactions = this.getTxList()
var matching = transactions.filter(tx => tx.id === txId) var matching = transactions.filter(tx => tx.id === txId)
return matching.length > 0 ? matching[0] : null return matching.length > 0 ? matching[0] : null
} }
ConfigManager.prototype.confirmTx = function(txId) { ConfigManager.prototype.confirmTx = function (txId) {
this._setTxStatus(txId, 'confirmed') this._setTxStatus(txId, 'confirmed')
} }
ConfigManager.prototype.rejectTx = function(txId) { ConfigManager.prototype.rejectTx = function (txId) {
this._setTxStatus(txId, 'rejected') this._setTxStatus(txId, 'rejected')
} }
ConfigManager.prototype._setTxStatus = function(txId, status) { ConfigManager.prototype._setTxStatus = function (txId, status) {
var tx = this.getTx(txId) var tx = this.getTx(txId)
tx.status = status tx.status = status
this.updateTx(tx) this.updateTx(tx)
} }
ConfigManager.prototype.updateTx = function(tx) { ConfigManager.prototype.updateTx = function (tx) {
var transactions = this.getTxList() var transactions = this.getTxList()
var found, index var found, index
transactions.forEach((otherTx, i) => { transactions.forEach((otherTx, i) => {
@ -232,19 +231,19 @@ ConfigManager.prototype.updateTx = function(tx) {
// wallet nickname methods // wallet nickname methods
ConfigManager.prototype.getWalletNicknames = function() { ConfigManager.prototype.getWalletNicknames = function () {
var data = this.getData() var data = this.getData()
let nicknames = ('walletNicknames' in data) ? data.walletNicknames : {} const nicknames = ('walletNicknames' in data) ? data.walletNicknames : {}
return nicknames return nicknames
} }
ConfigManager.prototype.nicknameForWallet = function(account) { ConfigManager.prototype.nicknameForWallet = function (account) {
let nicknames = this.getWalletNicknames() const nicknames = this.getWalletNicknames()
return nicknames[account] return nicknames[account]
} }
ConfigManager.prototype.setNicknameForWallet = function(account, nickname) { ConfigManager.prototype.setNicknameForWallet = function (account, nickname) {
let nicknames = this.getWalletNicknames() const nicknames = this.getWalletNicknames()
nicknames[account] = nickname nicknames[account] = nickname
var data = this.getData() var data = this.getData()
data.walletNicknames = nicknames data.walletNicknames = nicknames
@ -253,37 +252,35 @@ ConfigManager.prototype.setNicknameForWallet = function(account, nickname) {
// observable // observable
ConfigManager.prototype.subscribe = function(fn){ ConfigManager.prototype.subscribe = function (fn) {
this._subs.push(fn) this._subs.push(fn)
var unsubscribe = this.unsubscribe.bind(this, fn) var unsubscribe = this.unsubscribe.bind(this, fn)
return unsubscribe return unsubscribe
} }
ConfigManager.prototype.unsubscribe = function(fn){ ConfigManager.prototype.unsubscribe = function (fn) {
var index = this._subs.indexOf(fn) var index = this._subs.indexOf(fn)
if (index !== -1) this._subs.splice(index, 1) if (index !== -1) this._subs.splice(index, 1)
} }
ConfigManager.prototype._emitUpdates = function(state){ ConfigManager.prototype._emitUpdates = function (state) {
this._subs.forEach(function(handler){ this._subs.forEach(function (handler) {
handler(state) handler(state)
}) })
} }
ConfigManager.prototype.setConfirmed = function(confirmed) { ConfigManager.prototype.setConfirmed = function (confirmed) {
var data = this.getData() var data = this.getData()
data.isConfirmed = confirmed data.isConfirmed = confirmed
this.setData(data) this.setData(data)
} }
ConfigManager.prototype.getConfirmed = function() { ConfigManager.prototype.getConfirmed = function () {
var data = this.getData() var data = this.getData()
return ('isConfirmed' in data) && data.isConfirmed return ('isConfirmed' in data) && data.isConfirmed
} }
function loadData () {
function loadData() {
var oldData = getOldStyleData() var oldData = getOldStyleData()
var newData var newData
try { try {
@ -298,14 +295,14 @@ function loadData() {
config: { config: {
provider: { provider: {
type: 'testnet', type: 'testnet',
} },
} },
} },
}, oldData ? oldData : null, newData ? newData : null) }, oldData || null, newData || null)
return data return data
} }
function getOldStyleData() { function getOldStyleData () {
var config, wallet, seedWords var config, wallet, seedWords
var result = { var result = {

@ -1,21 +1,21 @@
module.exports = ensnare module.exports = ensnare
// creates a proxy object that calls cb everytime the obj's properties/fns are accessed // creates a proxy object that calls cb everytime the obj's properties/fns are accessed
function ensnare(obj, cb){ function ensnare (obj, cb) {
var proxy = {} var proxy = {}
Object.keys(obj).forEach(function(key){ Object.keys(obj).forEach(function (key) {
var val = obj[key] var val = obj[key]
switch (typeof val) { switch (typeof val) {
case 'function': case 'function':
proxy[key] = function(){ proxy[key] = function () {
cb() cb()
val.apply(obj, arguments) val.apply(obj, arguments)
} }
return return
default: default:
Object.defineProperty(proxy, key, { Object.defineProperty(proxy, key, {
get: function(){ cb(); return obj[key] }, get: function () { cb(); return obj[key] },
set: function(val){ cb(); return obj[key] = val }, set: function (val) { cb(); obj[key] = val; return val },
}) })
return return
} }

@ -4,19 +4,18 @@ const configManager = require('./config-manager-singleton')
module.exports = IdManagement module.exports = IdManagement
function IdManagement (opts) {
function IdManagement(opts) {
if (!opts) opts = {} if (!opts) opts = {}
this.keyStore = opts.keyStore this.keyStore = opts.keyStore
this.derivedKey = opts.derivedKey this.derivedKey = opts.derivedKey
this.hdPathString = "m/44'/60'/0'/0" this.hdPathString = "m/44'/60'/0'/0"
this.getAddresses = function(){ this.getAddresses = function () {
return keyStore.getAddresses(this.hdPathString).map(function(address){ return '0x'+address }) return this.keyStore.getAddresses(this.hdPathString).map(function (address) { return '0x' + address })
} }
this.signTx = function(txParams){ this.signTx = function (txParams) {
// normalize values // normalize values
txParams.to = ethUtil.addHexPrefix(txParams.to) txParams.to = ethUtil.addHexPrefix(txParams.to)
txParams.from = ethUtil.addHexPrefix(txParams.from) txParams.from = ethUtil.addHexPrefix(txParams.from)
@ -44,34 +43,34 @@ function IdManagement(opts) {
this.signMsg = function (address, message) { this.signMsg = function (address, message) {
// sign message // sign message
var privKeyHex = this.exportPrivateKey(address); var privKeyHex = this.exportPrivateKey(address)
var privKey = ethUtil.toBuffer(privKeyHex); var privKey = ethUtil.toBuffer(privKeyHex)
var msgSig = ethUtil.ecsign(new Buffer(message.replace('0x',''), 'hex'), privKey); var msgSig = ethUtil.ecsign(new Buffer(message.replace('0x', ''), 'hex'), privKey)
var rawMsgSig = ethUtil.bufferToHex(concatSig(msgSig.v, msgSig.r, msgSig.s)); var rawMsgSig = ethUtil.bufferToHex(concatSig(msgSig.v, msgSig.r, msgSig.s))
return rawMsgSig; return rawMsgSig
}; }
this.getSeed = function(){ this.getSeed = function () {
return this.keyStore.getSeed(this.derivedKey) return this.keyStore.getSeed(this.derivedKey)
} }
this.exportPrivateKey = function(address) { this.exportPrivateKey = function (address) {
var privKeyHex = ethUtil.addHexPrefix(this.keyStore.exportPrivateKey(address, this.derivedKey, this.hdPathString)) var privKeyHex = ethUtil.addHexPrefix(this.keyStore.exportPrivateKey(address, this.derivedKey, this.hdPathString))
return privKeyHex return privKeyHex
} }
} }
function pad_with_zeroes(number, length){ function padWithZeroes (number, length) {
var my_string = '' + number; var myString = '' + number
while (my_string.length < length) { while (myString.length < length) {
my_string = '0' + my_string; myString = '0' + myString
} }
return my_string; return myString
} }
function concatSig(v, r, s) { function concatSig (v, r, s) {
r = pad_with_zeroes(ethUtil.fromSigned(r), 64) r = padWithZeroes(ethUtil.fromSigned(r), 64)
s = pad_with_zeroes(ethUtil.fromSigned(s), 64) s = padWithZeroes(ethUtil.fromSigned(s), 64)
r = ethUtil.stripHexPrefix(r.toString('hex')) r = ethUtil.stripHexPrefix(r.toString('hex'))
s = ethUtil.stripHexPrefix(s.toString('hex')) s = ethUtil.stripHexPrefix(s.toString('hex'))
v = ethUtil.stripHexPrefix(ethUtil.intToHex(v)) v = ethUtil.stripHexPrefix(ethUtil.intToHex(v))

@ -1,10 +1,7 @@
const EventEmitter = require('events').EventEmitter const EventEmitter = require('events').EventEmitter
const inherits = require('util').inherits const inherits = require('util').inherits
const Transaction = require('ethereumjs-tx')
const ethUtil = require('ethereumjs-util') const ethUtil = require('ethereumjs-util')
const LightwalletKeyStore = require('eth-lightwallet').keystore const LightwalletKeyStore = require('eth-lightwallet').keystore
const LightwalletSigner = require('eth-lightwallet').signing
const async = require('async')
const clone = require('clone') const clone = require('clone')
const extend = require('xtend') const extend = require('xtend')
const createId = require('web3-provider-engine/util/random-id') const createId = require('web3-provider-engine/util/random-id')
@ -15,12 +12,10 @@ const messageManager = require('./message-manager')
const DEFAULT_RPC = 'https://testrpc.metamask.io/' const DEFAULT_RPC = 'https://testrpc.metamask.io/'
const IdManagement = require('./id-management') const IdManagement = require('./id-management')
module.exports = IdentityStore module.exports = IdentityStore
inherits(IdentityStore, EventEmitter) inherits(IdentityStore, EventEmitter)
function IdentityStore(opts = {}) { function IdentityStore (opts = {}) {
EventEmitter.call(this) EventEmitter.call(this)
// we just use the ethStore to auto-add accounts // we just use the ethStore to auto-add accounts
@ -46,7 +41,7 @@ function IdentityStore(opts = {}) {
// public // public
// //
IdentityStore.prototype.createNewVault = function(password, entropy, cb){ IdentityStore.prototype.createNewVault = function (password, entropy, cb) {
delete this._keyStore delete this._keyStore
configManager.clearWallet() configManager.clearWallet()
this._createIdmgmt(password, null, entropy, (err) => { this._createIdmgmt(password, null, entropy, (err) => {
@ -62,14 +57,14 @@ IdentityStore.prototype.createNewVault = function(password, entropy, cb){
}) })
} }
IdentityStore.prototype.recoverSeed = function(cb){ IdentityStore.prototype.recoverSeed = function (cb) {
configManager.setShowSeedWords(true) configManager.setShowSeedWords(true)
if (!this._idmgmt) return cb(new Error('Unauthenticated. Please sign in.')) if (!this._idmgmt) return cb(new Error('Unauthenticated. Please sign in.'))
var seedWords = this._idmgmt.getSeed() var seedWords = this._idmgmt.getSeed()
cb(null, seedWords) 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)
@ -79,18 +74,17 @@ IdentityStore.prototype.recoverFromSeed = function(password, seed, cb){
}) })
} }
IdentityStore.prototype.setStore = function(store){ IdentityStore.prototype.setStore = function (store) {
this._ethStore = store this._ethStore = store
} }
IdentityStore.prototype.clearSeedWordCache = function(cb) { IdentityStore.prototype.clearSeedWordCache = function (cb) {
configManager.setShowSeedWords(false) configManager.setShowSeedWords(false)
cb(null, configManager.getSelectedAccount()) cb(null, configManager.getSelectedAccount())
} }
IdentityStore.prototype.getState = function(){ IdentityStore.prototype.getState = function () {
var seedWords = this.getSeedIfUnlocked() var seedWords = this.getSeedIfUnlocked()
var wallet = configManager.getWallet()
return clone(extend(this._currentState, { return clone(extend(this._currentState, {
isInitialized: !!configManager.getWallet() && !seedWords, isInitialized: !!configManager.getWallet() && !seedWords,
isUnlocked: this._isUnlocked(), isUnlocked: this._isUnlocked(),
@ -104,7 +98,7 @@ IdentityStore.prototype.getState = function(){
})) }))
} }
IdentityStore.prototype.getSeedIfUnlocked = function() { IdentityStore.prototype.getSeedIfUnlocked = function () {
var showSeed = configManager.getShouldShowSeedWords() var showSeed = configManager.getShouldShowSeedWords()
var idmgmt = this._idmgmt var idmgmt = this._idmgmt
var shouldShow = showSeed && !!idmgmt var shouldShow = showSeed && !!idmgmt
@ -112,11 +106,11 @@ IdentityStore.prototype.getSeedIfUnlocked = function() {
return seedWords return seedWords
} }
IdentityStore.prototype.getSelectedAddress = function(){ IdentityStore.prototype.getSelectedAddress = function () {
return configManager.getSelectedAccount() return configManager.getSelectedAccount()
} }
IdentityStore.prototype.setSelectedAddress = function(address, cb){ IdentityStore.prototype.setSelectedAddress = function (address, cb) {
if (!address) { if (!address) {
var addresses = this._getAddresses() var addresses = this._getAddresses()
address = addresses[0] address = addresses[0]
@ -126,8 +120,7 @@ IdentityStore.prototype.setSelectedAddress = function(address, cb){
if (cb) return cb(null, address) if (cb) return cb(null, address)
} }
IdentityStore.prototype.revealAccount = function(cb) { IdentityStore.prototype.revealAccount = function (cb) {
let addresses = this._getAddresses()
const derivedKey = this._idmgmt.derivedKey const derivedKey = this._idmgmt.derivedKey
const keyStore = this._keyStore const keyStore = this._keyStore
@ -135,14 +128,12 @@ IdentityStore.prototype.revealAccount = function(cb) {
keyStore.generateNewAddress(derivedKey, 1) keyStore.generateNewAddress(derivedKey, 1)
configManager.setWallet(keyStore.serialize()) configManager.setWallet(keyStore.serialize())
addresses = this._getAddresses()
this._loadIdentities() this._loadIdentities()
this._didUpdate() this._didUpdate()
cb(null) cb(null)
} }
IdentityStore.prototype.getNetwork = function(err) { IdentityStore.prototype.getNetwork = function (err) {
if (err) { if (err) {
this._currentState.network = 'loading' this._currentState.network = 'loading'
this._didUpdate() this._didUpdate()
@ -160,13 +151,13 @@ IdentityStore.prototype.getNetwork = function(err) {
}) })
} }
IdentityStore.prototype.setLocked = function(cb){ IdentityStore.prototype.setLocked = function (cb) {
delete this._keyStore delete this._keyStore
delete this._idmgmt delete this._idmgmt
cb() 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...
@ -175,7 +166,7 @@ IdentityStore.prototype.submitPassword = function(password, cb){
}) })
} }
IdentityStore.prototype.exportAccount = function(address, cb) { IdentityStore.prototype.exportAccount = function (address, cb) {
var privateKey = this._idmgmt.exportPrivateKey(address) var privateKey = this._idmgmt.exportPrivateKey(address)
cb(null, privateKey) cb(null, privateKey)
} }
@ -185,7 +176,7 @@ IdentityStore.prototype.exportAccount = function(address, cb) {
// //
// comes from dapp via zero-client hooked-wallet provider // comes from dapp via zero-client hooked-wallet provider
IdentityStore.prototype.addUnconfirmedTransaction = function(txParams, onTxDoneCb, cb){ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDoneCb, cb) {
var self = this var self = this
// create txData obj with parameters and meta data // create txData obj with parameters and meta data
var time = (new Date()).getTime() var time = (new Date()).getTime()
@ -208,13 +199,13 @@ IdentityStore.prototype.addUnconfirmedTransaction = function(txParams, onTxDoneC
// perform static analyis on the target contract code // perform static analyis on the target contract code
var provider = self._ethStore._query.currentProvider var provider = self._ethStore._query.currentProvider
if (txParams.to) { if (txParams.to) {
provider.sendAsync({ id: 1, method: 'eth_getCode', params: [txParams.to, 'latest'] }, function(err, res){ provider.sendAsync({ id: 1, method: 'eth_getCode', params: [txParams.to, 'latest'] }, function (err, res) {
if (err) return didComplete(err) if (err) return didComplete(err)
if (res.error) return didComplete(res.error) if (res.error) return didComplete(res.error)
var code = ethUtil.toBuffer(res.result) var code = ethUtil.toBuffer(res.result)
if (code !== '0x') { if (code !== '0x') {
var ops = ethBinToOps(code) var ops = ethBinToOps(code)
var containsDelegateCall = ops.some((op)=>op.name === 'DELEGATECALL') var containsDelegateCall = ops.some((op) => op.name === 'DELEGATECALL')
txData.containsDelegateCall = containsDelegateCall txData.containsDelegateCall = containsDelegateCall
didComplete() didComplete()
} else { } else {
@ -225,19 +216,17 @@ IdentityStore.prototype.addUnconfirmedTransaction = function(txParams, onTxDoneC
didComplete() didComplete()
} }
function didComplete(err){ function didComplete (err) {
if (err) return cb(err) if (err) return cb(err)
// signal update // signal update
self._didUpdate() self._didUpdate()
// signal completion of add tx // signal completion of add tx
cb(null, txData) cb(null, txData)
} }
} }
// comes from metamask ui // comes from metamask ui
IdentityStore.prototype.approveTransaction = function(txId, cb){ IdentityStore.prototype.approveTransaction = function (txId, cb) {
var txData = configManager.getTx(txId)
var approvalCb = this._unconfTxCbs[txId] || noop var approvalCb = this._unconfTxCbs[txId] || noop
// accept tx // accept tx
@ -250,8 +239,7 @@ IdentityStore.prototype.approveTransaction = function(txId, cb){
} }
// comes from metamask ui // comes from metamask ui
IdentityStore.prototype.cancelTransaction = function(txId){ IdentityStore.prototype.cancelTransaction = function (txId) {
var txData = configManager.getTx(txId)
var approvalCb = this._unconfTxCbs[txId] || noop var approvalCb = this._unconfTxCbs[txId] || noop
// reject tx // reject tx
@ -263,7 +251,7 @@ IdentityStore.prototype.cancelTransaction = function(txId){
} }
// performs the actual signing, no autofill of params // performs the actual signing, no autofill of params
IdentityStore.prototype.signTransaction = function(txParams, cb){ IdentityStore.prototype.signTransaction = function (txParams, cb) {
try { try {
console.log('signing tx...', txParams) console.log('signing tx...', txParams)
var rawTx = this._idmgmt.signTx(txParams) var rawTx = this._idmgmt.signTx(txParams)
@ -278,8 +266,7 @@ IdentityStore.prototype.signTransaction = function(txParams, cb){
// //
// comes from dapp via zero-client hooked-wallet provider // comes from dapp via zero-client hooked-wallet provider
IdentityStore.prototype.addUnconfirmedMessage = function(msgParams, cb){ IdentityStore.prototype.addUnconfirmedMessage = function (msgParams, cb) {
// create txData obj with parameters and meta data // create txData obj with parameters and meta data
var time = (new Date()).getTime() var time = (new Date()).getTime()
var msgId = createId() var msgId = createId()
@ -303,8 +290,7 @@ IdentityStore.prototype.addUnconfirmedMessage = function(msgParams, cb){
} }
// comes from metamask ui // comes from metamask ui
IdentityStore.prototype.approveMessage = function(msgId, cb){ IdentityStore.prototype.approveMessage = function (msgId, cb) {
var msgData = messageManager.getMsg(msgId)
var approvalCb = this._unconfMsgCbs[msgId] || noop var approvalCb = this._unconfMsgCbs[msgId] || noop
// accept msg // accept msg
@ -317,8 +303,7 @@ IdentityStore.prototype.approveMessage = function(msgId, cb){
} }
// comes from metamask ui // comes from metamask ui
IdentityStore.prototype.cancelMessage = function(msgId){ IdentityStore.prototype.cancelMessage = function (msgId) {
var txData = messageManager.getMsg(msgId)
var approvalCb = this._unconfMsgCbs[msgId] || noop var approvalCb = this._unconfMsgCbs[msgId] || noop
// reject tx // reject tx
@ -330,7 +315,7 @@ IdentityStore.prototype.cancelMessage = function(msgId){
} }
// performs the actual signing, no autofill of params // performs the actual signing, no autofill of params
IdentityStore.prototype.signMessage = function(msgParams, cb){ IdentityStore.prototype.signMessage = function (msgParams, cb) {
try { try {
console.log('signing msg...', msgParams.data) console.log('signing msg...', msgParams.data)
var rawMsg = this._idmgmt.signMsg(msgParams.from, msgParams.data) var rawMsg = this._idmgmt.signMsg(msgParams.from, msgParams.data)
@ -351,17 +336,17 @@ IdentityStore.prototype.signMessage = function(msgParams, cb){
// private // private
// //
IdentityStore.prototype._didUpdate = function(){ IdentityStore.prototype._didUpdate = function () {
this.emit('update', this.getState()) this.emit('update', this.getState())
} }
IdentityStore.prototype._isUnlocked = function(){ IdentityStore.prototype._isUnlocked = function () {
var result = Boolean(this._keyStore) && Boolean(this._idmgmt) var result = Boolean(this._keyStore) && Boolean(this._idmgmt)
return result return result
} }
// load identities from keyStoreet // load identities from keyStoreet
IdentityStore.prototype._loadIdentities = function(){ IdentityStore.prototype._loadIdentities = function () {
if (!this._isUnlocked()) throw new Error('not unlocked') if (!this._isUnlocked()) throw new Error('not unlocked')
var addresses = this._getAddresses() var addresses = this._getAddresses()
@ -369,7 +354,7 @@ IdentityStore.prototype._loadIdentities = function(){
// // add to ethStore // // add to ethStore
this._ethStore.addAccount(address) this._ethStore.addAccount(address)
// add to identities // add to identities
const defaultLabel = 'Wallet ' + (i+1) const defaultLabel = 'Wallet ' + (i + 1)
const nickname = configManager.nicknameForWallet(address) const nickname = configManager.nicknameForWallet(address)
var identity = { var identity = {
name: nickname || defaultLabel, name: nickname || defaultLabel,
@ -381,7 +366,7 @@ IdentityStore.prototype._loadIdentities = function(){
this._didUpdate() this._didUpdate()
} }
IdentityStore.prototype.saveAccountLabel = function(account, label, cb) { IdentityStore.prototype.saveAccountLabel = function (account, label, cb) {
configManager.setNicknameForWallet(account, label) configManager.setNicknameForWallet(account, label)
this._loadIdentities() this._loadIdentities()
cb(null, label) cb(null, label)
@ -393,7 +378,7 @@ IdentityStore.prototype.saveAccountLabel = function(account, label, cb) {
// The UI will have to check the balance to know. // The UI will have to check the balance to know.
// If there is no balance and it mayBeFauceting, // If there is no balance and it mayBeFauceting,
// then it is in fact fauceting. // then it is in fact fauceting.
IdentityStore.prototype._mayBeFauceting = function(i) { IdentityStore.prototype._mayBeFauceting = function (i) {
var config = configManager.getProvider() var config = configManager.getProvider()
if (i === 0 && if (i === 0 &&
config.type === 'rpc' && config.type === 'rpc' &&
@ -407,11 +392,11 @@ 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)
} }
IdentityStore.prototype._createIdmgmt = function(password, seed, entropy, cb){ IdentityStore.prototype._createIdmgmt = function (password, seed, entropy, cb) {
var keyStore = null var keyStore = null
LightwalletKeyStore.deriveKeyFromPassword(password, (err, derivedKey) => { LightwalletKeyStore.deriveKeyFromPassword(password, (err, derivedKey) => {
if (err) return cb(err) if (err) return cb(err)
@ -446,9 +431,9 @@ IdentityStore.prototype._createIdmgmt = function(password, seed, entropy, cb){
}) })
} }
IdentityStore.prototype._restoreFromSeed = function(password, seed, derivedKey) { IdentityStore.prototype._restoreFromSeed = function (password, seed, derivedKey) {
var keyStore = new LightwalletKeyStore(seed, derivedKey, this.hdPathString) var keyStore = new LightwalletKeyStore(seed, derivedKey, this.hdPathString)
keyStore.addHdDerivationPath(this.hdPathString, derivedKey, {curve: 'secp256k1', purpose: 'sign'}); keyStore.addHdDerivationPath(this.hdPathString, derivedKey, {curve: 'secp256k1', purpose: 'sign'})
keyStore.setDefaultHdDerivationPath(this.hdPathString) keyStore.setDefaultHdDerivationPath(this.hdPathString)
keyStore.generateNewAddress(derivedKey, 3) keyStore.generateNewAddress(derivedKey, 3)
@ -457,10 +442,10 @@ IdentityStore.prototype._restoreFromSeed = function(password, seed, derivedKey)
return keyStore return keyStore
} }
IdentityStore.prototype._createFirstWallet = function(entropy, derivedKey) { IdentityStore.prototype._createFirstWallet = function (entropy, derivedKey) {
var secretSeed = LightwalletKeyStore.generateRandomSeed(entropy) var secretSeed = LightwalletKeyStore.generateRandomSeed(entropy)
var keyStore = new LightwalletKeyStore(secretSeed, derivedKey, this.hdPathString) var keyStore = new LightwalletKeyStore(secretSeed, derivedKey, this.hdPathString)
keyStore.addHdDerivationPath(this.hdPathString, derivedKey, {curve: 'secp256k1', purpose: 'sign'}); keyStore.addHdDerivationPath(this.hdPathString, derivedKey, {curve: 'secp256k1', purpose: 'sign'})
keyStore.setDefaultHdDerivationPath(this.hdPathString) keyStore.setDefaultHdDerivationPath(this.hdPathString)
keyStore.generateNewAddress(derivedKey, 3) keyStore.generateNewAddress(derivedKey, 3)
@ -470,15 +455,15 @@ IdentityStore.prototype._createFirstWallet = function(entropy, derivedKey) {
} }
// get addresses and normalize address hexString // get addresses and normalize address hexString
IdentityStore.prototype._getAddresses = function() { IdentityStore.prototype._getAddresses = function () {
return this._keyStore.getAddresses(this.hdPathString).map((address) => { return '0x'+address }) return this._keyStore.getAddresses(this.hdPathString).map((address) => { return '0x' + address })
} }
IdentityStore.prototype._autoFaucet = function() { IdentityStore.prototype._autoFaucet = function () {
var addresses = this._getAddresses() var addresses = this._getAddresses()
autoFaucet(addresses[0]) autoFaucet(addresses[0])
} }
// util // util
function noop(){} function noop () {}

@ -7,13 +7,12 @@ const MetamaskConfig = require('../config.js')
module.exports = MetamaskInpageProvider module.exports = MetamaskInpageProvider
function MetamaskInpageProvider (connectionStream) {
function MetamaskInpageProvider(connectionStream){
const self = this const self = this
// setup connectionStream multiplexing // setup connectionStream multiplexing
var multiStream = ObjectMultiplex() var multiStream = ObjectMultiplex()
Streams.pipe(connectionStream, multiStream, connectionStream, function(err){ Streams.pipe(connectionStream, multiStream, connectionStream, function (err) {
console.warn('MetamaskInpageProvider - lost connection to MetaMask') console.warn('MetamaskInpageProvider - lost connection to MetaMask')
if (err) throw err if (err) throw err
}) })
@ -22,7 +21,7 @@ function MetamaskInpageProvider(connectionStream){
// subscribe to metamask public config // subscribe to metamask public config
var publicConfigStore = remoteStoreWithLocalStorageCache('MetaMask-Config') var publicConfigStore = remoteStoreWithLocalStorageCache('MetaMask-Config')
var storeStream = publicConfigStore.createStream() var storeStream = publicConfigStore.createStream()
Streams.pipe(storeStream, multiStream.createStream('publicConfig'), storeStream, function(err){ Streams.pipe(storeStream, multiStream.createStream('publicConfig'), storeStream, function (err) {
console.warn('MetamaskInpageProvider - lost connection to MetaMask publicConfig') console.warn('MetamaskInpageProvider - lost connection to MetaMask publicConfig')
if (err) throw err if (err) throw err
}) })
@ -31,13 +30,13 @@ function MetamaskInpageProvider(connectionStream){
// connect to sync provider // connect to sync provider
self.syncProvider = createSyncProvider(publicConfigStore.get('provider')) self.syncProvider = createSyncProvider(publicConfigStore.get('provider'))
// subscribe to publicConfig to update the syncProvider on change // subscribe to publicConfig to update the syncProvider on change
publicConfigStore.subscribe(function(state){ publicConfigStore.subscribe(function (state) {
self.syncProvider = createSyncProvider(state.provider) self.syncProvider = createSyncProvider(state.provider)
}) })
// connect to async provider // connect to async provider
var asyncProvider = new StreamProvider() var asyncProvider = new StreamProvider()
Streams.pipe(asyncProvider, multiStream.createStream('provider'), asyncProvider, function(err){ Streams.pipe(asyncProvider, multiStream.createStream('provider'), asyncProvider, function (err) {
console.warn('MetamaskInpageProvider - lost connection to MetaMask provider') console.warn('MetamaskInpageProvider - lost connection to MetaMask provider')
if (err) throw err if (err) throw err
}) })
@ -47,21 +46,22 @@ function MetamaskInpageProvider(connectionStream){
self.sendAsync = asyncProvider.sendAsync.bind(asyncProvider) self.sendAsync = asyncProvider.sendAsync.bind(asyncProvider)
} }
MetamaskInpageProvider.prototype.send = function(payload){ MetamaskInpageProvider.prototype.send = function (payload) {
const self = this const self = this
let selectedAddress
var result = null var result = null
switch (payload.method) { switch (payload.method) {
case 'eth_accounts': case 'eth_accounts':
// read from localStorage // read from localStorage
var selectedAddress = self.publicConfigStore.get('selectedAddress') selectedAddress = self.publicConfigStore.get('selectedAddress')
result = selectedAddress ? [selectedAddress] : [] result = selectedAddress ? [selectedAddress] : []
break break
case 'eth_coinbase': case 'eth_coinbase':
// read from localStorage // read from localStorage
var selectedAddress = self.publicConfigStore.get('selectedAddress') selectedAddress = self.publicConfigStore.get('selectedAddress')
result = selectedAddress || '0x0000000000000000000000000000000000000000' result = selectedAddress || '0x0000000000000000000000000000000000000000'
break break
@ -79,24 +79,24 @@ MetamaskInpageProvider.prototype.send = function(payload){
} }
} }
MetamaskInpageProvider.prototype.sendAsync = function(){ MetamaskInpageProvider.prototype.sendAsync = function () {
throw new Error('MetamaskInpageProvider - sendAsync not overwritten') throw new Error('MetamaskInpageProvider - sendAsync not overwritten')
} }
MetamaskInpageProvider.prototype.isConnected = function(){ MetamaskInpageProvider.prototype.isConnected = function () {
return true return true
} }
// util // util
function createSyncProvider(providerConfig){ function createSyncProvider (providerConfig) {
providerConfig = providerConfig || {} providerConfig = providerConfig || {}
var syncProviderUrl = undefined let syncProviderUrl
if (providerConfig.rpcTarget) { if (providerConfig.rpcTarget) {
syncProviderUrl = providerConfig.rpcTarget syncProviderUrl = providerConfig.rpcTarget
} else { } else {
switch(providerConfig.type) { switch (providerConfig.type) {
case 'testnet': case 'testnet':
syncProviderUrl = MetamaskConfig.network.testnet syncProviderUrl = MetamaskConfig.network.testnet
break break
@ -110,14 +110,14 @@ function createSyncProvider(providerConfig){
return new HttpProvider(syncProviderUrl) return new HttpProvider(syncProviderUrl)
} }
function remoteStoreWithLocalStorageCache(storageKey){ function remoteStoreWithLocalStorageCache (storageKey) {
// read local cache // read local cache
var initState = JSON.parse(localStorage[storageKey] || '{}') var initState = JSON.parse(localStorage[storageKey] || '{}')
var store = new RemoteStore(initState) var store = new RemoteStore(initState)
// cache the latest state locally // cache the latest state locally
store.subscribe(function(state){ store.subscribe(function (state) {
localStorage[storageKey] = JSON.stringify(state) localStorage[storageKey] = JSON.stringify(state)
}) })
return store return store
} }

@ -3,10 +3,9 @@ const inherits = require('util').inherits
module.exports = LocalMessageDuplexStream module.exports = LocalMessageDuplexStream
inherits(LocalMessageDuplexStream, Duplex) inherits(LocalMessageDuplexStream, Duplex)
function LocalMessageDuplexStream(opts){ function LocalMessageDuplexStream (opts) {
Duplex.call(this, { Duplex.call(this, {
objectMode: true, objectMode: true,
}) })
@ -21,19 +20,19 @@ function LocalMessageDuplexStream(opts){
// private // private
LocalMessageDuplexStream.prototype._onMessage = function(event){ LocalMessageDuplexStream.prototype._onMessage = function (event) {
var msg = event.data var msg = event.data
// console.log('LocalMessageDuplexStream ('+this._name+') - heard message...', event) // console.log('LocalMessageDuplexStream ('+this._name+') - heard message...', event)
// validate message // validate message
if (event.origin !== location.origin) return //console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (event.origin !== location.origin) ') if (event.origin !== location.origin) return // console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (event.origin !== location.origin) ')
if (typeof msg !== 'object') return //console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (typeof msg !== "object") ') if (typeof msg !== 'object') return // console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (typeof msg !== "object") ')
if (msg.target !== this._name) return //console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (msg.target !== this._name) ', msg.target, this._name) if (msg.target !== this._name) return // console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (msg.target !== this._name) ', msg.target, this._name)
if (!msg.data) return //console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (!msg.data) ') if (!msg.data) return // console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (!msg.data) ')
// console.log('LocalMessageDuplexStream ('+this._name+') - accepted', msg.data) // console.log('LocalMessageDuplexStream ('+this._name+') - accepted', msg.data)
// forward message // forward message
try { try {
this.push(msg.data) this.push(msg.data)
} catch(err) { } catch (err) {
this.emit('error', err) this.emit('error', err)
} }
} }
@ -42,7 +41,7 @@ LocalMessageDuplexStream.prototype._onMessage = function(event){
LocalMessageDuplexStream.prototype._read = noop LocalMessageDuplexStream.prototype._read = noop
LocalMessageDuplexStream.prototype._write = function(data, encoding, cb){ LocalMessageDuplexStream.prototype._write = function (data, encoding, cb) {
// console.log('LocalMessageDuplexStream ('+this._name+') - sending message...') // console.log('LocalMessageDuplexStream ('+this._name+') - sending message...')
var message = { var message = {
target: this._target, target: this._target,
@ -54,4 +53,4 @@ LocalMessageDuplexStream.prototype._write = function(data, encoding, cb){
// util // util
function noop(){} function noop () {}

@ -1,50 +1,50 @@
module.exports = new MessageManager() module.exports = new MessageManager()
function MessageManager(opts) { function MessageManager (opts) {
this.messages = [] this.messages = []
} }
MessageManager.prototype.getMsgList = function() { MessageManager.prototype.getMsgList = function () {
return this.messages return this.messages
} }
MessageManager.prototype.unconfirmedMsgs = function() { MessageManager.prototype.unconfirmedMsgs = function () {
var messages = this.getMsgList() var messages = this.getMsgList()
return messages.filter(msg => msg.status === 'unconfirmed') return messages.filter(msg => msg.status === 'unconfirmed')
.reduce((result, msg) => { result[msg.id] = msg; return result }, {}) .reduce((result, msg) => { result[msg.id] = msg; return result }, {})
} }
MessageManager.prototype._saveMsgList = function(msgList) { MessageManager.prototype._saveMsgList = function (msgList) {
this.messages = msgList this.messages = msgList
} }
MessageManager.prototype.addMsg = function(msg) { MessageManager.prototype.addMsg = function (msg) {
var messages = this.getMsgList() var messages = this.getMsgList()
messages.push(msg) messages.push(msg)
this._saveMsgList(messages) this._saveMsgList(messages)
} }
MessageManager.prototype.getMsg = function(msgId) { MessageManager.prototype.getMsg = function (msgId) {
var messages = this.getMsgList() var messages = this.getMsgList()
var matching = messages.filter(msg => msg.id === msgId) var matching = messages.filter(msg => msg.id === msgId)
return matching.length > 0 ? matching[0] : null return matching.length > 0 ? matching[0] : null
} }
MessageManager.prototype.confirmMsg = function(msgId) { MessageManager.prototype.confirmMsg = function (msgId) {
this._setMsgStatus(msgId, 'confirmed') this._setMsgStatus(msgId, 'confirmed')
} }
MessageManager.prototype.rejectMsg = function(msgId) { MessageManager.prototype.rejectMsg = function (msgId) {
this._setMsgStatus(msgId, 'rejected') this._setMsgStatus(msgId, 'rejected')
} }
MessageManager.prototype._setMsgStatus = function(msgId, status) { MessageManager.prototype._setMsgStatus = function (msgId, status) {
var msg = this.getMsg(msgId) var msg = this.getMsg(msgId)
if (msg) msg.status = status if (msg) msg.status = status
this.updateMsg(msg) this.updateMsg(msg)
} }
MessageManager.prototype.updateMsg = function(msg) { MessageManager.prototype.updateMsg = function (msg) {
var messages = this.getMsgList() var messages = this.getMsgList()
var found, index var found, index
messages.forEach((otherMsg, i) => { messages.forEach((otherMsg, i) => {

@ -10,13 +10,12 @@ module.exports = {
setupListeners() setupListeners()
function setupListeners(){ function setupListeners () {
// guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236 // guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236
if (!chrome.notifications) return console.error('Chrome notifications API missing...') if (!chrome.notifications) return console.error('Chrome notifications API missing...')
// notification button press // notification button press
chrome.notifications.onButtonClicked.addListener(function(notificationId, buttonIndex){ chrome.notifications.onButtonClicked.addListener(function (notificationId, buttonIndex) {
var handlers = notificationHandlers[notificationId] var handlers = notificationHandlers[notificationId]
if (buttonIndex === 0) { if (buttonIndex === 0) {
handlers.confirm() handlers.confirm()
@ -27,14 +26,13 @@ function setupListeners(){
}) })
// notification teardown // notification teardown
chrome.notifications.onClosed.addListener(function(notificationId){ chrome.notifications.onClosed.addListener(function (notificationId) {
delete notificationHandlers[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 // guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236
if (!chrome.notifications) return console.error('Chrome notifications API missing...') 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.'
@ -46,18 +44,17 @@ function createUnlockRequestNotification(opts){
title: opts.title, title: opts.title,
message: message, message: message,
}) })
} }
function createTxNotification(opts){ function createTxNotification (opts) {
// guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236 // guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236
if (!chrome.notifications) return console.error('Chrome notifications API missing...') 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),
'from: '+uiUtils.addressSummary(opts.txParams.from), 'from: ' + uiUtils.addressSummary(opts.txParams.from),
'value: '+uiUtils.formatBalance(opts.txParams.value), 'value: ' + uiUtils.formatBalance(opts.txParams.value),
'data: '+uiUtils.dataSize(opts.txParams.data), 'data: ' + uiUtils.dataSize(opts.txParams.data),
].join('\n') ].join('\n')
var id = createId() var id = createId()
@ -69,9 +66,9 @@ function createTxNotification(opts){
message: message, message: message,
buttons: [{ buttons: [{
title: 'confirm', title: 'confirm',
},{ }, {
title: 'cancel', title: 'cancel',
}] }],
}) })
notificationHandlers[id] = { notificationHandlers[id] = {
confirm: opts.confirm, confirm: opts.confirm,
@ -79,13 +76,13 @@ function createTxNotification(opts){
} }
} }
function createMsgNotification(opts){ function createMsgNotification (opts) {
// guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236 // guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236
if (!chrome.notifications) return console.error('Chrome notifications API missing...') 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),
'message:\n'+opts.msgParams.data, 'message:\n' + opts.msgParams.data,
].join('\n') ].join('\n')
var id = createId() var id = createId()
@ -97,12 +94,12 @@ function createMsgNotification(opts){
message: message, message: message,
buttons: [{ buttons: [{
title: 'confirm', title: 'confirm',
},{ }, {
title: 'cancel', title: 'cancel',
}] }],
}) })
notificationHandlers[id] = { notificationHandlers[id] = {
confirm: opts.confirm, confirm: opts.confirm,
cancel: opts.cancel, cancel: opts.cancel,
} }
} }

@ -2,11 +2,10 @@ const through = require('through2')
module.exports = ObjectMultiplex module.exports = ObjectMultiplex
function ObjectMultiplex (opts) {
function ObjectMultiplex(opts){
opts = opts || {} opts = opts || {}
// create multiplexer // create multiplexer
var mx = through.obj(function(chunk, enc, cb) { var mx = through.obj(function (chunk, enc, cb) {
var name = chunk.name var name = chunk.name
var data = chunk.data var data = chunk.data
var substream = mx.streams[name] var substream = mx.streams[name]
@ -19,19 +18,19 @@ function ObjectMultiplex(opts){
}) })
mx.streams = {} mx.streams = {}
// create substreams // create substreams
mx.createStream = function(name) { mx.createStream = function (name) {
var substream = mx.streams[name] = through.obj(function(chunk, enc, cb) { var substream = mx.streams[name] = through.obj(function (chunk, enc, cb) {
mx.push({ mx.push({
name: name, name: name,
data: chunk, data: chunk,
}) })
return cb() return cb()
}) })
mx.on('end', function() { mx.on('end', function () {
return substream.emit('end') return substream.emit('end')
}) })
if (opts.error) { if (opts.error) {
mx.on('error', function() { mx.on('error', function () {
return substream.emit('error') return substream.emit('error')
}) })
} }

@ -3,10 +3,9 @@ const inherits = require('util').inherits
module.exports = PortDuplexStream module.exports = PortDuplexStream
inherits(PortDuplexStream, Duplex) inherits(PortDuplexStream, Duplex)
function PortDuplexStream(port){ function PortDuplexStream (port) {
Duplex.call(this, { Duplex.call(this, {
objectMode: true, objectMode: true,
}) })
@ -17,7 +16,7 @@ function PortDuplexStream(port){
// private // private
PortDuplexStream.prototype._onMessage = function(msg){ PortDuplexStream.prototype._onMessage = function (msg) {
if (Buffer.isBuffer(msg)) { if (Buffer.isBuffer(msg)) {
delete msg._isBuffer delete msg._isBuffer
var data = new Buffer(msg) var data = new Buffer(msg)
@ -29,11 +28,11 @@ PortDuplexStream.prototype._onMessage = function(msg){
} }
} }
PortDuplexStream.prototype._onDisconnect = function(){ PortDuplexStream.prototype._onDisconnect = function () {
try { try {
// this.end() // this.end()
this.emit('close') this.emit('close')
} catch(err){ } catch (err) {
this.emit('error', err) this.emit('error', err)
} }
} }
@ -42,7 +41,7 @@ PortDuplexStream.prototype._onDisconnect = function(){
PortDuplexStream.prototype._read = noop PortDuplexStream.prototype._read = noop
PortDuplexStream.prototype._write = function(msg, encoding, cb){ PortDuplexStream.prototype._write = function (msg, encoding, cb) {
try { try {
if (Buffer.isBuffer(msg)) { if (Buffer.isBuffer(msg)) {
var data = msg.toJSON() var data = msg.toJSON()
@ -54,7 +53,7 @@ PortDuplexStream.prototype._write = function(msg, encoding, cb){
this._port.postMessage(msg) this._port.postMessage(msg)
} }
cb() cb()
} catch(err){ } catch (err) {
console.error(err) console.error(err)
// this.emit('error', err) // this.emit('error', err)
cb(new Error('PortDuplexStream - disconnected')) cb(new Error('PortDuplexStream - disconnected'))
@ -63,4 +62,4 @@ PortDuplexStream.prototype._write = function(msg, encoding, cb){
// util // util
function noop(){} function noop () {}

@ -6,32 +6,32 @@ module.exports = {
RemoteStore: RemoteStore, RemoteStore: RemoteStore,
} }
function BaseStore(initState){ function BaseStore (initState) {
this._state = initState || {} this._state = initState || {}
this._subs = [] this._subs = []
} }
BaseStore.prototype.set = function(key, value){ BaseStore.prototype.set = function (key, value) {
throw Error('Not implemented.') throw Error('Not implemented.')
} }
BaseStore.prototype.get = function(key){ BaseStore.prototype.get = function (key) {
return this._state[key] return this._state[key]
} }
BaseStore.prototype.subscribe = function(fn){ BaseStore.prototype.subscribe = function (fn) {
this._subs.push(fn) this._subs.push(fn)
var unsubscribe = this.unsubscribe.bind(this, fn) var unsubscribe = this.unsubscribe.bind(this, fn)
return unsubscribe return unsubscribe
} }
BaseStore.prototype.unsubscribe = function(fn){ BaseStore.prototype.unsubscribe = function (fn) {
var index = this._subs.indexOf(fn) var index = this._subs.indexOf(fn)
if (index !== -1) this._subs.splice(index, 1) if (index !== -1) this._subs.splice(index, 1)
} }
BaseStore.prototype._emitUpdates = function(state){ BaseStore.prototype._emitUpdates = function (state) {
this._subs.forEach(function(handler){ this._subs.forEach(function (handler) {
handler(state) handler(state)
}) })
} }
@ -41,16 +41,16 @@ BaseStore.prototype._emitUpdates = function(state){
// //
inherits(HostStore, BaseStore) inherits(HostStore, BaseStore)
function HostStore(initState, opts){ function HostStore (initState, opts) {
BaseStore.call(this, initState) BaseStore.call(this, initState)
} }
HostStore.prototype.set = function(key, value){ HostStore.prototype.set = function (key, value) {
this._state[key] = value this._state[key] = value
process.nextTick(this._emitUpdates.bind(this, this._state)) process.nextTick(this._emitUpdates.bind(this, this._state))
} }
HostStore.prototype.createStream = function(){ HostStore.prototype.createStream = function () {
var dnode = Dnode({ var dnode = Dnode({
// update: this._didUpdate.bind(this), // update: this._didUpdate.bind(this),
}) })
@ -58,8 +58,8 @@ HostStore.prototype.createStream = function(){
return dnode return dnode
} }
HostStore.prototype._didConnect = function(remote){ HostStore.prototype._didConnect = function (remote) {
this.subscribe(function(state){ this.subscribe(function (state) {
remote.update(state) remote.update(state)
}) })
remote.update(this._state) remote.update(this._state)
@ -70,16 +70,16 @@ HostStore.prototype._didConnect = function(remote){
// //
inherits(RemoteStore, BaseStore) inherits(RemoteStore, BaseStore)
function RemoteStore(initState, opts){ function RemoteStore (initState, opts) {
BaseStore.call(this, initState) BaseStore.call(this, initState)
this._remote = null this._remote = null
} }
RemoteStore.prototype.set = function(key, value){ RemoteStore.prototype.set = function (key, value) {
this._remote.set(key, value) this._remote.set(key, value)
} }
RemoteStore.prototype.createStream = function(){ RemoteStore.prototype.createStream = function () {
var dnode = Dnode({ var dnode = Dnode({
update: this._didUpdate.bind(this), update: this._didUpdate.bind(this),
}) })
@ -87,11 +87,11 @@ RemoteStore.prototype.createStream = function(){
return dnode return dnode
} }
RemoteStore.prototype._didConnect = function(remote){ RemoteStore.prototype._didConnect = function (remote) {
this._remote = remote this._remote = remote
} }
RemoteStore.prototype._didUpdate = function(state){ RemoteStore.prototype._didUpdate = function (state) {
this._state = state this._state = state
this._emitUpdates(state) this._emitUpdates(state)
} }

@ -1,36 +1,35 @@
const Through = require('through2') const Through = require('through2')
const ObjectMultiplex = require('./obj-multiplex') const ObjectMultiplex = require('./obj-multiplex')
module.exports = { module.exports = {
jsonParseStream: jsonParseStream, jsonParseStream: jsonParseStream,
jsonStringifyStream: jsonStringifyStream, jsonStringifyStream: jsonStringifyStream,
setupMultiplex: setupMultiplex, setupMultiplex: setupMultiplex,
} }
function jsonParseStream(){ function jsonParseStream () {
return Through.obj(function(serialized, encoding, cb){ return Through.obj(function (serialized, encoding, cb) {
this.push(JSON.parse(serialized)) this.push(JSON.parse(serialized))
cb() cb()
}) })
} }
function jsonStringifyStream(){ function jsonStringifyStream () {
return Through.obj(function(obj, encoding, cb){ return Through.obj(function (obj, encoding, cb) {
this.push(JSON.stringify(obj)) this.push(JSON.stringify(obj))
cb() cb()
}) })
} }
function setupMultiplex(connectionStream){ function setupMultiplex (connectionStream) {
var mx = ObjectMultiplex() var mx = ObjectMultiplex()
connectionStream.pipe(mx).pipe(connectionStream) connectionStream.pipe(mx).pipe(connectionStream)
mx.on('error', function(err) { mx.on('error', function (err) {
console.error(err) console.error(err)
}) })
connectionStream.on('error', function(err) { connectionStream.on('error', function (err) {
console.error(err) console.error(err)
mx.destroy() mx.destroy()
}) })
return mx return mx
} }

@ -1,7 +1,7 @@
module.exports = { module.exports = {
version: 2, version: 2,
migrate: function(data) { migrate: function (data) {
try { try {
if (data.config.provider.type === 'etherscan') { if (data.config.provider.type === 'etherscan') {
data.config.provider.type = 'rpc' data.config.provider.type = 'rpc'
@ -9,5 +9,5 @@ module.exports = {
} }
} catch (e) {} } catch (e) {}
return data return data
} },
} }

@ -4,12 +4,12 @@ var newTestRpc = 'https://testrpc.metamask.io/'
module.exports = { module.exports = {
version: 3, version: 3,
migrate: function(data) { migrate: function (data) {
try { try {
if (data.config.provider.rpcTarget === oldTestRpc) { if (data.config.provider.rpcTarget === oldTestRpc) {
data.config.provider.rpcTarget = newTestRpc data.config.provider.rpcTarget = newTestRpc
} }
} catch (e) {} } catch (e) {}
return data return data
} },
} }

@ -1,22 +1,22 @@
module.exports = { module.exports = {
version: 4, version: 4,
migrate: function(data) { migrate: function (data) {
try { try {
if (data.config.provider.type !== 'rpc') return data if (data.config.provider.type !== 'rpc') return data
switch (data.config.provider.rpcTarget) { switch (data.config.provider.rpcTarget) {
case 'https://testrpc.metamask.io/': case 'https://testrpc.metamask.io/':
data.config.provider = { data.config.provider = {
type: 'testnet' type: 'testnet',
} }
break break
case 'https://rpc.metamask.io/': case 'https://rpc.metamask.io/':
data.config.provider = { data.config.provider = {
type: 'mainnet' type: 'mainnet',
} }
break break
} }
} catch (_) {} } catch (_) {}
return data return data
} },
} }

@ -19,7 +19,7 @@ async.parallel({
accountManager: connectToAccountManager, accountManager: connectToAccountManager,
}, setupApp) }, setupApp)
function connectToAccountManager(cb){ function connectToAccountManager (cb) {
// setup communication with background // setup communication with background
var pluginPort = chrome.runtime.connect({name: 'popup'}) var pluginPort = chrome.runtime.connect({name: 'popup'})
var portStream = new PortStream(pluginPort) var portStream = new PortStream(pluginPort)
@ -30,7 +30,7 @@ function connectToAccountManager(cb){
setupWeb3Connection(mx.createStream('provider')) setupWeb3Connection(mx.createStream('provider'))
} }
function setupWeb3Connection(stream){ function setupWeb3Connection (stream) {
var remoteProvider = new StreamProvider() var remoteProvider = new StreamProvider()
remoteProvider.pipe(stream).pipe(remoteProvider) remoteProvider.pipe(stream).pipe(remoteProvider)
stream.on('error', console.error.bind(console)) stream.on('error', console.error.bind(console))
@ -38,23 +38,23 @@ function setupWeb3Connection(stream){
global.web3 = new Web3(remoteProvider) global.web3 = new Web3(remoteProvider)
} }
function setupControllerConnection(stream, cb){ function setupControllerConnection (stream, cb) {
var eventEmitter = new EventEmitter() var eventEmitter = new EventEmitter()
var background = Dnode({ var background = Dnode({
sendUpdate: function(state){ sendUpdate: function (state) {
eventEmitter.emit('update', state) eventEmitter.emit('update', state)
}, },
}) })
stream.pipe(background).pipe(stream) stream.pipe(background).pipe(stream)
background.once('remote', function(accountManager){ background.once('remote', function (accountManager) {
// setup push events // setup push events
accountManager.on = eventEmitter.on.bind(eventEmitter) accountManager.on = eventEmitter.on.bind(eventEmitter)
cb(null, accountManager) cb(null, accountManager)
}) })
} }
function getCurrentDomain(cb){ function getCurrentDomain (cb) {
chrome.tabs.query({active: true, currentWindow: true}, function(results){ chrome.tabs.query({active: true, currentWindow: true}, function (results) {
var activeTab = results[0] var activeTab = results[0]
var currentUrl = activeTab && activeTab.url var currentUrl = activeTab && activeTab.url
var currentDomain = url.parse(currentUrl).host var currentDomain = url.parse(currentUrl).host
@ -65,16 +65,15 @@ function getCurrentDomain(cb){
}) })
} }
function setupApp(err, opts){ function setupApp (err, opts) {
if (err) { if (err) {
alert(err.stack) alert(err.stack)
throw err throw err
return
} }
var container = document.getElementById('app-content') var container = document.getElementById('app-content')
var app = MetaMaskUi({ MetaMaskUi({
container: container, container: container,
accountManager: opts.accountManager, accountManager: opts.accountManager,
currentDomain: opts.currentDomain, currentDomain: opts.currentDomain,

@ -0,0 +1,3 @@
machine:
node:
version: 6.0.0

@ -9,6 +9,9 @@ var sourcemaps = require('gulp-sourcemaps')
var assign = require('lodash.assign') var assign = require('lodash.assign')
var livereload = require('gulp-livereload') var livereload = require('gulp-livereload')
var del = require('del') var del = require('del')
var eslint = require('gulp-eslint')
var fs = require('fs')
var path = require('path')
// browser reload // browser reload
@ -49,6 +52,25 @@ gulp.task('copy:watch', function(){
gulp.watch(['./app/{_locales,images}/*', './app/scripts/chromereload.js', './app/*.{html,json}'], gulp.series('copy')) gulp.watch(['./app/{_locales,images}/*', './app/scripts/chromereload.js', './app/*.{html,json}'], gulp.series('copy'))
}) })
// lint js
gulp.task('lint', function () {
// Ignoring node_modules, dist, and docs folders:
return gulp.src(['app/**/*.js', 'ui/**/*.js', '!node_modules/**', '!dist/**', '!docs/**', '!app/scripts/chromereload.js'])
.pipe(eslint(fs.readFileSync(path.join(__dirname, '.eslintrc'))))
// eslint.format() outputs the lint results to the console.
// Alternatively use eslint.formatEach() (see Docs).
.pipe(eslint.format())
// To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failAfterError last.
.pipe(eslint.failAfterError())
});
/*
gulp.task('default', ['lint'], function () {
// This will only run if the lint task is successful...
});
*/
// build js // build js

@ -36,6 +36,7 @@
"eth-store": "^1.1.0", "eth-store": "^1.1.0",
"ethereumjs-tx": "^1.0.0", "ethereumjs-tx": "^1.0.0",
"ethereumjs-util": "^4.4.0", "ethereumjs-util": "^4.4.0",
"gulp-eslint": "^2.0.0",
"hat": "0.0.3", "hat": "0.0.3",
"identicon.js": "^1.2.1", "identicon.js": "^1.2.1",
"inject-css": "^0.1.1", "inject-css": "^0.1.1",
@ -68,6 +69,7 @@
"xtend": "^4.0.1" "xtend": "^4.0.1"
}, },
"devDependencies": { "devDependencies": {
"babel-eslint": "^6.0.5",
"babel-preset-es2015": "^6.6.0", "babel-preset-es2015": "^6.6.0",
"babel-register": "^6.7.2", "babel-register": "^6.7.2",
"babelify": "^7.2.0", "babelify": "^7.2.0",
@ -87,6 +89,7 @@
"jshint-stylish": "~0.1.5", "jshint-stylish": "~0.1.5",
"lodash.assign": "^4.0.6", "lodash.assign": "^4.0.6",
"mocha": "^2.4.5", "mocha": "^2.4.5",
"mocha-eslint": "^2.1.1",
"mocha-jsdom": "^1.1.0", "mocha-jsdom": "^1.1.0",
"mocha-sinon": "^1.1.5", "mocha-sinon": "^1.1.5",
"sinon": "^1.17.3", "sinon": "^1.17.3",

@ -0,0 +1,9 @@
// LINTING:
const lint = require('mocha-eslint');
const lintPaths = ['app/**/*.js', 'ui/**/*.js', '!node_modules/**', '!dist/**', '!docs/**', '!app/scripts/chromereload.js']
const lintOptions = {
strict: true,
}
lint(lintPaths, lintOptions)

@ -17,7 +17,7 @@ const EditableLabel = require('./components/editable-label')
module.exports = connect(mapStateToProps)(AccountDetailScreen) module.exports = connect(mapStateToProps)(AccountDetailScreen)
function mapStateToProps(state) { function mapStateToProps (state) {
return { return {
identities: state.metamask.identities, identities: state.metamask.identities,
accounts: state.metamask.accounts, accounts: state.metamask.accounts,
@ -31,17 +31,15 @@ function mapStateToProps(state) {
} }
inherits(AccountDetailScreen, Component) inherits(AccountDetailScreen, Component)
function AccountDetailScreen() { function AccountDetailScreen () {
Component.call(this) Component.call(this)
} }
AccountDetailScreen.prototype.render = function() { AccountDetailScreen.prototype.render = function () {
var props = this.props var props = this.props
var selected = props.address || Object.keys(props.accounts)[0] var selected = props.address || Object.keys(props.accounts)[0]
var identity = props.identities[selected] var identity = props.identities[selected]
var account = props.accounts[selected] var account = props.accounts[selected]
var accountDetail = props.accountDetail
var transactions = props.transactions
return ( return (
@ -88,7 +86,7 @@ AccountDetailScreen.prototype.render = function() {
style: { style: {
height: '62px', height: '62px',
paddingTop: '8px', paddingTop: '8px',
} },
}, [ }, [
h(EditableLabel, { h(EditableLabel, {
textValue: identity ? identity.name : '', textValue: identity ? identity.name : '',
@ -101,7 +99,7 @@ AccountDetailScreen.prototype.render = function() {
}, [ }, [
// What is shown when not editing + edit text: // What is shown when not editing + edit text:
h('label.editing-label',[h('.edit-text','edit')]), h('label.editing-label', [h('.edit-text', 'edit')]),
h('h2.font-medium.color-forest', {name: 'edit'}, identity && identity.name), h('h2.font-medium.color-forest', {name: 'edit'}, identity && identity.name),
]), ]),
]), ]),
@ -124,7 +122,7 @@ AccountDetailScreen.prototype.render = function() {
h('img.cursor-pointer.color-orange', { h('img.cursor-pointer.color-orange', {
src: 'images/copy.svg', src: 'images/copy.svg',
onClick: () => copyToClipboard(ethUtil.toChecksumAddress(selected)), onClick: () => copyToClipboard(ethUtil.toChecksumAddress(selected)),
style:{ style: {
margin: '0px 5px', margin: '0px 5px',
}, },
}), }),
@ -179,7 +177,7 @@ AccountDetailScreen.prototype.render = function() {
) )
} }
AccountDetailScreen.prototype.subview = function() { AccountDetailScreen.prototype.subview = function () {
var subview var subview
try { try {
subview = this.props.accountDetail.subview subview = this.props.accountDetail.subview
@ -198,7 +196,7 @@ AccountDetailScreen.prototype.subview = function() {
} }
} }
AccountDetailScreen.prototype.transactionList = function() { AccountDetailScreen.prototype.transactionList = function () {
const { transactions, unconfTxs, unconfMsgs, address, network } = this.props const { transactions, unconfTxs, unconfMsgs, address, network } = this.props
var txsToRender = transactions var txsToRender = transactions
@ -214,18 +212,18 @@ AccountDetailScreen.prototype.transactionList = function() {
network, network,
unconfTxs, unconfTxs,
unconfMsgs, unconfMsgs,
viewPendingTx:(txId) => { viewPendingTx: (txId) => {
this.props.dispatch(actions.viewPendingTx(txId)) this.props.dispatch(actions.viewPendingTx(txId))
} },
}) })
} }
AccountDetailScreen.prototype.navigateToAccounts = function(event){ AccountDetailScreen.prototype.navigateToAccounts = function (event) {
event.stopPropagation() event.stopPropagation()
this.props.dispatch(actions.showAccountsPage()) this.props.dispatch(actions.showAccountsPage())
} }
AccountDetailScreen.prototype.requestAccountExport = function() { AccountDetailScreen.prototype.requestAccountExport = function () {
this.props.dispatch(actions.requestExportAccount()) this.props.dispatch(actions.requestExportAccount())
} }

@ -9,18 +9,15 @@ const Identicon = require('../components/identicon')
module.exports = NewComponent module.exports = NewComponent
inherits(NewComponent, Component) inherits(NewComponent, Component)
function NewComponent() { function NewComponent () {
Component.call(this) Component.call(this)
} }
NewComponent.prototype.render = function() { NewComponent.prototype.render = function () {
const identity = this.props.identity const identity = this.props.identity
var mayBeFauceting = identity.mayBeFauceting
var isSelected = this.props.selectedAddress === identity.address var isSelected = this.props.selectedAddress === identity.address
var account = this.props.accounts[identity.address] var account = this.props.accounts[identity.address]
var isFauceting = mayBeFauceting && account.balance === '0x0'
const selectedClass = isSelected ? '.selected' : '' const selectedClass = isSelected ? '.selected' : ''
return ( return (
@ -35,7 +32,7 @@ NewComponent.prototype.render = function() {
h('.identicon-wrapper.flex-column.flex-center.select-none', [ h('.identicon-wrapper.flex-column.flex-center.select-none', [
this.pendingOrNot(), this.pendingOrNot(),
h(Identicon, { h(Identicon, {
address: identity.address address: identity.address,
}), }),
]), ]),
@ -70,16 +67,19 @@ NewComponent.prototype.render = function() {
event.preventDefault() event.preventDefault()
copyToClipboard(ethUtil.toChecksumAddress(identity.address)) copyToClipboard(ethUtil.toChecksumAddress(identity.address))
}, },
<<<<<<< HEAD
style:{ style:{
margin: '0px 5px', margin: '0px 5px',
}, },
=======
>>>>>>> master
}), }),
]), ]),
]) ])
) )
} }
NewComponent.prototype.pendingOrNot = function() { NewComponent.prototype.pendingOrNot = function () {
const pending = this.props.pending const pending = this.props.pending
if (pending.length === 0) return null if (pending.length === 0) return null
return h('.pending-dot', pending.length) return h('.pending-dot', pending.length)

@ -2,7 +2,6 @@ const inherits = require('util').inherits
const Component = require('react').Component const Component = require('react').Component
const h = require('react-hyperscript') const h = require('react-hyperscript')
const connect = require('react-redux').connect const connect = require('react-redux').connect
const extend = require('xtend')
const actions = require('../actions') const actions = require('../actions')
const valuesFor = require('../util').valuesFor const valuesFor = require('../util').valuesFor
const findDOMNode = require('react-dom').findDOMNode const findDOMNode = require('react-dom').findDOMNode
@ -10,8 +9,7 @@ const AccountPanel = require('./account-panel')
module.exports = connect(mapStateToProps)(AccountsScreen) module.exports = connect(mapStateToProps)(AccountsScreen)
function mapStateToProps (state) {
function mapStateToProps(state) {
const pendingTxs = valuesFor(state.metamask.unconfTxs) const pendingTxs = valuesFor(state.metamask.unconfTxs)
const pendingMsgs = valuesFor(state.metamask.unconfMsgs) const pendingMsgs = valuesFor(state.metamask.unconfMsgs)
const pending = pendingTxs.concat(pendingMsgs) const pending = pendingTxs.concat(pendingMsgs)
@ -28,12 +26,11 @@ function mapStateToProps(state) {
} }
inherits(AccountsScreen, Component) inherits(AccountsScreen, Component)
function AccountsScreen() { function AccountsScreen () {
Component.call(this) Component.call(this)
} }
AccountsScreen.prototype.render = function () {
AccountsScreen.prototype.render = function() {
var state = this.props var state = this.props
var identityList = valuesFor(state.identities) var identityList = valuesFor(state.identities)
var unconfTxList = valuesFor(state.unconfTxs) var unconfTxList = valuesFor(state.unconfTxs)
@ -63,48 +60,48 @@ AccountsScreen.prototype.render = function() {
height: '418px', height: '418px',
overflowY: 'auto', overflowY: 'auto',
overflowX: 'hidden', overflowX: 'hidden',
} },
}, },
[ [
identityList.map((identity) => { identityList.map((identity) => {
const pending = this.props.pending.filter((txOrMsg) => { const pending = this.props.pending.filter((txOrMsg) => {
if ('txParams' in txOrMsg) { if ('txParams' in txOrMsg) {
return txOrMsg.txParams.from === identity.address return txOrMsg.txParams.from === identity.address
} else if ('msgParams' in txOrMsg) { } else if ('msgParams' in txOrMsg) {
return txOrMsg.msgParams.from === identity.address return txOrMsg.msgParams.from === identity.address
} else { } else {
return false return false
} }
}) })
return h(AccountPanel, { return h(AccountPanel, {
key: `acct-panel-${identity.address}`, key: `acct-panel-${identity.address}`,
identity, identity,
selectedAddress: this.props.selectedAddress, selectedAddress: this.props.selectedAddress,
accounts: this.props.accounts, accounts: this.props.accounts,
onShowDetail: this.onShowDetail.bind(this), onShowDetail: this.onShowDetail.bind(this),
pending, pending,
}) })
}), }),
h('hr.horizontal-line', {key: 'horizontal-line1'}), h('hr.horizontal-line', {key: 'horizontal-line1'}),
h('div.footer.hover-white.pointer', { h('div.footer.hover-white.pointer', {
key: 'reveal-account-bar', key: 'reveal-account-bar',
onClick:() => { onClick: () => {
actions.revealAccount() actions.revealAccount()
}, },
style: { style: {
display: 'flex', display: 'flex',
flex: '1 0 auto', flex: '1 0 auto',
height: '40px', height: '40px',
paddint: '10px', paddint: '10px',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
} },
}, [ }, [
h('i.fa.fa-plus.fa-lg', {key: ''}), h('i.fa.fa-plus.fa-lg', {key: ''}),
]),
]), ]),
]),
unconfTxList.length ? ( unconfTxList.length ? (
@ -123,7 +120,7 @@ AccountsScreen.prototype.render = function() {
} }
// If a new account was revealed, scroll to the bottom // If a new account was revealed, scroll to the bottom
AccountsScreen.prototype.componentDidUpdate = function(){ AccountsScreen.prototype.componentDidUpdate = function () {
const scrollToBottom = this.props.scrollToBottom const scrollToBottom = this.props.scrollToBottom
if (scrollToBottom) { if (scrollToBottom) {
@ -133,27 +130,27 @@ AccountsScreen.prototype.componentDidUpdate = function(){
} }
} }
AccountsScreen.prototype.navigateToConfTx = function(){ AccountsScreen.prototype.navigateToConfTx = function () {
event.stopPropagation() event.stopPropagation()
this.props.dispatch(actions.showConfTxPage()) this.props.dispatch(actions.showConfTxPage())
} }
AccountsScreen.prototype.onSelect = function(address, event){ AccountsScreen.prototype.onSelect = function (address, event) {
event.stopPropagation() event.stopPropagation()
// if already selected, deselect // if already selected, deselect
if (this.props.selectedAddress === address) address = null if (this.props.selectedAddress === address) address = null
this.props.dispatch(actions.setSelectedAddress(address)) this.props.dispatch(actions.setSelectedAddress(address))
} }
AccountsScreen.prototype.onShowDetail = function(address, event){ AccountsScreen.prototype.onShowDetail = function (address, event) {
event.stopPropagation() event.stopPropagation()
this.props.dispatch(actions.showAccountDetail(address)) this.props.dispatch(actions.showAccountDetail(address))
} }
AccountsScreen.prototype.onRevealAccount = function() { AccountsScreen.prototype.onRevealAccount = function () {
this.props.dispatch(actions.revealAccount()) this.props.dispatch(actions.revealAccount())
} }
AccountsScreen.prototype.goHome = function() { AccountsScreen.prototype.goHome = function () {
this.props.dispatch(actions.goHome()) this.props.dispatch(actions.goHome())
} }

@ -114,11 +114,11 @@ var actions = {
module.exports = actions module.exports = actions
var _accountManager = null var _accountManager = null
function _setAccountManager(accountManager){ function _setAccountManager (accountManager) {
_accountManager = accountManager _accountManager = accountManager
} }
function goHome() { function goHome () {
return { return {
type: actions.GO_HOME, type: actions.GO_HOME,
} }
@ -126,28 +126,22 @@ function goHome() {
// menu state // menu state
function toggleMenu() { function toggleMenu () {
return { return {
type: actions.TOGGLE_MENU, type: actions.TOGGLE_MENU,
} }
} }
function closeMenu() { function closeMenu () {
return { return {
type: actions.SET_MENU_STATE, type: actions.SET_MENU_STATE,
value: false, value: false,
} }
} }
function getNetworkStatus(){
return {
type: actions.getNetworkStatus,
}
}
// async actions // async actions
function tryUnlockMetamask(password) { function tryUnlockMetamask (password) {
return (dispatch) => { return (dispatch) => {
dispatch(actions.unlockInProgress()) dispatch(actions.unlockInProgress())
_accountManager.submitPassword(password, (err, selectedAccount) => { _accountManager.submitPassword(password, (err, selectedAccount) => {
@ -160,22 +154,25 @@ function tryUnlockMetamask(password) {
} }
} }
function createNewVault(password, entropy) { function createNewVault (password, entropy) {
return (dispatch) => { return (dispatch) => {
dispatch(actions.createNewVaultInProgress()) dispatch(actions.createNewVaultInProgress())
_accountManager.createNewVault(password, entropy, (err, result) => { _accountManager.createNewVault(password, entropy, (err, result) => {
if (err) {
return dispatch(actions.showWarning(err.message))
}
dispatch(actions.showNewVaultSeed(result)) dispatch(actions.showNewVaultSeed(result))
}) })
} }
} }
function revealSeedConfirmation() { function revealSeedConfirmation () {
return { return {
type: this.REVEAL_SEED_CONFIRMATION, type: this.REVEAL_SEED_CONFIRMATION,
} }
} }
function requestRevealSeed(password) { function requestRevealSeed (password) {
return (dispatch) => { return (dispatch) => {
dispatch(actions.showLoadingIndication()) dispatch(actions.showLoadingIndication())
_accountManager.tryPassword(password, (err, seed) => { _accountManager.tryPassword(password, (err, seed) => {
@ -189,7 +186,7 @@ function requestRevealSeed(password) {
} }
} }
function recoverFromSeed(password, seed) { function recoverFromSeed (password, seed) {
return (dispatch) => { return (dispatch) => {
// dispatch(actions.createNewVaultInProgress()) // dispatch(actions.createNewVaultInProgress())
dispatch(actions.showLoadingIndication()) dispatch(actions.showLoadingIndication())
@ -199,23 +196,23 @@ function recoverFromSeed(password, seed) {
var account = Object.keys(metamaskState.identities)[0] var account = Object.keys(metamaskState.identities)[0]
dispatch(actions.unlockMetamask(account)) dispatch(actions.unlockMetamask(account))
}) })
} }
} }
function showInfoPage() { function showInfoPage () {
return { return {
type: actions.SHOW_INFO_PAGE, type: actions.SHOW_INFO_PAGE,
} }
} }
function setSelectedAddress(address) { function setSelectedAddress (address) {
return (dispatch) => { return (dispatch) => {
_accountManager.setSelectedAddress(address) _accountManager.setSelectedAddress(address)
} }
} }
function revealAccount() { function revealAccount () {
return (dispatch) => { return (dispatch) => {
dispatch(actions.showLoadingIndication()) dispatch(actions.showLoadingIndication())
_accountManager.revealAccount((err) => { _accountManager.revealAccount((err) => {
@ -228,7 +225,7 @@ function revealAccount() {
} }
} }
function signMsg(msgData) { function signMsg (msgData) {
return (dispatch) => { return (dispatch) => {
dispatch(actions.showLoadingIndication()) dispatch(actions.showLoadingIndication())
@ -241,7 +238,7 @@ function signMsg(msgData) {
} }
} }
function signTx(txData) { function signTx (txData) {
return (dispatch) => { return (dispatch) => {
dispatch(actions.showLoadingIndication()) dispatch(actions.showLoadingIndication())
@ -255,7 +252,7 @@ function signTx(txData) {
} }
} }
function sendTx(txData) { function sendTx (txData) {
return (dispatch) => { return (dispatch) => {
_accountManager.approveTransaction(txData.id, (err) => { _accountManager.approveTransaction(txData.id, (err) => {
if (err) { if (err) {
@ -268,26 +265,26 @@ function sendTx(txData) {
} }
} }
function completedTx(id) { function completedTx (id) {
return { return {
type: actions.COMPLETED_TX, type: actions.COMPLETED_TX,
id, id,
} }
} }
function txError(err) { function txError (err) {
return { return {
type: actions.TRANSACTION_ERROR, type: actions.TRANSACTION_ERROR,
message: err.message, message: err.message,
} }
} }
function cancelMsg(msgData){ function cancelMsg (msgData) {
_accountManager.cancelMessage(msgData.id) _accountManager.cancelMessage(msgData.id)
return actions.completedTx(msgData.id) return actions.completedTx(msgData.id)
} }
function cancelTx(txData){ function cancelTx (txData) {
_accountManager.cancelTransaction(txData.id) _accountManager.cancelTransaction(txData.id)
return actions.completedTx(txData.id) return actions.completedTx(txData.id)
} }
@ -296,29 +293,32 @@ function cancelTx(txData){
// initialize screen // initialize screen
// //
function showCreateVault () {
function showCreateVault() {
return { return {
type: actions.SHOW_CREATE_VAULT, type: actions.SHOW_CREATE_VAULT,
} }
} }
function showRestoreVault() { function showRestoreVault () {
return { return {
type: actions.SHOW_RESTORE_VAULT, type: actions.SHOW_RESTORE_VAULT,
} }
} }
function showInitializeMenu() { function showInitializeMenu () {
return { return {
type: actions.SHOW_INIT_MENU, type: actions.SHOW_INIT_MENU,
} }
} }
function agreeToDisclaimer() { function agreeToDisclaimer () {
return (dispatch) => { return (dispatch) => {
dispatch(this.showLoadingIndication()) dispatch(this.showLoadingIndication())
_accountManager.agreeToDisclaimer((err) => { _accountManager.agreeToDisclaimer((err) => {
if (err) {
return dispatch(actions.showWarning(err.message))
}
dispatch(this.hideLoadingIndication()) dispatch(this.hideLoadingIndication())
dispatch({ dispatch({
type: this.AGREE_TO_DISCLAIMER, type: this.AGREE_TO_DISCLAIMER,
@ -327,13 +327,13 @@ function agreeToDisclaimer() {
} }
} }
function createNewVaultInProgress() { function createNewVaultInProgress () {
return { return {
type: actions.CREATE_NEW_VAULT_IN_PROGRESS, type: actions.CREATE_NEW_VAULT_IN_PROGRESS,
} }
} }
function showNewVaultSeed(seed) { function showNewVaultSeed (seed) {
return { return {
type: actions.SHOW_NEW_VAULT_SEED, type: actions.SHOW_NEW_VAULT_SEED,
value: seed, value: seed,
@ -344,48 +344,56 @@ function showNewVaultSeed(seed) {
// unlock screen // unlock screen
// //
function unlockInProgress() { function unlockInProgress () {
return { return {
type: actions.UNLOCK_IN_PROGRESS, type: actions.UNLOCK_IN_PROGRESS,
} }
} }
function unlockFailed() { function unlockFailed () {
return { return {
type: actions.UNLOCK_FAILED, type: actions.UNLOCK_FAILED,
} }
} }
function unlockMetamask(account) { function unlockMetamask (account) {
return { return {
type: actions.UNLOCK_METAMASK, type: actions.UNLOCK_METAMASK,
value: account, value: account,
} }
} }
function updateMetamaskState(newState) { function updateMetamaskState (newState) {
return { return {
type: actions.UPDATE_METAMASK_STATE, type: actions.UPDATE_METAMASK_STATE,
value: newState, value: newState,
} }
} }
function lockMetamask() { function lockMetamask () {
return (dispatch) => { return (dispatch) => {
_accountManager.setLocked((err) => { _accountManager.setLocked((err) => {
dispatch(actions.hideLoadingIndication())
if (err) {
return dispatch(actions.showWarning(err.message))
}
dispatch({ dispatch({
type: actions.LOCK_METAMASK, type: actions.LOCK_METAMASK,
}) })
dispatch(actions.hideLoadingIndication())
}) })
} }
} }
function showAccountDetail(address) { function showAccountDetail (address) {
return (dispatch) => { return (dispatch) => {
dispatch(actions.showLoadingIndication()) dispatch(actions.showLoadingIndication())
_accountManager.setSelectedAddress(address, (err, address) => { _accountManager.setSelectedAddress(address, (err, address) => {
dispatch(actions.hideLoadingIndication()) dispatch(actions.hideLoadingIndication())
if (err) {
return dispatch(actions.showWarning(err.message))
}
dispatch({ dispatch({
type: actions.SHOW_ACCOUNT_DETAIL, type: actions.SHOW_ACCOUNT_DETAIL,
value: address, value: address,
@ -394,61 +402,66 @@ function showAccountDetail(address) {
} }
} }
function backToAccountDetail(address) { function backToAccountDetail (address) {
return { return {
type: actions.BACK_TO_ACCOUNT_DETAIL, type: actions.BACK_TO_ACCOUNT_DETAIL,
value: address, value: address,
} }
} }
function clearSeedWordCache(account) { function clearSeedWordCache (account) {
return { return {
type: actions.CLEAR_SEED_WORD_CACHE, type: actions.CLEAR_SEED_WORD_CACHE,
value: account, value: account,
} }
} }
function confirmSeedWords() { function confirmSeedWords () {
return (dispatch) => { return (dispatch) => {
dispatch(actions.showLoadingIndication()) dispatch(actions.showLoadingIndication())
_accountManager.clearSeedWordCache((err, account) => { _accountManager.clearSeedWordCache((err, account) => {
dispatch(actions.hideLoadingIndication())
if (err) {
return dispatch(actions.showWarning(err.message))
}
console.log('Seed word cache cleared. ' + account) console.log('Seed word cache cleared. ' + account)
dispatch(actions.showAccountDetail(account)) dispatch(actions.showAccountDetail(account))
}) })
} }
} }
function showAccountsPage() { function showAccountsPage () {
return { return {
type: actions.SHOW_ACCOUNTS_PAGE, type: actions.SHOW_ACCOUNTS_PAGE,
} }
} }
function showConfTxPage() { function showConfTxPage () {
return { return {
type: actions.SHOW_CONF_TX_PAGE, type: actions.SHOW_CONF_TX_PAGE,
} }
} }
function nextTx() { function nextTx () {
return { return {
type: actions.NEXT_TX, type: actions.NEXT_TX,
} }
} }
function viewPendingTx(txId) { function viewPendingTx (txId) {
return { return {
type: actions.VIEW_PENDING_TX, type: actions.VIEW_PENDING_TX,
value: txId, value: txId,
} }
} }
function previousTx() { function previousTx () {
return { return {
type: actions.PREVIOUS_TX, type: actions.PREVIOUS_TX,
} }
} }
function showConfigPage(transitionForward = true) { function showConfigPage (transitionForward = true) {
return { return {
type: actions.SHOW_CONFIG_PAGE, type: actions.SHOW_CONFIG_PAGE,
value: transitionForward, value: transitionForward,
@ -459,7 +472,7 @@ function showConfigPage(transitionForward = true) {
// config // config
// //
function setRpcTarget(newRpc) { function setRpcTarget (newRpc) {
_accountManager.setRpcTarget(newRpc) _accountManager.setRpcTarget(newRpc)
return { return {
type: actions.SET_RPC_TARGET, type: actions.SET_RPC_TARGET,
@ -467,7 +480,7 @@ function setRpcTarget(newRpc) {
} }
} }
function setProviderType(type) { function setProviderType (type) {
_accountManager.setProviderType(type) _accountManager.setProviderType(type)
return { return {
type: actions.SET_PROVIDER_TYPE, type: actions.SET_PROVIDER_TYPE,
@ -475,51 +488,51 @@ function setProviderType(type) {
} }
} }
function useEtherscanProvider() { function useEtherscanProvider () {
_accountManager.useEtherscanProvider() _accountManager.useEtherscanProvider()
return { return {
type: actions.USE_ETHERSCAN_PROVIDER, type: actions.USE_ETHERSCAN_PROVIDER,
} }
} }
function showLoadingIndication() { function showLoadingIndication () {
return { return {
type: actions.SHOW_LOADING, type: actions.SHOW_LOADING,
} }
} }
function hideLoadingIndication() { function hideLoadingIndication () {
return { return {
type: actions.HIDE_LOADING, type: actions.HIDE_LOADING,
} }
} }
function displayWarning(text) { function displayWarning (text) {
return { return {
type: actions.DISPLAY_WARNING, type: actions.DISPLAY_WARNING,
value: text, value: text,
} }
} }
function hideWarning() { function hideWarning () {
return { return {
type: actions.HIDE_WARNING, type: actions.HIDE_WARNING,
} }
} }
function requestExportAccount() { function requestExportAccount () {
return { return {
type: actions.REQUEST_ACCOUNT_EXPORT, type: actions.REQUEST_ACCOUNT_EXPORT,
} }
} }
function exportAccount(address) { function exportAccount (address) {
var self = this var self = this
return function(dispatch) { return function (dispatch) {
dispatch(self.showLoadingIndication()) dispatch(self.showLoadingIndication())
_accountManager.exportAccount(address, function(err, result) { _accountManager.exportAccount(address, function (err, result) {
dispatch(self.hideLoadingIndication()) dispatch(self.hideLoadingIndication())
if (err) { if (err) {
@ -532,14 +545,14 @@ function exportAccount(address) {
} }
} }
function showPrivateKey(key) { function showPrivateKey (key) {
return { return {
type: actions.SHOW_PRIVATE_KEY, type: actions.SHOW_PRIVATE_KEY,
value: key, value: key,
} }
} }
function saveAccountLabel(account, label) { function saveAccountLabel (account, label) {
return (dispatch) => { return (dispatch) => {
dispatch(actions.showLoadingIndication()) dispatch(actions.showLoadingIndication())
_accountManager.saveAccountLabel(account, label, (err) => { _accountManager.saveAccountLabel(account, label, (err) => {
@ -555,7 +568,7 @@ function saveAccountLabel(account, label) {
} }
} }
function showSendPage() { function showSendPage () {
return { return {
type: actions.SHOW_SEND_PAGE, type: actions.SHOW_SEND_PAGE,
} }

@ -1,10 +1,7 @@
const inherits = require('util').inherits const inherits = require('util').inherits
const React = require('react')
const Component = require('react').Component const Component = require('react').Component
const PropTypes = require('react').PropTypes
const connect = require('react-redux').connect const connect = require('react-redux').connect
const h = require('react-hyperscript') const h = require('react-hyperscript')
const extend = require('xtend')
const actions = require('./actions') const actions = require('./actions')
const ReactCSSTransitionGroup = require('react-addons-css-transition-group') const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
// init // init
@ -25,7 +22,6 @@ const ConfigScreen = require('./config')
const RevealSeedConfirmation = require('./recover-seed/confirmation') 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 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')
@ -33,11 +29,10 @@ const NetworkIndicator = require('./components/network')
module.exports = connect(mapStateToProps)(App) module.exports = connect(mapStateToProps)(App)
inherits(App, Component) inherits(App, Component)
function App() { Component.call(this) } function App () { Component.call(this) }
function mapStateToProps(state) { function mapStateToProps (state) {
return { return {
// state from plugin // state from plugin
isConfirmed: state.metamask.isConfirmed, isConfirmed: state.metamask.isConfirmed,
@ -54,9 +49,8 @@ function mapStateToProps(state) {
} }
} }
App.prototype.render = function() { App.prototype.render = function () {
var props = this.props var props = this.props
var view = props.currentView.name
var transForward = props.transForward var transForward = props.transForward
return ( return (
@ -65,7 +59,7 @@ App.prototype.render = function() {
style: { style: {
// Windows was showing a vertical scroll bar: // Windows was showing a vertical scroll bar:
overflow: 'hidden', overflow: 'hidden',
} },
}, [ }, [
h(LoadingIndicator), h(LoadingIndicator),
@ -80,7 +74,7 @@ App.prototype.render = function() {
style: { style: {
height: '380px', height: '380px',
width: '360px', width: '360px',
} },
}, [ }, [
h(ReactCSSTransitionGroup, { h(ReactCSSTransitionGroup, {
className: 'css-transition-group', className: 'css-transition-group',
@ -95,7 +89,7 @@ App.prototype.render = function() {
) )
} }
App.prototype.renderAppBar = function(){ App.prototype.renderAppBar = function () {
const props = this.props const props = this.props
const state = this.state || {} const state = this.state || {}
const isNetworkMenuOpen = state.isNetworkMenuOpen || false const isNetworkMenuOpen = state.isNetworkMenuOpen || false
@ -117,11 +111,11 @@ App.prototype.renderAppBar = function(){
h(NetworkIndicator, { h(NetworkIndicator, {
network: this.props.network, network: this.props.network,
onClick:(event) => { onClick: (event) => {
event.preventDefault() event.preventDefault()
event.stopPropagation() event.stopPropagation()
this.setState({ isNetworkMenuOpen: !isNetworkMenuOpen }) this.setState({ isNetworkMenuOpen: !isNetworkMenuOpen })
} },
}), }),
// metamask name // metamask name
@ -144,16 +138,14 @@ App.prototype.renderAppBar = function(){
) )
} }
App.prototype.renderNetworkDropdown = function() { App.prototype.renderNetworkDropdown = function () {
const props = this.props const props = this.props
const state = this.state || {} const state = this.state || {}
const isOpen = state.isNetworkMenuOpen const isOpen = state.isNetworkMenuOpen
const checked = h('i.fa.fa-check.fa-lg', { ariaHidden: true })
return h(MenuDroppo, { return h(MenuDroppo, {
isOpen, isOpen,
onClickOutside:(event) => { onClickOutside: (event) => {
this.setState({ isNetworkMenuOpen: !isOpen }) this.setState({ isNetworkMenuOpen: !isOpen })
}, },
style: { style: {
@ -173,28 +165,28 @@ App.prototype.renderNetworkDropdown = function() {
h(DropMenuItem, { h(DropMenuItem, {
label: 'Main Ethereum Network', label: 'Main Ethereum Network',
closeMenu:() => this.setState({ isNetworkMenuOpen: false }), closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
action:() => props.dispatch(actions.setProviderType('mainnet')), action: () => props.dispatch(actions.setProviderType('mainnet')),
icon: h('.menu-icon.ether-icon'), icon: h('.menu-icon.ether-icon'),
}), }),
h(DropMenuItem, { h(DropMenuItem, {
label: 'Morden Test Network', label: 'Morden Test Network',
closeMenu:() => this.setState({ isNetworkMenuOpen: false }), closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
action:() => props.dispatch(actions.setProviderType('testnet')), action: () => props.dispatch(actions.setProviderType('testnet')),
icon: h('.menu-icon.morden-icon'), icon: h('.menu-icon.morden-icon'),
}), }),
h(DropMenuItem, { h(DropMenuItem, {
label: 'Localhost 8545', label: 'Localhost 8545',
closeMenu:() => this.setState({ isNetworkMenuOpen: false }), closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
action:() => props.dispatch(actions.setRpcTarget('http://localhost:8545')), action: () => props.dispatch(actions.setRpcTarget('http://localhost:8545')),
icon: h('i.fa.fa-question-circle.fa-lg', { ariaHidden: true }), 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, {
isOpen: props.menuOpen, isOpen: props.menuOpen,
@ -218,28 +210,28 @@ App.prototype.renderDropdown = function() {
h(DropMenuItem, { h(DropMenuItem, {
label: 'Settings', label: 'Settings',
closeMenu:() => this.props.dispatch(actions.closeMenu()), closeMenu: () => this.props.dispatch(actions.closeMenu()),
action:() => this.props.dispatch(actions.showConfigPage()), action: () => this.props.dispatch(actions.showConfigPage()),
icon: h('i.fa.fa-gear.fa-lg', { ariaHidden: true }), icon: h('i.fa.fa-gear.fa-lg', { ariaHidden: true }),
}), }),
h(DropMenuItem, { h(DropMenuItem, {
label: 'Lock', label: 'Lock',
closeMenu:() => this.props.dispatch(actions.closeMenu()), closeMenu: () => this.props.dispatch(actions.closeMenu()),
action:() => this.props.dispatch(actions.lockMetamask()), action: () => this.props.dispatch(actions.lockMetamask()),
icon: h('i.fa.fa-lock.fa-lg', { ariaHidden: true }), icon: h('i.fa.fa-lock.fa-lg', { ariaHidden: true }),
}), }),
h(DropMenuItem, { h(DropMenuItem, {
label: 'Help', label: 'Help',
closeMenu:() => this.props.dispatch(actions.closeMenu()), closeMenu: () => this.props.dispatch(actions.closeMenu()),
action:() => this.props.dispatch(actions.showInfoPage()), action: () => this.props.dispatch(actions.showInfoPage()),
icon: h('i.fa.fa-question.fa-lg', { ariaHidden: true }), icon: h('i.fa.fa-question.fa-lg', { ariaHidden: true }),
}), }),
]) ])
} }
App.prototype.renderPrimary = function(){ App.prototype.renderPrimary = function () {
var props = this.props var props = this.props
if (!props.isConfirmed) { if (!props.isConfirmed) {
@ -252,7 +244,6 @@ App.prototype.renderPrimary = function(){
// show initialize screen // show initialize screen
if (!props.isInitialized) { if (!props.isInitialized) {
// show current view // show current view
switch (props.currentView.name) { switch (props.currentView.name) {
@ -305,10 +296,10 @@ App.prototype.renderPrimary = function(){
default: default:
return h(AccountDetailScreen, {key: 'account-detail'}) return h(AccountDetailScreen, {key: 'account-detail'})
} }
} }
App.prototype.toggleMetamaskActive = function(){ App.prototype.toggleMetamaskActive = function () {
if (!this.props.isUnlocked) { if (!this.props.isUnlocked) {
// currently inactive: redirect to password box // currently inactive: redirect to password box
var passwordBox = document.querySelector('input[type=password]') var passwordBox = document.querySelector('input[type=password]')

@ -6,14 +6,13 @@ const actions = require('../actions')
module.exports = ExportAccountView module.exports = ExportAccountView
inherits(ExportAccountView, Component) inherits(ExportAccountView, Component)
function ExportAccountView() { function ExportAccountView () {
Component.call(this) Component.call(this)
} }
ExportAccountView.prototype.render = function() { ExportAccountView.prototype.render = function () {
console.log("EXPORT VIEW") console.log('EXPORT VIEW')
console.dir(this.props) console.dir(this.props)
var state = this.props var state = this.props
var accountDetail = state.accountDetail var accountDetail = state.accountDetail
@ -47,13 +46,13 @@ ExportAccountView.prototype.render = function() {
style: { style: {
position: 'relative', position: 'relative',
top: '1.5px', top: '1.5px',
} },
}), }),
h('button', { h('button', {
onClick: () => this.onExportKeyPress({ key: 'Enter', preventDefault: () => {} }), onClick: () => this.onExportKeyPress({ key: 'Enter', preventDefault: () => {} }),
}, 'Submit'), }, 'Submit'),
h('button', { h('button', {
onClick: () => this.props.dispatch(actions.backToAccountDetail(this.props.address)) onClick: () => this.props.dispatch(actions.backToAccountDetail(this.props.address)),
}, 'Cancel'), }, 'Cancel'),
]) ])
@ -72,18 +71,18 @@ ExportAccountView.prototype.render = function() {
webkitUserSelect: 'text', webkitUserSelect: 'text',
width: '100%', width: '100%',
}, },
onClick: function(event) { onClick: function (event) {
copyToClipboard(accountDetail.privateKey) copyToClipboard(accountDetail.privateKey)
} },
}, accountDetail.privateKey), }, accountDetail.privateKey),
h('button', { h('button', {
onClick: () => this.props.dispatch(actions.backToAccountDetail(this.props.address)) onClick: () => this.props.dispatch(actions.backToAccountDetail(this.props.address)),
}, 'Done'), }, 'Done'),
]) ])
} }
} }
ExportAccountView.prototype.onExportKeyPress = function(event) { ExportAccountView.prototype.onExportKeyPress = function (event) {
if (event.key !== 'Enter') return if (event.key !== 'Enter') return
event.preventDefault() event.preventDefault()
@ -96,6 +95,6 @@ ExportAccountView.prototype.onExportKeyPress = function(event) {
} }
} }
ExportAccountView.prototype.exportAccount = function(address) { ExportAccountView.prototype.exportAccount = function (address) {
this.props.dispatch(actions.exportAccount(address)) this.props.dispatch(actions.exportAccount(address))
} }

@ -1,30 +1,24 @@
const inherits = require('util').inherits const inherits = require('util').inherits
const ethUtil = require('ethereumjs-util')
const Component = require('react').Component const Component = require('react').Component
const h = require('react-hyperscript') const h = require('react-hyperscript')
const formatBalance = require('../util').formatBalance const formatBalance = require('../util').formatBalance
const Identicon = require('./identicon')
const addressSummary = require('../util').addressSummary const addressSummary = require('../util').addressSummary
const Panel = require('./panel') const Panel = require('./panel')
module.exports = AccountPanel module.exports = AccountPanel
inherits(AccountPanel, Component) inherits(AccountPanel, Component)
function AccountPanel() { function AccountPanel () {
Component.call(this) Component.call(this)
} }
AccountPanel.prototype.render = function() { AccountPanel.prototype.render = function () {
var state = this.props var state = this.props
var identity = state.identity || {} var identity = state.identity || {}
var account = state.account || {} var account = state.account || {}
var isFauceting = state.isFauceting var isFauceting = state.isFauceting
var identicon = new Identicon(identity.address, 46).toString()
var identiconSrc = `data:image/png;base64,${identicon}`
var panelOpts = { var panelOpts = {
key: `accountPanel${identity.address}`, key: `accountPanel${identity.address}`,
onClick: (event) => { onClick: (event) => {
@ -40,21 +34,19 @@ AccountPanel.prototype.render = function() {
value: addressSummary(identity.address), value: addressSummary(identity.address),
}, },
balanceOrFaucetingIndication(account, isFauceting), balanceOrFaucetingIndication(account, isFauceting),
] ],
} }
return h(Panel, panelOpts, return h(Panel, panelOpts,
!state.onShowDetail ? null : h('.arrow-right.cursor-pointer', [ !state.onShowDetail ? null : h('.arrow-right.cursor-pointer', [
h('i.fa.fa-chevron-right.fa-lg'), h('i.fa.fa-chevron-right.fa-lg'),
])) ]))
} }
function balanceOrFaucetingIndication(account, isFauceting) { function balanceOrFaucetingIndication (account, isFauceting) {
// Temporarily deactivating isFauceting indication // Temporarily deactivating isFauceting indication
// because it shows fauceting for empty restored accounts. // because it shows fauceting for empty restored accounts.
if (/*isFauceting*/ false) { if (/* isFauceting*/ false) {
return { return {
key: 'Account is auto-funding.', key: 'Account is auto-funding.',
value: 'Please wait.', value: 'Please wait.',
@ -62,7 +54,7 @@ function balanceOrFaucetingIndication(account, isFauceting) {
} else { } else {
return { return {
key: 'BALANCE', key: 'BALANCE',
value: formatBalance(account.balance) value: formatBalance(account.balance),
} }
} }
} }

@ -4,16 +4,14 @@ const inherits = require('util').inherits
module.exports = DropMenuItem module.exports = DropMenuItem
inherits(DropMenuItem, Component) inherits(DropMenuItem, Component)
function DropMenuItem() { function DropMenuItem () {
Component.call(this) Component.call(this)
} }
DropMenuItem.prototype.render = function() { DropMenuItem.prototype.render = function () {
return h('li.drop-menu-item', { return h('li.drop-menu-item', {
onClick:() => { onClick: () => {
this.props.closeMenu() this.props.closeMenu()
this.props.action() this.props.action()
}, },

@ -5,46 +5,43 @@ const findDOMNode = require('react-dom').findDOMNode
module.exports = EditableLabel module.exports = EditableLabel
inherits(EditableLabel, Component) inherits(EditableLabel, Component)
function EditableLabel() { function EditableLabel () {
Component.call(this) Component.call(this)
} }
EditableLabel.prototype.render = function() { EditableLabel.prototype.render = function () {
const props = this.props const props = this.props
let state = this.state const state = this.state
if (state && state.isEditingLabel) { if (state && state.isEditingLabel) {
return h('div.editable-label', [ return h('div.editable-label', [
h('input.sizing-input', { h('input.sizing-input', {
defaultValue: props.textValue, defaultValue: props.textValue,
onKeyPress:(event) => { onKeyPress: (event) => {
this.saveIfEnter(event) this.saveIfEnter(event)
}, },
}), }),
h('button.editable-button', { h('button.editable-button', {
onClick:() => this.saveText(), onClick: () => this.saveText(),
}, 'Save') }, 'Save'),
]) ])
} else { } else {
return h('div.name-label', { return h('div.name-label', {
onClick:(event) => { onClick: (event) => {
this.setState({ isEditingLabel: true }) this.setState({ isEditingLabel: true })
}, },
}, this.props.children) }, this.props.children)
} }
} }
EditableLabel.prototype.saveIfEnter = function(event) { EditableLabel.prototype.saveIfEnter = function (event) {
if (event.key === 'Enter') { if (event.key === 'Enter') {
this.saveText() this.saveText()
} }
} }
EditableLabel.prototype.saveText = function() { EditableLabel.prototype.saveText = function () {
var container = findDOMNode(this) var container = findDOMNode(this)
var text = container.querySelector('.editable-label input').value var text = container.querySelector('.editable-label input').value
this.props.saveText(text) this.props.saveText(text)

@ -1,17 +1,16 @@
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 parseBalance = require('../util').parseBalance
const formatBalance = require('../util').formatBalance const formatBalance = require('../util').formatBalance
module.exports = EthBalanceComponent module.exports = EthBalanceComponent
inherits(EthBalanceComponent, Component) inherits(EthBalanceComponent, Component)
function EthBalanceComponent() { function EthBalanceComponent () {
Component.call(this) Component.call(this)
} }
EthBalanceComponent.prototype.render = function() { EthBalanceComponent.prototype.render = function () {
var state = this.props var state = this.props
var style = state.style var style = state.style
var value = formatBalance(state.value) var value = formatBalance(state.value)

@ -9,13 +9,13 @@ const iconFactory = iconFactoryGen(jazzicon)
module.exports = IdenticonComponent module.exports = IdenticonComponent
inherits(IdenticonComponent, Component) inherits(IdenticonComponent, Component)
function IdenticonComponent() { function IdenticonComponent () {
Component.call(this) Component.call(this)
this.defaultDiameter = 46 this.defaultDiameter = 46
} }
IdenticonComponent.prototype.render = function() { IdenticonComponent.prototype.render = function () {
var state = this.props var state = this.props
var diameter = state.diameter || this.defaultDiameter var diameter = state.diameter || this.defaultDiameter
return ( return (
@ -32,7 +32,7 @@ IdenticonComponent.prototype.render = function() {
) )
} }
IdenticonComponent.prototype.componentDidMount = function(){ IdenticonComponent.prototype.componentDidMount = function () {
var state = this.props var state = this.props
var address = state.address var address = state.address

@ -2,14 +2,12 @@ const inherits = require('util').inherits
const Component = require('react').Component const Component = require('react').Component
const h = require('react-hyperscript') const h = require('react-hyperscript')
const metamaskLogo = require('metamask-logo') const metamaskLogo = require('metamask-logo')
const getCaretCoordinates = require('textarea-caret')
const debounce = require('debounce') const debounce = require('debounce')
module.exports = Mascot module.exports = Mascot
inherits(Mascot, Component) inherits(Mascot, Component)
function Mascot() { function Mascot () {
Component.call(this) Component.call(this)
this.logo = metamaskLogo({ this.logo = metamaskLogo({
followMouse: true, followMouse: true,
@ -22,8 +20,7 @@ function Mascot() {
this.unfollowMouse = this.logo.setFollowMouse.bind(this.logo, false) this.unfollowMouse = this.logo.setFollowMouse.bind(this.logo, false)
} }
Mascot.prototype.render = function () {
Mascot.prototype.render = function() {
// this is a bit hacky // this is a bit hacky
// the event emitter is on `this.props` // the event emitter is on `this.props`
// and we dont get that until render // and we dont get that until render
@ -36,19 +33,19 @@ Mascot.prototype.render = function() {
) )
} }
Mascot.prototype.componentDidMount = function() { Mascot.prototype.componentDidMount = function () {
if (!this.logo) return if (!this.logo) return
var targetDivId = 'metamask-mascot-container' var targetDivId = 'metamask-mascot-container'
var container = document.getElementById(targetDivId) var container = document.getElementById(targetDivId)
container.appendChild(this.logo.canvas) container.appendChild(this.logo.canvas)
} }
Mascot.prototype.componentWillUnmount = function() { Mascot.prototype.componentWillUnmount = function () {
if (!this.logo) return if (!this.logo) return
this.logo.canvas.remove() this.logo.canvas.remove()
} }
Mascot.prototype.handleAnimationEvents = function(){ Mascot.prototype.handleAnimationEvents = function () {
if (!this.logo) return if (!this.logo) return
// only setup listeners once // only setup listeners once
if (this.animations) return if (this.animations) return
@ -57,7 +54,7 @@ Mascot.prototype.handleAnimationEvents = function(){
this.animations.on('setFollowMouse', this.logo.setFollowMouse.bind(this.logo)) this.animations.on('setFollowMouse', this.logo.setFollowMouse.bind(this.logo))
} }
Mascot.prototype.lookAt = function(target){ Mascot.prototype.lookAt = function (target) {
if (!this.logo) return if (!this.logo) return
this.unfollowMouse() this.unfollowMouse()
this.logo.lookAt(target) this.logo.lookAt(target)

@ -6,34 +6,33 @@ module.exports = Network
inherits(Network, Component) inherits(Network, Component)
function Network() { function Network () {
Component.call(this) Component.call(this)
} }
Network.prototype.render = function() { Network.prototype.render = function () {
const state = this.props const state = this.props
const networkNumber = state.network const networkNumber = state.network
let iconName, hoverText let iconName, hoverText
const imagePath = "/images/"
if (networkNumber == 'loading') { if (networkNumber === 'loading') {
return h('img', { return h('img', {
title: 'Attempting to connect to blockchain.', title: 'Attempting to connect to blockchain.',
onClick:(event) => this.props.onClick(event), onClick: (event) => this.props.onClick(event),
style: { style: {
width: '27px', width: '27px',
marginRight: '-27px' marginRight: '-27px',
}, },
src: 'images/loading.svg', src: 'images/loading.svg',
}) })
} else if (parseInt(networkNumber) == 1) { } else if (parseInt(networkNumber) === 1) {
hoverText = 'Main Ethereum Network' hoverText = 'Main Ethereum Network'
iconName = 'ethereum-network' iconName = 'ethereum-network'
}else if (parseInt(networkNumber) == 2) { } else if (parseInt(networkNumber) === 2) {
hoverText = "Morden Test Network" hoverText = 'Morden Test Network'
iconName = 'morden-test-network' iconName = 'morden-test-network'
}else { } else {
hoverText = "Unknown Private Network" hoverText = 'Unknown Private Network'
iconName = 'unknown-private-network' iconName = 'unknown-private-network'
} }
return ( return (
@ -43,24 +42,24 @@ Network.prototype.render = function() {
marginLeft: '-3px', marginLeft: '-3px',
}, },
title: hoverText, title: hoverText,
onClick:(event) => this.props.onClick(event), onClick: (event) => this.props.onClick(event),
},[ }, [
function() { (function () {
switch (iconName) { switch (iconName) {
case 'ethereum-network': case 'ethereum-network':
return h('.menu-icon.ether-icon') return h('.menu-icon.ether-icon')
case 'morden-test-network': case 'morden-test-network':
return h('.menu-icon.morden-icon') return h('.menu-icon.morden-icon')
default: default:
return h('i.fa.fa-question-circle.fa-lg', { return h('i.fa.fa-question-circle.fa-lg', {
ariaHidden: true, ariaHidden: true,
style: { style: {
margin: '10px', margin: '10px',
color: 'rgb(125, 128, 130)', color: 'rgb(125, 128, 130)',
}, },
}) })
} }
}() })(),
]) ])
) )
} }

@ -1,23 +1,18 @@
const inherits = require('util').inherits const inherits = require('util').inherits
const ethUtil = require('ethereumjs-util')
const Component = require('react').Component const Component = require('react').Component
const h = require('react-hyperscript') const h = require('react-hyperscript')
const Identicon = require('./identicon') const Identicon = require('./identicon')
module.exports = Panel module.exports = Panel
inherits(Panel, Component) inherits(Panel, Component)
function Panel() { function Panel () {
Component.call(this) Component.call(this)
} }
Panel.prototype.render = function() { Panel.prototype.render = function () {
var state = this.props var state = this.props
var identity = state.identity || {}
var account = state.account || {}
var isFauceting = state.isFauceting
var style = { var style = {
flex: '1 0 auto', flex: '1 0 auto',
} }

@ -3,25 +3,21 @@ const h = require('react-hyperscript')
const inherits = require('util').inherits const inherits = require('util').inherits
const AccountPanel = require('./account-panel') const AccountPanel = require('./account-panel')
const addressSummary = require('../util').addressSummary
const readableDate = require('../util').readableDate const readableDate = require('../util').readableDate
const formatBalance = require('../util').formatBalance
const dataSize = require('../util').dataSize
module.exports = PendingMsg module.exports = PendingMsg
inherits(PendingMsg, Component) inherits(PendingMsg, Component)
function PendingMsg() { function PendingMsg () {
Component.call(this) Component.call(this)
} }
PendingMsg.prototype.render = function() { PendingMsg.prototype.render = function () {
var state = this.props var state = this.props
var msgData = state.txData var msgData = state.txData
var msgParams = msgData.msgParams || {} var msgParams = msgData.msgParams || {}
var address = msgParams.from || state.selectedAddress var address = msgParams.from || state.selectedAddress
var identity = state.identities[address] || { address: address } var identity = state.identities[address] || { address: address }
var account = state.accounts[address] || { address: address } var account = state.accounts[address] || { address: address }
@ -34,7 +30,7 @@ PendingMsg.prototype.render = function() {
style: { style: {
fontWeight: 'bold', fontWeight: 'bold',
textAlign: 'center', textAlign: 'center',
} },
}, 'Sign Message'), }, 'Sign Message'),
// account that will sign // account that will sign

@ -6,22 +6,20 @@ const AccountPanel = require('./account-panel')
const addressSummary = require('../util').addressSummary const addressSummary = require('../util').addressSummary
const readableDate = require('../util').readableDate const readableDate = require('../util').readableDate
const formatBalance = require('../util').formatBalance const formatBalance = require('../util').formatBalance
const dataSize = require('../util').dataSize
module.exports = PendingTx module.exports = PendingTx
inherits(PendingTx, Component) inherits(PendingTx, Component)
function PendingTx() { function PendingTx () {
Component.call(this) Component.call(this)
} }
PendingTx.prototype.render = function() { PendingTx.prototype.render = function () {
var state = this.props var state = this.props
var txData = state.txData var txData = state.txData
var txParams = txData.txParams || {} var txParams = txData.txParams || {}
var address = txParams.from || state.selectedAddress var address = txParams.from || state.selectedAddress
var identity = state.identities[address] || { address: address } var identity = state.identities[address] || { address: address }
var account = state.accounts[address] || { address: address } var account = state.accounts[address] || { address: address }
@ -34,7 +32,7 @@ PendingTx.prototype.render = function() {
style: { style: {
fontWeight: 'bold', fontWeight: 'bold',
textAlign: 'center', textAlign: 'center',
} },
}, 'Submit Transaction'), }, 'Submit Transaction'),
// account that will sign // account that will sign

@ -4,16 +4,15 @@ const inherits = require('util').inherits
module.exports = NewComponent module.exports = NewComponent
inherits(NewComponent, Component) inherits(NewComponent, Component)
function NewComponent() { function NewComponent () {
Component.call(this) Component.call(this)
} }
NewComponent.prototype.render = function() { NewComponent.prototype.render = function () {
var state = this.props const props = this.props
return ( return (
h('span', 'Placeholder component') h('span', props.message)
) )
} }

@ -6,20 +6,19 @@ const Identicon = require('./identicon')
module.exports = TransactionIcon module.exports = TransactionIcon
inherits(TransactionIcon, Component) inherits(TransactionIcon, Component)
function TransactionIcon() { function TransactionIcon () {
Component.call(this) Component.call(this)
} }
TransactionIcon.prototype.render = function() { TransactionIcon.prototype.render = function () {
const { transaction, txParams, isTx, isMsg } = this.props const { transaction, txParams, isMsg } = this.props
if (transaction.status === 'rejected') { if (transaction.status === 'rejected') {
return h('i.fa.fa-exclamation-triangle.fa-lg.error', { return h('i.fa.fa-exclamation-triangle.fa-lg.error', {
style: { style: {
width: '24px', width: '24px',
} },
}) })
} }
@ -27,7 +26,7 @@ TransactionIcon.prototype.render = function() {
return h('i.fa.fa-certificate.fa-lg', { return h('i.fa.fa-certificate.fa-lg', {
style: { style: {
width: '24px', width: '24px',
} },
}) })
} }
@ -40,7 +39,7 @@ TransactionIcon.prototype.render = function() {
return h('i.fa.fa-file-text-o.fa-lg', { return h('i.fa.fa-file-text-o.fa-lg', {
style: { style: {
width: '24px', width: '24px',
} },
}) })
} }
} }

@ -5,20 +5,18 @@ const inherits = require('util').inherits
const EtherBalance = require('./eth-balance') const EtherBalance = require('./eth-balance')
const addressSummary = require('../util').addressSummary const addressSummary = require('../util').addressSummary
const explorerLink = require('../../lib/explorer-link') const explorerLink = require('../../lib/explorer-link')
const formatBalance = require('../util').formatBalance
const vreme = new (require('vreme')) const vreme = new (require('vreme'))
const TransactionIcon = require('./transaction-list-item-icon') const TransactionIcon = require('./transaction-list-item-icon')
module.exports = TransactionListItem module.exports = TransactionListItem
inherits(TransactionListItem, Component) inherits(TransactionListItem, Component)
function TransactionListItem() { function TransactionListItem () {
Component.call(this) Component.call(this)
} }
TransactionListItem.prototype.render = function() { TransactionListItem.prototype.render = function () {
const { transaction, i, network } = this.props const { transaction, i, network } = this.props
var date = formatDate(transaction.time) var date = formatDate(transaction.time)
@ -59,8 +57,8 @@ TransactionListItem.prototype.render = function() {
// large identicon // large identicon
h('.identicon-wrapper.flex-column.flex-center.select-none', [ h('.identicon-wrapper.flex-column.flex-center.select-none', [
transaction.status === 'unconfirmed' ? h('.red-dot', ' ') : transaction.status === 'unconfirmed' ? h('.red-dot', ' ')
h(TransactionIcon, { txParams, transaction, isTx, isMsg }), : h(TransactionIcon, { txParams, transaction, isTx, isMsg }),
]), ]),
h('.flex-column', [ h('.flex-column', [
@ -76,24 +74,24 @@ TransactionListItem.prototype.render = function() {
) )
} }
function domainField(txParams) { function domainField (txParams) {
return h('div', { return h('div', {
style: { style: {
fontSize: 'small', fontSize: 'small',
color: '#ABA9AA', color: '#ABA9AA',
}, },
},[ }, [
txParams.origin, txParams.origin,
]) ])
} }
function recipientField(txParams, transaction, isTx, isMsg) { function recipientField (txParams, transaction, isTx, isMsg) {
let message let message
if (isMsg) { if (isMsg) {
message = 'Signature Requested' message = 'Signature Requested'
} else if (txParams.to) { } else if (txParams.to) {
message = addressSummary(txParams.to) message = addressSummary(txParams.to)
} else { } else {
message = 'Contract Published' message = 'Contract Published'
} }
@ -103,23 +101,17 @@ function recipientField(txParams, transaction, isTx, isMsg) {
fontSize: 'small', fontSize: 'small',
color: '#ABA9AA', color: '#ABA9AA',
}, },
},[ }, [
message, message,
failIfFailed(transaction), failIfFailed(transaction),
]) ])
}
TransactionListItem.prototype.renderMessage = function() {
const { transaction, i, network } = this.props
return h('div', 'wowie, thats a message')
} }
function formatDate(date){ function formatDate (date) {
return vreme.format(new Date(date), 'March 16 2014 14:30') return vreme.format(new Date(date), 'March 16 2014 14:30')
} }
function failIfFailed(transaction) { function failIfFailed (transaction) {
if (transaction.status === 'rejected') { if (transaction.status === 'rejected') {
return h('span.error', ' (Rejected)') return h('span.error', ' (Rejected)')
} }

@ -8,12 +8,12 @@ module.exports = TransactionList
inherits(TransactionList, Component) inherits(TransactionList, Component)
function TransactionList() { function TransactionList () {
Component.call(this) Component.call(this)
} }
TransactionList.prototype.render = function() { TransactionList.prototype.render = function () {
const { txsToRender, network, unconfTxs, unconfMsgs } = this.props const { txsToRender, network, unconfMsgs } = this.props
const transactions = txsToRender.concat(unconfMsgs) const transactions = txsToRender.concat(unconfMsgs)
.sort((a, b) => b.time - a.time) .sort((a, b) => b.time - a.time)
@ -49,22 +49,21 @@ TransactionList.prototype.render = function() {
}, },
}, ( }, (
transactions.length ? transactions.length
transactions.map((transaction, i) => { ? transactions.map((transaction, i) => {
return h(TransactionListItem, { return h(TransactionListItem, {
transaction, i, network, transaction, i, network,
showTx:(txId) => { showTx: (txId) => {
this.props.viewPendingTx(txId) this.props.viewPendingTx(txId)
}, },
}) })
}) })
: : [h('.flex-center', {
[h('.flex-center', { style: {
style: { height: '100%',
height: '100%', },
}, }, 'No transaction history...')]
}, 'No transaction history...')] )),
))
]) ])
) )
} }

@ -3,10 +3,7 @@ const Component = require('react').Component
const ReactCSSTransitionGroup = require('react-addons-css-transition-group') const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
const h = require('react-hyperscript') const h = require('react-hyperscript')
const connect = require('react-redux').connect const connect = require('react-redux').connect
const copyToClipboard = require('copy-to-clipboard')
const actions = require('./actions') const actions = require('./actions')
const AccountPanel = require('./components/account-panel')
const valuesFor = require('./util').valuesFor
const txHelper = require('../lib/tx-helper') const txHelper = require('../lib/tx-helper')
const ConfirmTx = require('./components/pending-tx') const ConfirmTx = require('./components/pending-tx')
@ -14,7 +11,7 @@ const PendingMsg = require('./components/pending-msg')
module.exports = connect(mapStateToProps)(ConfirmTxScreen) module.exports = connect(mapStateToProps)(ConfirmTxScreen)
function mapStateToProps(state) { function mapStateToProps (state) {
return { return {
identities: state.metamask.identities, identities: state.metamask.identities,
accounts: state.metamask.accounts, accounts: state.metamask.accounts,
@ -27,12 +24,11 @@ function mapStateToProps(state) {
} }
inherits(ConfirmTxScreen, Component) inherits(ConfirmTxScreen, Component)
function ConfirmTxScreen() { function ConfirmTxScreen () {
Component.call(this) Component.call(this)
} }
ConfirmTxScreen.prototype.render = function () {
ConfirmTxScreen.prototype.render = function() {
var state = this.props var state = this.props
var unconfTxs = state.unconfTxs var unconfTxs = state.unconfTxs
@ -103,7 +99,6 @@ ConfirmTxScreen.prototype.render = function() {
} }
function currentTxView (opts) { function currentTxView (opts) {
if ('txParams' in opts.txData) { if ('txParams' in opts.txData) {
// This is a pending transaction // This is a pending transaction
return h(ConfirmTx, opts) return h(ConfirmTx, opts)
@ -113,34 +108,34 @@ function currentTxView (opts) {
} }
} }
ConfirmTxScreen.prototype.sendTransaction = function(txData, event){ ConfirmTxScreen.prototype.sendTransaction = function (txData, event) {
event.stopPropagation() event.stopPropagation()
this.props.dispatch(actions.sendTx(txData)) this.props.dispatch(actions.sendTx(txData))
} }
ConfirmTxScreen.prototype.cancelTransaction = function(txData, event){ ConfirmTxScreen.prototype.cancelTransaction = function (txData, event) {
event.stopPropagation() event.stopPropagation()
this.props.dispatch(actions.cancelTx(txData)) this.props.dispatch(actions.cancelTx(txData))
} }
ConfirmTxScreen.prototype.signMessage = function(msgData, event){ ConfirmTxScreen.prototype.signMessage = function (msgData, event) {
var params = msgData.msgParams var params = msgData.msgParams
params.metamaskId = msgData.id params.metamaskId = msgData.id
event.stopPropagation() event.stopPropagation()
this.props.dispatch(actions.signMsg(params)) this.props.dispatch(actions.signMsg(params))
} }
ConfirmTxScreen.prototype.cancelMessage = function(msgData, event){ ConfirmTxScreen.prototype.cancelMessage = function (msgData, event) {
event.stopPropagation() event.stopPropagation()
this.props.dispatch(actions.cancelMsg(msgData)) this.props.dispatch(actions.cancelMsg(msgData))
} }
ConfirmTxScreen.prototype.goHome = function(event){ ConfirmTxScreen.prototype.goHome = function (event) {
event.stopPropagation() event.stopPropagation()
this.props.dispatch(actions.goHome()) this.props.dispatch(actions.goHome())
} }
function warningIfExists(warning) { function warningIfExists (warning) {
if (warning) { if (warning) {
return h('span.error', { style: { margin: 'auto' } }, warning) return h('span.error', { style: { margin: 'auto' } }, warning)
} }

@ -6,22 +6,19 @@ const actions = require('./actions')
module.exports = connect(mapStateToProps)(ConfigScreen) module.exports = connect(mapStateToProps)(ConfigScreen)
function mapStateToProps(state) { function mapStateToProps (state) {
return { return {
rpc: state.metamask.rpcTarget,
metamask: state.metamask, metamask: state.metamask,
} }
} }
inherits(ConfigScreen, Component) inherits(ConfigScreen, Component)
function ConfigScreen() { function ConfigScreen () {
Component.call(this) Component.call(this)
} }
ConfigScreen.prototype.render = function () {
ConfigScreen.prototype.render = function() {
var state = this.props var state = this.props
var rpc = state.rpc
var metamaskState = state.metamask var metamaskState = state.metamask
return ( return (
@ -32,7 +29,7 @@ ConfigScreen.prototype.render = function() {
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', { h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
onClick: (event) => { onClick: (event) => {
state.dispatch(actions.goHome()) state.dispatch(actions.goHome())
} },
}), }),
h('h2.page-subtitle', 'Configuration'), h('h2.page-subtitle', 'Configuration'),
]), ]),
@ -42,7 +39,7 @@ ConfigScreen.prototype.render = function() {
h('.flex-space-around', { h('.flex-space-around', {
style: { style: {
padding: '20px', padding: '20px',
} },
}, [ }, [
currentProviderDisplay(metamaskState), currentProviderDisplay(metamaskState),
@ -56,25 +53,25 @@ ConfigScreen.prototype.render = function() {
height: '30px', height: '30px',
margin: '8px', margin: '8px',
}, },
onKeyPress(event) { onKeyPress (event) {
if (event.key === 'Enter') { if (event.key === 'Enter') {
var element = event.target var element = event.target
var newRpc = element.value var newRpc = element.value
state.dispatch(actions.setRpcTarget(newRpc)) state.dispatch(actions.setRpcTarget(newRpc))
} }
} },
}), }),
h('button', { h('button', {
style: { style: {
alignSelf: 'center', alignSelf: 'center',
}, },
onClick(event) { onClick (event) {
event.preventDefault() event.preventDefault()
var element = document.querySelector('input#new_rpc') var element = document.querySelector('input#new_rpc')
var newRpc = element.value var newRpc = element.value
state.dispatch(actions.setRpcTarget(newRpc)) state.dispatch(actions.setRpcTarget(newRpc))
} },
}, 'Save') }, 'Save'),
]), ]),
h('div', [ h('div', [
@ -82,10 +79,10 @@ ConfigScreen.prototype.render = function() {
style: { style: {
alignSelf: 'center', alignSelf: 'center',
}, },
onClick(event) { onClick (event) {
event.preventDefault() event.preventDefault()
state.dispatch(actions.setProviderType('mainnet')) state.dispatch(actions.setProviderType('mainnet'))
} },
}, 'Use Main Network'), }, 'Use Main Network'),
]), ]),
@ -94,10 +91,10 @@ ConfigScreen.prototype.render = function() {
style: { style: {
alignSelf: 'center', alignSelf: 'center',
}, },
onClick(event) { onClick (event) {
event.preventDefault() event.preventDefault()
state.dispatch(actions.setProviderType('testnet')) state.dispatch(actions.setProviderType('testnet'))
} },
}, 'Use Morden Test Network'), }, 'Use Morden Test Network'),
]), ]),
@ -106,10 +103,10 @@ ConfigScreen.prototype.render = function() {
style: { style: {
alignSelf: 'center', alignSelf: 'center',
}, },
onClick(event) { onClick (event) {
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'),
]), ]),
@ -118,17 +115,17 @@ ConfigScreen.prototype.render = function() {
h('div', { h('div', {
style: { style: {
marginTop: '20px', marginTop: '20px',
} },
}, [ }, [
h('button', { h('button', {
style: { style: {
alignSelf: 'center', alignSelf: 'center',
}, },
onClick(event) { onClick (event) {
event.preventDefault() event.preventDefault()
state.dispatch(actions.revealSeedConfirmation()) state.dispatch(actions.revealSeedConfirmation())
} },
}, 'Reveal Seed Words') }, 'Reveal Seed Words'),
]), ]),
]), ]),
@ -137,7 +134,7 @@ ConfigScreen.prototype.render = function() {
) )
} }
function currentProviderDisplay(metamaskState) { function currentProviderDisplay (metamaskState) {
var provider = metamaskState.provider var provider = metamaskState.provider
var title, value var title, value
@ -156,10 +153,10 @@ function currentProviderDisplay(metamaskState) {
default: default:
title = 'Current RPC' title = 'Current RPC'
value = metamaskState.provider.rpcTarget value = metamaskState.provider.rpcTarget
} }
return h('div', [ return h('div', [
h('span', {style: { fontWeight: 'bold', paddingRight: '10px'}}, title), h('span', {style: { fontWeight: 'bold', paddingRight: '10px'}}, title),
h('span', value) h('span', value),
]) ])
} }

@ -6,20 +6,19 @@ const actions = require('../actions')
module.exports = connect(mapStateToProps)(CreateVaultCompleteScreen) module.exports = connect(mapStateToProps)(CreateVaultCompleteScreen)
inherits(CreateVaultCompleteScreen, Component) inherits(CreateVaultCompleteScreen, Component)
function CreateVaultCompleteScreen() { function CreateVaultCompleteScreen () {
Component.call(this) Component.call(this)
} }
function mapStateToProps(state) { function mapStateToProps (state) {
return { return {
seed: state.appState.currentView.seedWords, seed: state.appState.currentView.seedWords,
cachedSeed: state.metamask.seedWords, cachedSeed: state.metamask.seedWords,
} }
} }
CreateVaultCompleteScreen.prototype.render = function() { CreateVaultCompleteScreen.prototype.render = function () {
var state = this.props var state = this.props
var seed = state.seed || state.cachedSeed var seed = state.seed || state.cachedSeed
@ -50,7 +49,7 @@ CreateVaultCompleteScreen.prototype.render = function() {
style: { style: {
padding: '12px 20px 0px 20px', padding: '12px 20px 0px 20px',
textAlign: 'center', textAlign: 'center',
} },
}, 'These 12 words can restore all of your MetaMask accounts for this vault.\nSave them somewhere safe and secret.'), }, 'These 12 words can restore all of your MetaMask accounts for this vault.\nSave them somewhere safe and secret.'),
h('textarea.twelve-word-phrase', { h('textarea.twelve-word-phrase', {
@ -68,7 +67,7 @@ CreateVaultCompleteScreen.prototype.render = function() {
) )
} }
CreateVaultCompleteScreen.prototype.confirmSeedWords = function() { CreateVaultCompleteScreen.prototype.confirmSeedWords = function () {
this.props.dispatch(actions.confirmSeedWords()) this.props.dispatch(actions.confirmSeedWords())
} }

@ -7,19 +7,18 @@ const actions = require('../actions')
module.exports = connect(mapStateToProps)(CreateVaultScreen) module.exports = connect(mapStateToProps)(CreateVaultScreen)
inherits(CreateVaultScreen, Component) inherits(CreateVaultScreen, Component)
function CreateVaultScreen() { function CreateVaultScreen () {
Component.call(this) Component.call(this)
} }
function mapStateToProps(state) { function mapStateToProps (state) {
return { return {
warning: state.appState.warning, warning: state.appState.warning,
} }
} }
CreateVaultScreen.prototype.render = function() { CreateVaultScreen.prototype.render = function () {
var state = this.props var state = this.props
return ( return (
@ -91,24 +90,24 @@ CreateVaultScreen.prototype.render = function() {
) )
} }
CreateVaultScreen.prototype.componentDidMount = function(){ CreateVaultScreen.prototype.componentDidMount = function () {
document.getElementById('password-box').focus() document.getElementById('password-box').focus()
} }
CreateVaultScreen.prototype.showInitializeMenu = function() { CreateVaultScreen.prototype.showInitializeMenu = function () {
this.props.dispatch(actions.showInitializeMenu()) this.props.dispatch(actions.showInitializeMenu())
} }
// create vault // create vault
CreateVaultScreen.prototype.createVaultOnEnter = function(event) { CreateVaultScreen.prototype.createVaultOnEnter = function (event) {
if (event.key === 'Enter') { if (event.key === 'Enter') {
event.preventDefault() event.preventDefault()
this.createNewVault() this.createNewVault()
} }
} }
CreateVaultScreen.prototype.createNewVault = function(){ CreateVaultScreen.prototype.createNewVault = function () {
var passwordBox = document.getElementById('password-box') var passwordBox = document.getElementById('password-box')
var password = passwordBox.value var password = passwordBox.value
var passwordConfirmBox = document.getElementById('password-box-confirm') var passwordConfirmBox = document.getElementById('password-box-confirm')
@ -126,5 +125,5 @@ CreateVaultScreen.prototype.createNewVault = function(){
return return
} }
this.props.dispatch(actions.createNewVault(password, ''/*entropy*/)) this.props.dispatch(actions.createNewVault(password, ''/* entropy*/))
} }

@ -8,17 +8,16 @@ const path = require('path')
const disclaimer = fs.readFileSync(path.join(__dirname, 'disclaimer.txt')).toString() const disclaimer = fs.readFileSync(path.join(__dirname, 'disclaimer.txt')).toString()
module.exports = connect(mapStateToProps)(DisclaimerScreen) module.exports = connect(mapStateToProps)(DisclaimerScreen)
function mapStateToProps(state) { function mapStateToProps (state) {
return {} return {}
} }
inherits(DisclaimerScreen, Component) inherits(DisclaimerScreen, Component)
function DisclaimerScreen() { function DisclaimerScreen () {
Component.call(this) Component.call(this)
} }
DisclaimerScreen.prototype.render = function() { DisclaimerScreen.prototype.render = function () {
return ( return (
h('.flex-column.flex-center.flex-grow', [ h('.flex-column.flex-center.flex-grow', [
@ -43,13 +42,13 @@ DisclaimerScreen.prototype.render = function() {
padding: '6px', padding: '6px',
width: '80%', width: '80%',
overflowY: 'scroll', overflowY: 'scroll',
} },
}, disclaimer), }, disclaimer),
h('button', { h('button', {
style: { marginTop: '18px' }, style: { marginTop: '18px' },
onClick: () => this.props.dispatch(actions.agreeToDisclaimer()) onClick: () => this.props.dispatch(actions.agreeToDisclaimer()),
}, 'I Agree') }, 'I Agree'),
]) ])
) )
} }

@ -3,28 +3,25 @@ const EventEmitter = require('events').EventEmitter
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 getCaretCoordinates = require('textarea-caret')
const Mascot = require('../components/mascot') const Mascot = require('../components/mascot')
const actions = require('../actions') const actions = require('../actions')
const CreateVaultScreen = require('./create-vault')
const CreateVaultCompleteScreen = require('./create-vault-complete')
module.exports = connect(mapStateToProps)(InitializeMenuScreen) module.exports = connect(mapStateToProps)(InitializeMenuScreen)
inherits(InitializeMenuScreen, Component) inherits(InitializeMenuScreen, Component)
function InitializeMenuScreen() { function InitializeMenuScreen () {
Component.call(this) Component.call(this)
this.animationEventEmitter = new EventEmitter() this.animationEventEmitter = new EventEmitter()
} }
function mapStateToProps(state) { function mapStateToProps (state) {
return { return {
// state from plugin // state from plugin
currentView: state.appState.currentView, currentView: state.appState.currentView,
} }
} }
InitializeMenuScreen.prototype.render = function() { InitializeMenuScreen.prototype.render = function () {
var state = this.props var state = this.props
switch (state.currentView.name) { switch (state.currentView.name) {
@ -33,15 +30,13 @@ InitializeMenuScreen.prototype.render = function() {
return this.renderMenu() return this.renderMenu()
} }
} }
// InitializeMenuScreen.prototype.componentDidMount = function(){ // InitializeMenuScreen.prototype.componentDidMount = function(){
// document.getElementById('password-box').focus() // document.getElementById('password-box').focus()
// } // }
InitializeMenuScreen.prototype.renderMenu = function() { InitializeMenuScreen.prototype.renderMenu = function () {
var state = this.props
return ( return (
h('.initialize-screen.flex-column.flex-center.flex-grow', [ h('.initialize-screen.flex-column.flex-center.flex-grow', [
@ -88,15 +83,15 @@ InitializeMenuScreen.prototype.renderMenu = function() {
// this.props.dispatch(actions.showInitializeMenu()) // this.props.dispatch(actions.showInitializeMenu())
// } // }
InitializeMenuScreen.prototype.showInitializeMenu = function() { InitializeMenuScreen.prototype.showInitializeMenu = function () {
this.props.dispatch(actions.showInitializeMenu()) this.props.dispatch(actions.showInitializeMenu())
} }
InitializeMenuScreen.prototype.showCreateVault = function() { InitializeMenuScreen.prototype.showCreateVault = function () {
this.props.dispatch(actions.showCreateVault()) this.props.dispatch(actions.showCreateVault())
} }
InitializeMenuScreen.prototype.showRestoreVault = function() { InitializeMenuScreen.prototype.showRestoreVault = function () {
this.props.dispatch(actions.showRestoreVault()) this.props.dispatch(actions.showRestoreVault())
} }

@ -6,20 +6,18 @@ const actions = require('../actions')
module.exports = connect(mapStateToProps)(RestoreVaultScreen) module.exports = connect(mapStateToProps)(RestoreVaultScreen)
inherits(RestoreVaultScreen, Component) inherits(RestoreVaultScreen, Component)
function RestoreVaultScreen() { function RestoreVaultScreen () {
Component.call(this) Component.call(this)
} }
function mapStateToProps(state) { function mapStateToProps (state) {
return { return {
warning: state.appState.warning, warning: state.appState.warning,
} }
} }
RestoreVaultScreen.prototype.render = function () {
RestoreVaultScreen.prototype.render = function() {
var state = this.props var state = this.props
return ( return (
@ -41,7 +39,7 @@ RestoreVaultScreen.prototype.render = function() {
// wallet seed entry // wallet seed entry
h('h3', 'Wallet Seed'), h('h3', 'Wallet Seed'),
h('textarea.twelve-word-phrase.letter-spacey', { h('textarea.twelve-word-phrase.letter-spacey', {
placeholder: 'Enter your secret twelve word phrase here to restore your vault.' placeholder: 'Enter your secret twelve word phrase here to restore your vault.',
}), }),
// password // password
@ -97,17 +95,17 @@ RestoreVaultScreen.prototype.render = function() {
) )
} }
RestoreVaultScreen.prototype.showInitializeMenu = function() { RestoreVaultScreen.prototype.showInitializeMenu = function () {
this.props.dispatch(actions.showInitializeMenu()) this.props.dispatch(actions.showInitializeMenu())
} }
RestoreVaultScreen.prototype.onMaybeCreate = function(event) { RestoreVaultScreen.prototype.onMaybeCreate = function (event) {
if (event.key === 'Enter') { if (event.key === 'Enter') {
this.restoreVault() this.restoreVault()
} }
} }
RestoreVaultScreen.prototype.restoreVault = function(){ RestoreVaultScreen.prototype.restoreVault = function () {
// check password // check password
var passwordBox = document.getElementById('password-box') var passwordBox = document.getElementById('password-box')
var password = passwordBox.value var password = passwordBox.value

@ -6,19 +6,18 @@ const actions = require('./actions')
module.exports = connect(mapStateToProps)(InfoScreen) module.exports = connect(mapStateToProps)(InfoScreen)
function mapStateToProps(state) { function mapStateToProps (state) {
return {} return {}
} }
inherits(InfoScreen, Component) inherits(InfoScreen, Component)
function InfoScreen() { function InfoScreen () {
Component.call(this) Component.call(this)
} }
InfoScreen.prototype.render = function() { InfoScreen.prototype.render = function () {
var state = this.props var state = this.props
var rpc = state.rpc var manifest = chrome.runtime.getManifest()
var manifest = chrome.runtime.getManifest();
return ( return (
h('.flex-column.flex-grow', [ h('.flex-column.flex-grow', [
@ -27,7 +26,7 @@ InfoScreen.prototype.render = function() {
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', { h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
onClick: (event) => { onClick: (event) => {
state.dispatch(actions.goHome()) state.dispatch(actions.goHome())
} },
}), }),
h('h2.page-subtitle', 'Info'), h('h2.page-subtitle', 'Info'),
]), ]),
@ -37,96 +36,93 @@ InfoScreen.prototype.render = function() {
h('.flex-space-around', { h('.flex-space-around', {
style: { style: {
padding: '20px', padding: '20px',
} },
}, [ }, [
//current version number // current version number
h('.info.info-gray',[ h('.info.info-gray', [
h('div','Metamask'), h('div', 'Metamask'),
h('div', { h('div', {
style: { style: {
marginBottom: '10px', marginBottom: '10px',
} },
},`Version: ${manifest.version}`), }, `Version: ${manifest.version}`),
]), ]),
h('hr',{ h('hr', {
style: { style: {
margin:'20px 0 ', margin: '20px 0 ',
width: '7em', width: '7em',
} },
}), }),
h('.info', {
h('.info',{ style: {
style: { marginBottom: '20px',
marginBottom: '20px', }},
}},
`For more information on MetaMask `For more information on MetaMask
you can visit our web site. If you want to you can visit our web site. If you want to
contact us with questions or just contact us with questions or just
say 'Hi', you can find us on theise platforms:`), say 'Hi', you can find us on theise platforms:`),
h('div',{ h('div', {
style: { style: {
paddingLeft: '30px', paddingLeft: '30px',
}}, }},
[ [
h('div', [ h('div', [
h('a', { h('a', {
href: 'https://metamask.io/', href: 'https://metamask.io/',
target: '_blank', target: '_blank',
onClick(event) { this.navigateTo(event.target.href) }, onClick (event) { this.navigateTo(event.target.href) },
},[ }, [
h('img.icon-size', { h('img.icon-size', {
src: manifest.icons[128] src: manifest.icons[128],
}), }),
h('div.info',{ h('div.info', {
style: { style: {
fontWeight: 800, fontWeight: 800,
} },
},'Visit our web site') }, 'Visit our web site'),
]) ]),
]), ]),
h('div.fa.fa-slack', [ h('div.fa.fa-slack', [
h('a.info', { h('a.info', {
href: 'http://slack.metamask.io', href: 'http://slack.metamask.io',
target: '_blank', target: '_blank',
onClick(event) { this.navigateTo(event.target.href) }, onClick (event) { this.navigateTo(event.target.href) },
}, 'Join the conversation on Slack'), }, 'Join the conversation on Slack'),
]), ]),
h('div.fa.fa-twitter', [
h('div.fa.fa-twitter', [ h('a.info', {
h('a.info', { href: 'https://twitter.com/metamask_io',
href: 'https://twitter.com/metamask_io', target: '_blank',
target: '_blank', onClick (event) { this.navigateTo(event.target.href) },
onClick(event) { this.navigateTo(event.target.href) }, }, 'Follow us on Twitter'),
}, 'Follow us on Twitter'), ]),
]),
h('div.fa.fa-envelope', [
h('div.fa.fa-envelope', [ h('a.info', {
h('a.info', { href: 'mailto:hello@metamask.io?subject=Feedback',
href: 'mailto:hello@metamask.io?subject=Feedback', target: '_blank',
target: '_blank', }, 'Email us any questions or comments!'),
}, 'Email us any questions or comments!'), ]),
h('div.fa.fa-github', [
h('a.info', {
href: 'https://github.com/metamask/talk/issues',
target: '_blank',
onClick (event) { this.navigateTo(event.target.href) },
}, 'Start a thread on Github'),
]),
]), ]),
h('div.fa.fa-github', [
h('a.info', {
href: 'https://github.com/metamask/talk/issues',
target: '_blank',
onClick(event) { this.navigateTo(event.target.href) },
}, 'Start a thread on Github'),
]),
]),
]), ]),
]), ]),
]) ])
) )
} }
InfoScreen.prototype.navigateTo = function(url) { InfoScreen.prototype.navigateTo = function (url) {
chrome.tabs.create({ url }); chrome.tabs.create({ url })
} }

@ -2,23 +2,22 @@ const inherits = require('util').inherits
const Component = require('react').Component const Component = require('react').Component
const h = require('react-hyperscript') const h = require('react-hyperscript')
const connect = require('react-redux').connect const connect = require('react-redux').connect
const actions = require('./actions')
const ReactCSSTransitionGroup = require('react-addons-css-transition-group') const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
module.exports = connect(mapStateToProps)(LoadingIndicator) module.exports = connect(mapStateToProps)(LoadingIndicator)
function mapStateToProps(state) { function mapStateToProps (state) {
return { return {
isLoading: state.appState.isLoading, isLoading: state.appState.isLoading,
} }
} }
inherits(LoadingIndicator, Component) inherits(LoadingIndicator, Component)
function LoadingIndicator() { function LoadingIndicator () {
Component.call(this) Component.call(this)
} }
LoadingIndicator.prototype.render = function() { LoadingIndicator.prototype.render = function () {
var isLoading = this.props.isLoading var isLoading = this.props.isLoading
return ( return (
@ -38,7 +37,7 @@ LoadingIndicator.prototype.render = function() {
height: '100%', height: '100%',
width: '100%', width: '100%',
background: 'rgba(255, 255, 255, 0.5)', background: 'rgba(255, 255, 255, 0.5)',
} },
}, [ }, [
h('img', { h('img', {
src: 'images/loading.svg', src: 'images/loading.svg',

@ -7,13 +7,12 @@ const actions = require('../actions')
module.exports = connect(mapStateToProps)(RevealSeedConfirmatoin) module.exports = connect(mapStateToProps)(RevealSeedConfirmatoin)
inherits(RevealSeedConfirmatoin, Component) inherits(RevealSeedConfirmatoin, Component)
function RevealSeedConfirmatoin() { function RevealSeedConfirmatoin () {
Component.call(this) Component.call(this)
} }
function mapStateToProps(state) { function mapStateToProps (state) {
return { return {
warning: state.appState.warning, warning: state.appState.warning,
} }
@ -21,7 +20,7 @@ function mapStateToProps(state) {
RevealSeedConfirmatoin.prototype.confirmationPhrase = 'I understand' RevealSeedConfirmatoin.prototype.confirmationPhrase = 'I understand'
RevealSeedConfirmatoin.prototype.render = function() { RevealSeedConfirmatoin.prototype.render = function () {
const props = this.props const props = this.props
const state = this.state const state = this.state
@ -48,7 +47,7 @@ RevealSeedConfirmatoin.prototype.render = function() {
flexDirection: 'column', flexDirection: 'column',
padding: '20px', padding: '20px',
justifyContent: 'center', justifyContent: 'center',
} },
}, [ }, [
h('h4', 'Do not recover your seed words in a public place! These words can be used to steal all your accounts.'), h('h4', 'Do not recover your seed words in a public place! These words can be used to steal all your accounts.'),
@ -68,8 +67,8 @@ RevealSeedConfirmatoin.prototype.render = function() {
h(`h4${state && state.confirmationWrong ? '.error' : ''}`, { h(`h4${state && state.confirmationWrong ? '.error' : ''}`, {
style: { style: {
marginTop: '12px', marginTop: '12px',
} },
}, `Enter the phrase "I understand" to proceed.`), }, 'Enter the phrase "I understand" to proceed.'),
// confirm confirmation // confirm confirmation
h('input.large-input.letter-spacey', { h('input.large-input.letter-spacey', {
@ -105,7 +104,7 @@ RevealSeedConfirmatoin.prototype.render = function() {
h('span.error', { h('span.error', {
style: { style: {
margin: '20px', margin: '20px',
} },
}, props.warning.split('-')) }, props.warning.split('-'))
), ),
@ -117,24 +116,24 @@ RevealSeedConfirmatoin.prototype.render = function() {
) )
} }
RevealSeedConfirmatoin.prototype.componentDidMount = function(){ RevealSeedConfirmatoin.prototype.componentDidMount = function () {
document.getElementById('password-box').focus() document.getElementById('password-box').focus()
} }
RevealSeedConfirmatoin.prototype.goHome = function() { RevealSeedConfirmatoin.prototype.goHome = function () {
this.props.dispatch(actions.showConfigPage(false)) this.props.dispatch(actions.showConfigPage(false))
} }
// create vault // create vault
RevealSeedConfirmatoin.prototype.checkConfirmation = function(event) { RevealSeedConfirmatoin.prototype.checkConfirmation = function (event) {
if (event.key === 'Enter') { if (event.key === 'Enter') {
event.preventDefault() event.preventDefault()
this.revealSeedWords() this.revealSeedWords()
} }
} }
RevealSeedConfirmatoin.prototype.revealSeedWords = function(){ RevealSeedConfirmatoin.prototype.revealSeedWords = function () {
this.setState({ confirmationWrong: false }) this.setState({ confirmationWrong: false })
const confirmBox = document.getElementById('confirm-box') const confirmBox = document.getElementById('confirm-box')

@ -1,5 +1,3 @@
const combineReducers = require('redux').combineReducers
const actions = require('./actions')
const extend = require('xtend') const extend = require('xtend')
// //
@ -11,8 +9,7 @@ const reduceApp = require('./reducers/app')
module.exports = rootReducer module.exports = rootReducer
function rootReducer(state, action) { function rootReducer (state, action) {
// clone // clone
state = extend(state) state = extend(state)
@ -34,8 +31,6 @@ function rootReducer(state, action) {
state.appState = reduceApp(state, action) state.appState = reduceApp(state, action)
return state return state
} }

@ -1,12 +1,10 @@
const extend = require('xtend') const extend = require('xtend')
const actions = require('../actions') const actions = require('../actions')
const valuesFor = require('../util').valuesFor
const txHelper = require('../../lib/tx-helper') const txHelper = require('../../lib/tx-helper')
module.exports = reduceApp module.exports = reduceApp
function reduceApp(state, action) { function reduceApp (state, action) {
// clone and defaults // clone and defaults
const selectedAccount = state.metamask.selectedAccount const selectedAccount = state.metamask.selectedAccount
const pendingTxs = hasPendingTxs(state) const pendingTxs = hasPendingTxs(state)
@ -45,343 +43,341 @@ function reduceApp(state, action) {
switch (action.type) { switch (action.type) {
case actions.TOGGLE_MENU: case actions.TOGGLE_MENU:
return extend(appState, { return extend(appState, {
menuOpen: !appState.menuOpen, menuOpen: !appState.menuOpen,
}) })
case actions.SET_MENU_STATE: case actions.SET_MENU_STATE:
return extend(appState, { return extend(appState, {
menuOpen: action.value, menuOpen: action.value,
}) })
// intialize // intialize
case actions.SHOW_CREATE_VAULT: case actions.SHOW_CREATE_VAULT:
return extend(appState, { return extend(appState, {
currentView: { currentView: {
name: 'createVault', name: 'createVault',
}, },
transForward: true, transForward: true,
warning: null, warning: null,
}) })
case actions.SHOW_RESTORE_VAULT:
return extend(appState, {
currentView: {
name: 'restoreVault',
},
transForward: true,
})
case actions.SHOW_INIT_MENU:
return extend(appState, {
currentView: defaultView,
transForward: false,
})
case actions.SHOW_CONFIG_PAGE:
return extend(appState, {
currentView: {
name: 'config',
context: appState.currentView.context,
},
transForward: action.value,
})
case actions.SHOW_INFO_PAGE:
return extend(appState, {
currentView: {
name: 'info',
context: appState.currentView.context,
},
transForward: true,
})
case actions.CREATE_NEW_VAULT_IN_PROGRESS:
return extend(appState, {
currentView: {
name: 'createVault',
inProgress: true,
},
transForward: true,
isLoading: true,
})
case actions.SHOW_NEW_VAULT_SEED:
return extend(appState, {
currentView: {
name: 'createVaultComplete',
seedWords: action.value,
},
transForward: true,
isLoading: false,
})
case actions.SHOW_SEND_PAGE:
return extend(appState, {
currentView: {
name: 'sendTransaction',
context: appState.currentView.context,
},
transForward: true,
warning: null,
})
// unlock case actions.SHOW_RESTORE_VAULT:
return extend(appState, {
currentView: {
name: 'restoreVault',
},
transForward: true,
})
case actions.UNLOCK_METAMASK: case actions.SHOW_INIT_MENU:
return extend(appState, { return extend(appState, {
detailView: {}, currentView: defaultView,
transForward: true, transForward: false,
isLoading: false, })
warning: null,
})
case actions.LOCK_METAMASK:
return extend(appState, {
currentView: defaultView,
transForward: false,
warning: null,
})
// reveal seed words case actions.SHOW_CONFIG_PAGE:
return extend(appState, {
currentView: {
name: 'config',
context: appState.currentView.context,
},
transForward: action.value,
})
case actions.REVEAL_SEED_CONFIRMATION: case actions.SHOW_INFO_PAGE:
return extend(appState, { return extend(appState, {
currentView: { currentView: {
name: 'reveal-seed-conf', name: 'info',
}, context: appState.currentView.context,
transForward: true, },
warning: null, transForward: true,
}) })
case actions.CREATE_NEW_VAULT_IN_PROGRESS:
return extend(appState, {
currentView: {
name: 'createVault',
inProgress: true,
},
transForward: true,
isLoading: true,
})
// accounts case actions.SHOW_NEW_VAULT_SEED:
return extend(appState, {
currentView: {
name: 'createVaultComplete',
seedWords: action.value,
},
transForward: true,
isLoading: false,
})
case actions.SET_SELECTED_ACCOUNT: case actions.SHOW_SEND_PAGE:
return extend(appState, { return extend(appState, {
activeAddress: action.value, currentView: {
}) name: 'sendTransaction',
context: appState.currentView.context,
case actions.GO_HOME: },
return extend(appState, { transForward: true,
currentView: extend(appState.currentView, { warning: null,
name: 'accountDetail', })
}),
accountDetail: { // unlock
subview: 'transactions',
accountExport: 'none',
privateKey: '',
},
transForward: false,
warning: null,
})
case actions.SHOW_ACCOUNT_DETAIL:
return extend(appState, {
currentView: {
name: 'accountDetail',
context: action.value || account,
},
accountDetail: {
subview: 'transactions',
accountExport: 'none',
privateKey: '',
},
transForward: false,
})
case actions.BACK_TO_ACCOUNT_DETAIL:
return extend(appState, {
currentView: {
name: 'accountDetail',
context: action.value,
},
accountDetail: {
subview: 'transactions',
accountExport: 'none',
privateKey: '',
},
transForward: false,
})
case actions.SHOW_ACCOUNTS_PAGE:
var seedWords = state.metamask.seedWords
return extend(appState, {
currentView: {
name: seedWords ? 'createVaultComplete' : 'accounts',
seedWords,
},
transForward: true,
isLoading: false,
warning: null,
scrollToBottom: false,
})
case actions.REVEAL_ACCOUNT:
return extend(appState, {
scrollToBottom: true,
})
case actions.SHOW_CONF_TX_PAGE:
return extend(appState, {
currentView: {
name: 'confTx',
context: 0,
},
transForward: true,
warning: null,
})
case actions.SHOW_CONF_MSG_PAGE:
return extend(appState, {
currentView: {
name: 'confTx',
context: 0,
},
transForward: true,
warning: null,
})
case actions.COMPLETED_TX:
var unconfTxs = state.metamask.unconfTxs
var unconfMsgs = state.metamask.unconfMsgs
var unconfTxList = txHelper(unconfTxs, unconfMsgs)
.filter(tx => tx !== tx.id)
if (unconfTxList && unconfTxList.length > 0) { case actions.UNLOCK_METAMASK:
return extend(appState, { return extend(appState, {
detailView: {},
transForward: true,
isLoading: false,
warning: null,
})
case actions.LOCK_METAMASK:
return extend(appState, {
currentView: defaultView,
transForward: false, transForward: false,
warning: null,
})
// reveal seed words
case actions.REVEAL_SEED_CONFIRMATION:
return extend(appState, {
currentView: { currentView: {
name: 'confTx', name: 'reveal-seed-conf',
context: 0,
}, },
transForward: true,
warning: null, warning: null,
}) })
} else {
// accounts
case actions.SET_SELECTED_ACCOUNT:
return extend(appState, { return extend(appState, {
activeAddress: action.value,
})
case actions.GO_HOME:
return extend(appState, {
currentView: extend(appState.currentView, {
name: 'accountDetail',
}),
accountDetail: {
subview: 'transactions',
accountExport: 'none',
privateKey: '',
},
transForward: false, transForward: false,
warning: null, warning: null,
})
case actions.SHOW_ACCOUNT_DETAIL:
return extend(appState, {
currentView: { currentView: {
name: 'accountDetail', name: 'accountDetail',
context: state.metamask.selectedAddress, context: action.value,
}, },
accountDetail: { accountDetail: {
subview: 'transactions', subview: 'transactions',
accountExport: 'none',
privateKey: '',
}, },
transForward: false,
}) })
}
case actions.NEXT_TX: case actions.BACK_TO_ACCOUNT_DETAIL:
return extend(appState, { return extend(appState, {
transForward: true, currentView: {
currentView: { name: 'accountDetail',
name: 'confTx', context: action.value,
context: ++appState.currentView.context, },
accountDetail: {
subview: 'transactions',
accountExport: 'none',
privateKey: '',
},
transForward: false,
})
case actions.SHOW_ACCOUNTS_PAGE:
return extend(appState, {
currentView: {
name: seedWords ? 'createVaultComplete' : 'accounts',
seedWords,
},
transForward: true,
isLoading: false,
warning: null, warning: null,
} scrollToBottom: false,
}) })
case actions.VIEW_PENDING_TX: case actions.REVEAL_ACCOUNT:
const context = indexForPending(state, action.value) return extend(appState, {
return extend(appState, { scrollToBottom: true,
transForward: true, })
currentView: {
name: 'confTx', case actions.SHOW_CONF_TX_PAGE:
context, return extend(appState, {
currentView: {
name: 'confTx',
context: 0,
},
transForward: true,
warning: null, warning: null,
} })
})
case actions.SHOW_CONF_MSG_PAGE:
case actions.PREVIOUS_TX: return extend(appState, {
return extend(appState, { currentView: {
transForward: false, name: 'confTx',
currentView: { context: 0,
name: 'confTx', },
context: --appState.currentView.context, transForward: true,
warning: null, warning: null,
})
case actions.COMPLETED_TX:
var unconfTxs = state.metamask.unconfTxs
var unconfMsgs = state.metamask.unconfMsgs
var unconfTxList = txHelper(unconfTxs, unconfMsgs)
.filter(tx => tx !== tx.id)
if (unconfTxList && unconfTxList.length > 0) {
return extend(appState, {
transForward: false,
currentView: {
name: 'confTx',
context: 0,
},
warning: null,
})
} else {
return extend(appState, {
transForward: false,
warning: null,
currentView: {
name: 'accountDetail',
context: state.metamask.selectedAddress,
},
accountDetail: {
subview: 'transactions',
},
})
} }
})
case actions.NEXT_TX:
case actions.TRANSACTION_ERROR: return extend(appState, {
return extend(appState, { transForward: true,
currentView: { currentView: {
name: 'confTx', name: 'confTx',
errorMessage: 'There was a problem submitting this transaction.', context: ++appState.currentView.context,
}, warning: null,
}) },
})
case actions.UNLOCK_FAILED:
return extend(appState, { case actions.VIEW_PENDING_TX:
warning: 'Incorrect password. Try again.' const context = indexForPending(state, action.value)
}) return extend(appState, {
transForward: true,
case actions.SHOW_LOADING: currentView: {
return extend(appState, { name: 'confTx',
isLoading: true, context,
}) warning: null,
},
case actions.HIDE_LOADING: })
return extend(appState, {
isLoading: false, case actions.PREVIOUS_TX:
}) return extend(appState, {
transForward: false,
case actions.CLEAR_SEED_WORD_CACHE: currentView: {
return extend(appState, { name: 'confTx',
transForward: true, context: --appState.currentView.context,
currentView: {}, warning: null,
isLoading: false, },
accountDetail: { })
subview: 'transactions',
accountExport: 'none', case actions.TRANSACTION_ERROR:
privateKey: '', return extend(appState, {
}, currentView: {
}) name: 'confTx',
errorMessage: 'There was a problem submitting this transaction.',
case actions.DISPLAY_WARNING: },
return extend(appState, { })
warning: action.value,
}) case actions.UNLOCK_FAILED:
return extend(appState, {
case actions.HIDE_WARNING: warning: 'Incorrect password. Try again.',
return extend(appState, { })
warning: undefined,
}) case actions.SHOW_LOADING:
return extend(appState, {
case actions.REQUEST_ACCOUNT_EXPORT: isLoading: true,
return extend(appState, { })
transForward: true,
currentView: { case actions.HIDE_LOADING:
name: 'accountDetail', return extend(appState, {
context: appState.currentView.context, isLoading: false,
}, })
accountDetail: {
subview: 'export', case actions.CLEAR_SEED_WORD_CACHE:
accountExport: 'requested', return extend(appState, {
}, transForward: true,
}) currentView: {},
isLoading: false,
case actions.EXPORT_ACCOUNT: accountDetail: {
return extend(appState, { subview: 'transactions',
accountDetail: { accountExport: 'none',
subview: 'export', privateKey: '',
accountExport: 'completed', },
}, })
})
case actions.DISPLAY_WARNING:
case actions.SHOW_PRIVATE_KEY: return extend(appState, {
return extend(appState, { warning: action.value,
accountDetail: { })
subview: 'export',
accountExport: 'completed', case actions.HIDE_WARNING:
privateKey: action.value, return extend(appState, {
}, warning: undefined,
}) })
default: case actions.REQUEST_ACCOUNT_EXPORT:
return appState return extend(appState, {
transForward: true,
currentView: {
name: 'accountDetail',
context: appState.currentView.context,
},
accountDetail: {
subview: 'export',
accountExport: 'requested',
},
})
case actions.EXPORT_ACCOUNT:
return extend(appState, {
accountDetail: {
subview: 'export',
accountExport: 'completed',
},
})
case actions.SHOW_PRIVATE_KEY:
return extend(appState, {
accountDetail: {
subview: 'export',
accountExport: 'completed',
privateKey: action.value,
},
})
default:
return appState
} }
} }
@ -392,7 +388,7 @@ function hasPendingTxs (state) {
return unconfTxList.length > 0 return unconfTxList.length > 0
} }
function indexForPending(state, txId) { function indexForPending (state, txId) {
var unconfTxs = state.metamask.unconfTxs var unconfTxs = state.metamask.unconfTxs
var unconfMsgs = state.metamask.unconfMsgs var unconfMsgs = state.metamask.unconfMsgs
var unconfTxList = txHelper(unconfTxs, unconfMsgs) var unconfTxList = txHelper(unconfTxs, unconfMsgs)

@ -1,10 +1,8 @@
const extend = require('xtend') const extend = require('xtend')
const actions = require('../actions')
module.exports = reduceIdentities module.exports = reduceIdentities
function reduceIdentities(state, action) { function reduceIdentities (state, action) {
// clone + defaults // clone + defaults
var idState = extend({ var idState = extend({
@ -14,5 +12,4 @@ function reduceIdentities(state, action) {
default: default:
return idState return idState
} }
} }

@ -3,7 +3,8 @@ const actions = require('../actions')
module.exports = reduceMetamask module.exports = reduceMetamask
function reduceMetamask(state, action) { function reduceMetamask (state, action) {
let newState
// clone + defaults // clone + defaults
var metamaskState = extend({ var metamaskState = extend({
@ -17,99 +18,99 @@ function reduceMetamask(state, action) {
switch (action.type) { switch (action.type) {
case actions.SHOW_ACCOUNTS_PAGE: case actions.SHOW_ACCOUNTS_PAGE:
var state = extend(metamaskState) newState = extend(metamaskState)
delete state.seedWords delete newState.seedWords
return state return newState
case actions.UPDATE_METAMASK_STATE: case actions.UPDATE_METAMASK_STATE:
return extend(metamaskState, action.value) return extend(metamaskState, action.value)
case actions.AGREE_TO_DISCLAIMER: case actions.AGREE_TO_DISCLAIMER:
return extend(metamaskState, { return extend(metamaskState, {
isConfirmed: true, isConfirmed: true,
}) })
case actions.UNLOCK_METAMASK: case actions.UNLOCK_METAMASK:
return extend(metamaskState, { return extend(metamaskState, {
isUnlocked: true, isUnlocked: true,
isInitialized: true, isInitialized: true,
selectedAccount: action.value, selectedAccount: action.value,
}) })
case actions.LOCK_METAMASK: case actions.LOCK_METAMASK:
return extend(metamaskState, { return extend(metamaskState, {
isUnlocked: false, isUnlocked: false,
}) })
case actions.SET_RPC_TARGET: case actions.SET_RPC_TARGET:
return extend(metamaskState, { return extend(metamaskState, {
provider: { provider: {
type: 'rpc', type: 'rpc',
rpcTarget: action.value, rpcTarget: action.value,
}, },
}) })
case actions.SET_PROVIDER_TYPE: case actions.SET_PROVIDER_TYPE:
return extend(metamaskState, { return extend(metamaskState, {
provider: { provider: {
type: action.value, type: action.value,
}, },
}) })
case actions.COMPLETED_TX: case actions.COMPLETED_TX:
var stringId = String(action.id) var stringId = String(action.id)
var newState = extend(metamaskState, { newState = extend(metamaskState, {
unconfTxs: {}, unconfTxs: {},
unconfMsgs: {}, unconfMsgs: {},
}) })
for (var id in metamaskState.unconfTxs) { for (const id in metamaskState.unconfTxs) {
if (id !== stringId) { if (id !== stringId) {
newState.unconfTxs[id] = metamaskState.unconfTxs[id] newState.unconfTxs[id] = metamaskState.unconfTxs[id]
}
} }
} for (const id in metamaskState.unconfMsgs) {
for (var id in metamaskState.unconfMsgs) { if (id !== stringId) {
if (id !== stringId) { newState.unconfMsgs[id] = metamaskState.unconfMsgs[id]
newState.unconfMsgs[id] = metamaskState.unconfMsgs[id] }
} }
} return newState
return newState
case actions.SHOW_NEW_VAULT_SEED:
case actions.SHOW_NEW_VAULT_SEED: return extend(metamaskState, {
return extend(metamaskState, { isUnlocked: true,
isUnlocked: true, isInitialized: false,
isInitialized: false, })
})
case actions.CLEAR_SEED_WORD_CACHE:
case actions.CLEAR_SEED_WORD_CACHE: newState = extend(metamaskState, {
var newState = extend(metamaskState, { isUnlocked: true,
isUnlocked: true, isInitialized: true,
isInitialized: true, selectedAccount: action.value,
selectedAccount: action.value, })
}) delete newState.seedWords
delete newState.seedWords return newState
return newState
case actions.SHOW_ACCOUNT_DETAIL:
case actions.SHOW_ACCOUNT_DETAIL: newState = extend(metamaskState, {
const newState = extend(metamaskState, { isUnlocked: true,
isUnlocked: true, isInitialized: true,
isInitialized: true, selectedAccount: action.value,
selectedAccount: action.value, selectedAddress: action.value,
selectedAddress: action.value, })
}) delete newState.seedWords
delete newState.seedWords return newState
return newState
case actions.SAVE_ACCOUNT_LABEL:
case actions.SAVE_ACCOUNT_LABEL: const account = action.value.account
const account = action.value.account const name = action.value.label
const name = action.value.label var id = {}
var id = {} id[account] = extend(metamaskState.identities[account], { name })
id[account] = extend(metamaskState.identities[account], { name }) var identities = extend(metamaskState.identities, id)
var identities = extend(metamaskState.identities, id) return extend(metamaskState, { identities })
return extend(metamaskState, { identities })
default:
default: return metamaskState
return metamaskState
} }
} }

@ -1,5 +1,4 @@
const inherits = require('util').inherits const inherits = require('util').inherits
const React = require('react')
const Component = require('react').Component const Component = require('react').Component
const Provider = require('react-redux').Provider const Provider = require('react-redux').Provider
const h = require('react-hyperscript') const h = require('react-hyperscript')
@ -7,17 +6,16 @@ const App = require('./app')
module.exports = Root module.exports = Root
inherits(Root, Component) inherits(Root, Component)
function Root() { Component.call(this) } function Root () { Component.call(this) }
Root.prototype.render = function() { Root.prototype.render = function () {
return ( return (
h(Provider, { h(Provider, {
store: this.props.store, store: this.props.store,
}, [ }, [
h(App) h(App),
]) ])
) )

@ -6,14 +6,13 @@ const Identicon = require('./components/identicon')
const actions = require('./actions') const actions = require('./actions')
const util = require('./util') const util = require('./util')
const numericBalance = require('./util').numericBalance const numericBalance = require('./util').numericBalance
const formatBalance = require('./util').formatBalance
const addressSummary = require('./util').addressSummary const addressSummary = require('./util').addressSummary
const EtherBalance = require('./components/eth-balance') const EtherBalance = require('./components/eth-balance')
const ethUtil = require('ethereumjs-util') const ethUtil = require('ethereumjs-util')
module.exports = connect(mapStateToProps)(SendTransactionScreen) module.exports = connect(mapStateToProps)(SendTransactionScreen)
function mapStateToProps(state) { function mapStateToProps (state) {
var result = { var result = {
address: state.metamask.selectedAccount, address: state.metamask.selectedAccount,
accounts: state.metamask.accounts, accounts: state.metamask.accounts,
@ -31,11 +30,11 @@ function mapStateToProps(state) {
} }
inherits(SendTransactionScreen, Component) inherits(SendTransactionScreen, Component)
function SendTransactionScreen() { function SendTransactionScreen () {
Component.call(this) Component.call(this)
} }
SendTransactionScreen.prototype.render = function() { SendTransactionScreen.prototype.render = function () {
var state = this.props var state = this.props
var address = state.address var address = state.address
var account = state.account var account = state.account
@ -111,7 +110,7 @@ SendTransactionScreen.prototype.render = function() {
// h('div', formatBalance(account && account.balance)), // h('div', formatBalance(account && account.balance)),
h(EtherBalance, { h(EtherBalance, {
value: account && account.balance, value: account && account.balance,
}) }),
]), ]),
@ -140,7 +139,7 @@ SendTransactionScreen.prototype.render = function() {
h('input.large-input', { h('input.large-input', {
name: 'address', name: 'address',
placeholder: 'Recipient Address', placeholder: 'Recipient Address',
}) }),
]), ]),
// 'amount' and send button // 'amount' and send button
@ -160,7 +159,7 @@ SendTransactionScreen.prototype.render = function() {
style: { style: {
textTransform: 'uppercase', textTransform: 'uppercase',
}, },
}, 'Send') }, 'Send'),
]), ]),
@ -187,7 +186,7 @@ SendTransactionScreen.prototype.render = function() {
style: { style: {
width: '100%', width: '100%',
resize: 'none', resize: 'none',
} },
}), }),
]), ]),
@ -196,31 +195,31 @@ SendTransactionScreen.prototype.render = function() {
) )
} }
SendTransactionScreen.prototype.navigateToAccounts = function(event){ SendTransactionScreen.prototype.navigateToAccounts = function (event) {
event.stopPropagation() event.stopPropagation()
this.props.dispatch(actions.showAccountsPage()) this.props.dispatch(actions.showAccountsPage())
} }
SendTransactionScreen.prototype.back = function() { SendTransactionScreen.prototype.back = function () {
var address = this.props.address var address = this.props.address
this.props.dispatch(actions.backToAccountDetail(address)) this.props.dispatch(actions.backToAccountDetail(address))
} }
SendTransactionScreen.prototype.onSubmit = function() { SendTransactionScreen.prototype.onSubmit = function () {
const recipient = document.querySelector('input[name="address"]').value const recipient = document.querySelector('input[name="address"]').value
const input = document.querySelector('input[name="amount"]').value const input = document.querySelector('input[name="amount"]').value
const value = util.normalizeEthStringToWei(input) const value = util.normalizeEthStringToWei(input)
const txData = document.querySelector('input[name="txData"]').value const txData = document.querySelector('input[name="txData"]').value
const balance = this.props.balance const balance = this.props.balance
let message
if (value.gt(balance)) { if (value.gt(balance)) {
var message = 'Insufficient funds.' message = 'Insufficient funds.'
return this.props.dispatch(actions.displayWarning(message)) return this.props.dispatch(actions.displayWarning(message))
} }
if ((!util.isValidAddress(recipient) && !txData) || (!recipient && !txData)) { if ((!util.isValidAddress(recipient) && !txData) || (!recipient && !txData)) {
var message = 'Recipient address is invalid.' message = 'Recipient address is invalid.'
return this.props.dispatch(actions.displayWarning(message)) return this.props.dispatch(actions.displayWarning(message))
} }

@ -2,28 +2,20 @@ const inherits = require('util').inherits
const Component = require('react').Component const Component = require('react').Component
const h = require('react-hyperscript') const h = require('react-hyperscript')
const connect = require('react-redux').connect const connect = require('react-redux').connect
const copyToClipboard = require('copy-to-clipboard')
const actions = require('./actions') const actions = require('./actions')
const AccountPanel = require('./components/account-panel')
module.exports = connect(mapStateToProps)(AppSettingsPage) module.exports = connect(mapStateToProps)(AppSettingsPage)
function mapStateToProps(state) { function mapStateToProps (state) {
return { return {}
identities: state.metamask.identities,
address: state.appState.currentView.context,
}
} }
inherits(AppSettingsPage, Component) inherits(AppSettingsPage, Component)
function AppSettingsPage() { function AppSettingsPage () {
Component.call(this) Component.call(this)
} }
AppSettingsPage.prototype.render = function () {
AppSettingsPage.prototype.render = function() {
var state = this.props
var identity = state.identities[state.address]
return ( return (
h('.account-detail-section.flex-column.flex-grow', [ h('.account-detail-section.flex-column.flex-grow', [
@ -47,23 +39,22 @@ AppSettingsPage.prototype.render = function() {
}), }),
]) ])
) )
} }
AppSettingsPage.prototype.componentDidMount = function(){ AppSettingsPage.prototype.componentDidMount = function () {
document.querySelector('input').focus() document.querySelector('input').focus()
} }
AppSettingsPage.prototype.onKeyPress = function(event) { AppSettingsPage.prototype.onKeyPress = function (event) {
// get submit event // get submit event
if (event.key === 'Enter') { if (event.key === 'Enter') {
// this.submitPassword(event) // this.submitPassword(event)
} }
} }
AppSettingsPage.prototype.navigateToAccounts = function (event) {
AppSettingsPage.prototype.navigateToAccounts = function(event){
event.stopPropagation() event.stopPropagation()
this.props.dispatch(actions.showAccountsPage()) this.props.dispatch(actions.showAccountsPage())
} }

@ -6,7 +6,6 @@ const rootReducer = require('./reducers')
module.exports = configureStore module.exports = configureStore
const loggerMiddleware = createLogger() const loggerMiddleware = createLogger()
const createStoreWithMiddleware = applyMiddleware( const createStoreWithMiddleware = applyMiddleware(
@ -14,6 +13,6 @@ const createStoreWithMiddleware = applyMiddleware(
loggerMiddleware loggerMiddleware
)(createStore) )(createStore)
function configureStore(initialState) { function configureStore (initialState) {
return createStoreWithMiddleware(rootReducer, initialState) return createStoreWithMiddleware(rootReducer, initialState)
} }

@ -2,29 +2,28 @@ const inherits = require('util').inherits
const Component = require('react').Component const Component = require('react').Component
const h = require('react-hyperscript') const h = require('react-hyperscript')
const connect = require('react-redux').connect const connect = require('react-redux').connect
const actions = require('./actions')
module.exports = connect(mapStateToProps)(COMPONENTNAME) module.exports = connect(mapStateToProps)(COMPONENTNAME)
function mapStateToProps(state) { function mapStateToProps (state) {
return {} return {}
} }
inherits(COMPONENTNAME, Component) inherits(COMPONENTNAME, Component)
function COMPONENTNAME() { function COMPONENTNAME () {
Component.call(this) Component.call(this)
} }
COMPONENTNAME.prototype.render = function() { COMPONENTNAME.prototype.render = function () {
const props = this.props const props = this.props
return ( return (
h('div', { h('div', {
style: { style: {
background: 'blue', background: 'blue',
} },
}, [ }, [
'Hello, world!' `Hello, ${props.sender}`,
]) ])
) )
} }

@ -9,20 +9,19 @@ const EventEmitter = require('events').EventEmitter
module.exports = connect(mapStateToProps)(UnlockScreen) module.exports = connect(mapStateToProps)(UnlockScreen)
inherits(UnlockScreen, Component) inherits(UnlockScreen, Component)
function UnlockScreen() { function UnlockScreen () {
Component.call(this) Component.call(this)
this.animationEventEmitter = new EventEmitter() this.animationEventEmitter = new EventEmitter()
} }
function mapStateToProps(state) { function mapStateToProps (state) {
return { return {
warning: state.appState.warning, warning: state.appState.warning,
} }
} }
UnlockScreen.prototype.render = function() { UnlockScreen.prototype.render = function () {
const state = this.props const state = this.props
const warning = state.warning const warning = state.warning
return ( return (
@ -55,7 +54,7 @@ UnlockScreen.prototype.render = function() {
h('.error', { h('.error', {
style: { style: {
display: warning ? 'block' : 'none', display: warning ? 'block' : 'none',
} },
}, warning), }, warning),
h('button.primary.cursor-pointer', { h('button.primary.cursor-pointer', {
@ -70,23 +69,23 @@ UnlockScreen.prototype.render = function() {
) )
} }
UnlockScreen.prototype.componentDidMount = function(){ UnlockScreen.prototype.componentDidMount = function () {
document.getElementById('password-box').focus() document.getElementById('password-box').focus()
} }
UnlockScreen.prototype.onSubmit = function(event) { UnlockScreen.prototype.onSubmit = function (event) {
const input = document.getElementById('password-box') const input = document.getElementById('password-box')
const password = input.value const password = input.value
this.props.dispatch(actions.tryUnlockMetamask(password)) this.props.dispatch(actions.tryUnlockMetamask(password))
} }
UnlockScreen.prototype.onKeyPress = function(event) { UnlockScreen.prototype.onKeyPress = function (event) {
if (event.key === 'Enter') { if (event.key === 'Enter') {
this.submitPassword(event) this.submitPassword(event)
} }
} }
UnlockScreen.prototype.submitPassword = function(event){ UnlockScreen.prototype.submitPassword = function (event) {
var element = event.target var element = event.target
var password = element.value var password = element.value
// reset input // reset input
@ -94,7 +93,7 @@ UnlockScreen.prototype.submitPassword = function(event){
this.props.dispatch(actions.tryUnlockMetamask(password)) this.props.dispatch(actions.tryUnlockMetamask(password))
} }
UnlockScreen.prototype.inputChanged = function(event){ UnlockScreen.prototype.inputChanged = function (event) {
// tell mascot to look at page action // tell mascot to look at page action
var element = event.target var element = event.target
var boundingRect = element.getBoundingClientRect() var boundingRect = element.getBoundingClientRect()
@ -105,6 +104,6 @@ UnlockScreen.prototype.inputChanged = function(event){
}) })
} }
UnlockScreen.prototype.emitAnim = function(name, a, b, c){ UnlockScreen.prototype.emitAnim = function (name, a, b, c) {
this.animationEventEmitter.emit(name, a, b, c) this.animationEventEmitter.emit(name, a, b, c)
} }

@ -1,17 +1,17 @@
const ethUtil = require('ethereumjs-util') const ethUtil = require('ethereumjs-util')
var valueTable = { var valueTable = {
wei: '1000000000000000000', wei: '1000000000000000000',
kwei: '1000000000000000', kwei: '1000000000000000',
mwei: '1000000000000', mwei: '1000000000000',
gwei: '1000000000', gwei: '1000000000',
szabo: '1000000', szabo: '1000000',
finney:'1000', finney: '1000',
ether: '1', ether: '1',
kether:'0.001', kether: '0.001',
mether:'0.000001', mether: '0.000001',
gether:'0.000000001', gether: '0.000000001',
tether:'0.000000000001', tether: '0.000000000001',
} }
var bnTable = {} var bnTable = {}
for (var currency in valueTable) { for (var currency in valueTable) {
@ -37,25 +37,24 @@ module.exports = {
bnTable: bnTable, bnTable: bnTable,
} }
function valuesFor (obj) {
function valuesFor(obj) {
if (!obj) return [] if (!obj) return []
return Object.keys(obj) return Object.keys(obj)
.map(function(key){ return obj[key] }) .map(function (key) { return obj[key] })
} }
function addressSummary(address) { function addressSummary (address) {
if (!address) return '' if (!address) return ''
var checked = ethUtil.toChecksumAddress(address) var checked = ethUtil.toChecksumAddress(address)
return checked ? checked.slice(0,2+8)+'...'+checked.slice(-4) : '...' return checked ? checked.slice(0, 2 + 8) + '...' + checked.slice(-4) : '...'
} }
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) {
if (!address) return true if (!address) return true
var lower = address.toLowerCase() var lower = address.toLowerCase()
var upper = address.toUpperCase() var upper = address.toUpperCase()
@ -63,81 +62,81 @@ function isAllOneCase(address) {
} }
// Takes wei Hex, returns wei BN, even if input is null // Takes wei Hex, returns wei BN, even if input is null
function numericBalance(balance) { function numericBalance (balance) {
if (!balance) return new ethUtil.BN(0, 16) if (!balance) return new ethUtil.BN(0, 16)
var stripped = ethUtil.stripHexPrefix(balance) var stripped = ethUtil.stripHexPrefix(balance)
return new ethUtil.BN(stripped, 16) return new ethUtil.BN(stripped, 16)
} }
// Takes eth BN, returns BN wei // Takes eth BN, returns BN wei
function ethToWei(bn) { function ethToWei (bn) {
var eth = new ethUtil.BN('1000000000000000000') var eth = new ethUtil.BN('1000000000000000000')
var wei = bn.mul(eth) var wei = bn.mul(eth)
return wei return wei
} }
// Takes BN in Wei, returns BN in eth // Takes BN in Wei, returns BN in eth
function weiToEth(bn) { function weiToEth (bn) {
var diff = new ethUtil.BN('1000000000000000000') var diff = new ethUtil.BN('1000000000000000000')
var eth = bn.div(diff) var eth = bn.div(diff)
return eth return eth
} }
// Takes hex, returns [beforeDecimal, afterDecimal] // Takes hex, returns [beforeDecimal, afterDecimal]
function parseBalance(balance) { function parseBalance (balance) {
let beforeDecimal, afterDecimal var beforeDecimal, afterDecimal
let wei = numericBalance(balance).toString() const wei = numericBalance(balance).toString()
let trailingZeros = /0+$/ const trailingZeros = /0+$/
beforeDecimal = wei.length > 18 ? wei.slice(0, wei.length - 18) : '0' beforeDecimal = wei.length > 18 ? wei.slice(0, wei.length - 18) : '0'
afterDecimal = ("000000000000000000" + wei).slice(-18).replace(trailingZeros, "") afterDecimal = ('000000000000000000' + wei).slice(-18).replace(trailingZeros, '')
if(afterDecimal == ""){afterDecimal = "0" } if (afterDecimal === '') { afterDecimal = '0' }
return [beforeDecimal, afterDecimal] return [beforeDecimal, afterDecimal]
} }
// Takes wei hex, returns "None" or "${formattedAmount} ETH" // Takes wei hex, returns "None" or "${formattedAmount} ETH"
function formatBalance(balance, decimalsToKeep) { function formatBalance (balance, decimalsToKeep) {
var parsed = parseBalance(balance) var parsed = parseBalance(balance)
var beforeDecimal = parsed[0] var beforeDecimal = parsed[0]
var afterDecimal = parsed[1] var afterDecimal = parsed[1]
var formatted = "None" var formatted = 'None'
if(decimalsToKeep === undefined){ if (decimalsToKeep === undefined) {
if(beforeDecimal === '0'){ if (beforeDecimal === '0') {
if(afterDecimal !== '0'){ if (afterDecimal !== '0') {
var sigFigs = afterDecimal.match(/^0*(.{2})/) //default: grabs 2 most significant digits var sigFigs = afterDecimal.match(/^0*(.{2})/) // default: grabs 2 most significant digits
if(sigFigs){afterDecimal = sigFigs[0]} if (sigFigs) { afterDecimal = sigFigs[0] }
formatted = '0.' + afterDecimal + ' ETH' formatted = '0.' + afterDecimal + ' ETH'
} }
}else{ } else {
formatted = beforeDecimal + "." + afterDecimal.slice(0,3) + ' ETH' formatted = beforeDecimal + '.' + afterDecimal.slice(0, 3) + ' ETH'
} }
}else{ } else {
afterDecimal += Array(decimalsToKeep).join("0") afterDecimal += Array(decimalsToKeep).join('0')
formatted = beforeDecimal + "." + afterDecimal.slice(0,decimalsToKeep) + ' ETH' formatted = beforeDecimal + '.' + afterDecimal.slice(0, decimalsToKeep) + ' ETH'
} }
return formatted return formatted
} }
function dataSize(data) { function dataSize (data) {
var size = data ? ethUtil.stripHexPrefix(data).length : 0 var size = data ? ethUtil.stripHexPrefix(data).length : 0
return size+' bytes' return size + ' bytes'
} }
// Takes a BN and an ethereum currency name, // Takes a BN and an ethereum currency name,
// returns a BN in wei // returns a BN in wei
function normalizeToWei(amount, currency) { function normalizeToWei (amount, currency) {
try { try {
return amount.mul(bnTable.wei).div(bnTable[currency]) return amount.mul(bnTable.wei).div(bnTable[currency])
} catch (e) {} } catch (e) {}
return amount return amount
} }
function normalizeEthStringToWei(str) { function normalizeEthStringToWei (str) {
const parts = str.split('.') const parts = str.split('.')
let eth = new ethUtil.BN(parts[0], 10).mul(bnTable.wei) let eth = new ethUtil.BN(parts[0], 10).mul(bnTable.wei)
if (parts[1]) { if (parts[1]) {
var decimal = parts[1] var decimal = parts[1]
while(decimal.length < 18) { while (decimal.length < 18) {
decimal += '0' decimal += '0'
} }
const decimalBN = new ethUtil.BN(decimal, 10) const decimalBN = new ethUtil.BN(decimal, 10)
@ -147,22 +146,22 @@ function normalizeEthStringToWei(str) {
} }
var multiple = new ethUtil.BN('10000', 10) var multiple = new ethUtil.BN('10000', 10)
function normalizeNumberToWei(n, currency) { function normalizeNumberToWei (n, currency) {
var enlarged = n * 10000 var enlarged = n * 10000
var amount = new ethUtil.BN(String(enlarged), 10) var amount = new ethUtil.BN(String(enlarged), 10)
return normalizeToWei(amount, currency).div(multiple) return normalizeToWei(amount, currency).div(multiple)
} }
function readableDate(ms) { function readableDate (ms) {
var date = new Date(ms) var date = new Date(ms)
var month = date.getMonth() var month = date.getMonth()
var day = date.getDate() var day = date.getDate()
var year = date.getFullYear() var year = date.getFullYear()
var hours = date.getHours() var hours = date.getHours()
var minutes = "0" + date.getMinutes() var minutes = '0' + date.getMinutes()
var seconds = "0" + date.getSeconds() var seconds = '0' + date.getSeconds()
var date = `${month}/${day}/${year}` var dateStr = `${month}/${day}/${year}`
var time = `${hours}:${minutes.substr(-2)}:${seconds.substr(-2)}` var time = `${hours}:${minutes.substr(-2)}:${seconds.substr(-2)}`
return `${date} ${time}` return `${dateStr} ${time}`
} }

@ -1,25 +1,26 @@
const fs = require('fs') const fs = require('fs')
const path = require('path')
module.exports = bundleCss module.exports = bundleCss
var cssFiles = { var cssFiles = {
'fonts.css': fs.readFileSync(__dirname+'/app/css/fonts.css', 'utf8'), 'fonts.css': fs.readFileSync(path.join(__dirname, '/app/css/fonts.css'), 'utf8'),
'reset.css': fs.readFileSync(__dirname+'/app/css/reset.css', 'utf8'), 'reset.css': fs.readFileSync(path.join(__dirname, '/app/css/reset.css'), 'utf8'),
'lib.css': fs.readFileSync(__dirname+'/app/css/lib.css', 'utf8'), 'lib.css': fs.readFileSync(path.join(__dirname, '/app/css/lib.css'), 'utf8'),
'index.css': fs.readFileSync(__dirname+'/app/css/index.css', 'utf8'), 'index.css': fs.readFileSync(path.join(__dirname, '/app/css/index.css'), 'utf8'),
'transitions.css': fs.readFileSync(__dirname+'/app/css/transitions.css', 'utf8'), 'transitions.css': fs.readFileSync(path.join(__dirname, '/app/css/transitions.css'), 'utf8'),
} }
function bundleCss() { function bundleCss () {
var cssBundle = Object.keys(cssFiles).reduce(function(bundle, fileName){ var cssBundle = Object.keys(cssFiles).reduce(function (bundle, fileName) {
var fileContent = cssFiles[fileName] var fileContent = cssFiles[fileName]
var output = String() var output = String()
output += '/*========== '+fileName+' ==========*/\n\n' output += '/*========== ' + fileName + ' ==========*/\n\n'
output += fileContent output += fileContent
output += '\n\n' output += '\n\n'
return bundle+output return bundle + output
}, String()) }, String())
return cssBundle return cssBundle

@ -26,7 +26,7 @@ var identities = {
address: '0x333462427bcc9133bb46e88bcbe39cd7ef0e7333', address: '0x333462427bcc9133bb46e88bcbe39cd7ef0e7333',
balance: 0.000001, balance: 0.000001,
txCount: 1, txCount: 1,
} },
} }
var unconfTxs = {} var unconfTxs = {}
@ -42,7 +42,7 @@ addUnconfTx({
data: '0x000462427bcc9133bb46e88bcbe39cd7ef0e7000', data: '0x000462427bcc9133bb46e88bcbe39cd7ef0e7000',
}) })
function addUnconfTx(txParams){ function addUnconfTx (txParams) {
var time = (new Date()).getTime() var time = (new Date()).getTime()
var id = createRandomId() var id = createRandomId()
unconfTxs[id] = { unconfTxs[id] = {
@ -55,7 +55,7 @@ function addUnconfTx(txParams){
var isUnlocked = false var isUnlocked = false
var selectedAddress = null var selectedAddress = null
function getState(){ function getState () {
return { return {
isUnlocked: isUnlocked, isUnlocked: isUnlocked,
identities: isUnlocked ? identities : {}, identities: isUnlocked ? identities : {},
@ -66,16 +66,16 @@ function getState(){
var accountManager = new EventEmitter() var accountManager = new EventEmitter()
accountManager.getState = function(cb){ accountManager.getState = function (cb) {
cb(null, getState()) cb(null, getState())
} }
accountManager.setLocked = function(){ accountManager.setLocked = function () {
isUnlocked = false isUnlocked = false
this._didUpdate() this._didUpdate()
} }
accountManager.submitPassword = function(password, cb){ accountManager.submitPassword = function (password, cb) {
if (password === 'test') { if (password === 'test') {
isUnlocked = true isUnlocked = true
cb(null, getState()) cb(null, getState())
@ -85,17 +85,17 @@ accountManager.submitPassword = function(password, cb){
} }
} }
accountManager.setSelectedAddress = function(address, cb){ accountManager.setSelectedAddress = function (address, cb) {
selectedAddress = address selectedAddress = address
cb(null, getState()) cb(null, getState())
this._didUpdate() this._didUpdate()
} }
accountManager.signTransaction = function(txParams, cb){ accountManager.signTransaction = function (txParams, cb) {
alert('signing tx....') alert('signing tx....')
} }
accountManager._didUpdate = function(){ accountManager._didUpdate = function () {
this.emit('update', getState()) this.emit('update', getState())
} }
@ -106,18 +106,18 @@ var container = document.getElementById('app-content')
var css = MetaMaskUiCss() var css = MetaMaskUiCss()
injectCss(css) injectCss(css)
var app = MetaMaskUi({ MetaMaskUi({
container: container, container: container,
accountManager: accountManager accountManager: accountManager,
}) })
// util // util
function createRandomId(){ function createRandomId () {
// 13 time digits // 13 time digits
var datePart = new Date().getTime()*Math.pow(10, 3) var datePart = new Date().getTime() * Math.pow(10, 3)
// 3 random digits // 3 random digits
var extraPart = Math.floor(Math.random()*Math.pow(10, 3)) var extraPart = Math.floor(Math.random() * Math.pow(10, 3))
// 16 digits // 16 digits
return datePart+extraPart return datePart + extraPart
} }

@ -1,28 +1,23 @@
const React = require('react')
const render = require('react-dom').render const render = require('react-dom').render
const h = require('react-hyperscript') const h = require('react-hyperscript')
const extend = require('xtend')
const Root = require('./app/root') const Root = require('./app/root')
const actions = require('./app/actions') const actions = require('./app/actions')
const configureStore = require('./app/store') const configureStore = require('./app/store')
module.exports = launchApp module.exports = launchApp
function launchApp(opts) { function launchApp (opts) {
var accountManager = opts.accountManager var accountManager = opts.accountManager
actions._setAccountManager(accountManager) actions._setAccountManager(accountManager)
// check if we are unlocked first // check if we are unlocked first
accountManager.getState(function(err, metamaskState){ accountManager.getState(function (err, metamaskState) {
if (err) throw err if (err) throw err
startApp(metamaskState, accountManager, opts) startApp(metamaskState, accountManager, opts)
}) })
} }
function startApp(metamaskState, accountManager, opts){ function startApp (metamaskState, accountManager, opts) {
// parse opts // parse opts
var store = configureStore({ var store = configureStore({
@ -43,12 +38,7 @@ function startApp(metamaskState, accountManager, opts){
store.dispatch(actions.showConfTxPage()) store.dispatch(actions.showConfTxPage())
} }
// if unconfirmed messages, start on msgConf page accountManager.on('update', function (metamaskState) {
if (Object.keys(metamaskState.unconfMsgs || {}).length) {
store.dispatch(actions.showConfTxPage())
}
accountManager.on('update', function(metamaskState){
store.dispatch(actions.updateMetamaskState(metamaskState)) store.dispatch(actions.updateMetamaskState(metamaskState))
}) })
@ -59,5 +49,4 @@ function startApp(metamaskState, accountManager, opts){
store: store, store: store,
} }
), opts.container) ), opts.container)
} }

@ -1,4 +1,4 @@
module.exports = function(hash, network) { module.exports = function (hash, network) {
const net = parseInt(network) const net = parseInt(network)
let prefix let prefix
switch (net) { switch (net) {

@ -1,18 +1,18 @@
var iconFactory var iconFactory
module.exports = function(jazzicon) { module.exports = function (jazzicon) {
if (!iconFactory) { if (!iconFactory) {
iconFactory = new IconFactory(jazzicon) iconFactory = new IconFactory(jazzicon)
} }
return iconFactory return iconFactory
} }
function IconFactory(jazzicon) { function IconFactory (jazzicon) {
this.jazzicon = jazzicon this.jazzicon = jazzicon
this.cache = {} this.cache = {}
} }
IconFactory.prototype.iconForAddress = function(address, diameter) { IconFactory.prototype.iconForAddress = function (address, diameter) {
if (this.isCached(address, diameter)) { if (this.isCached(address, diameter)) {
return this.cache[address][diameter] return this.cache[address][diameter]
} }
@ -22,30 +22,31 @@ IconFactory.prototype.iconForAddress = function(address, diameter) {
return dataUri return dataUri
} }
IconFactory.prototype.generateNewUri = function(address, diameter) { IconFactory.prototype.generateNewUri = function (address, diameter) {
var numericRepresentation = jsNumberForAddress(address) var numericRepresentation = jsNumberForAddress(address)
var identicon = this.jazzicon(diameter, numericRepresentation) var identicon = this.jazzicon(diameter, numericRepresentation)
var identiconSrc = identicon.innerHTML var identiconSrc = identicon.innerHTML
var dataUri = 'data:image/svg+xml;charset=utf-8,'+encodeURIComponent(identiconSrc) var dataUri = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(identiconSrc)
return dataUri return dataUri
} }
IconFactory.prototype.cacheIcon = function(address, diameter, icon) { IconFactory.prototype.cacheIcon = function (address, diameter, icon) {
if (!(address in this.cache)) { if (!(address in this.cache)) {
var sizeCache = {} var sizeCache = {}
sizeCache[diameter] = icon sizeCache[diameter] = icon
return this.cache[address] = sizeCache this.cache[address] = sizeCache
return sizeCache
} else { } else {
return this.cache[address][diameter] = icon this.cache[address][diameter] = icon
return icon
} }
} }
IconFactory.prototype.isCached = function(address, diameter) { IconFactory.prototype.isCached = function (address, diameter) {
return address in this.cache && diameter in this.cache[address] return address in this.cache && diameter in this.cache[address]
} }
function jsNumberForAddress(address) { function jsNumberForAddress (address) {
var addr = address.slice(2, 10) var addr = address.slice(2, 10)
var seed = parseInt(addr, 16) var seed = parseInt(addr, 16)
return seed return seed

@ -1,6 +1,6 @@
const valuesFor = require('../app/util').valuesFor const valuesFor = require('../app/util').valuesFor
module.exports = function(unconfTxs, unconfMsgs) { module.exports = function (unconfTxs, unconfMsgs) {
var txValues = valuesFor(unconfTxs) var txValues = valuesFor(unconfTxs)
var msgValues = valuesFor(unconfMsgs) var msgValues = valuesFor(unconfMsgs)
var allValues = txValues.concat(msgValues) var allValues = txValues.concat(msgValues)

Loading…
Cancel
Save