aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/scripts/background.js8
-rw-r--r--app/scripts/lib/config-manager.js67
-rw-r--r--app/scripts/lib/idStore.js27
-rw-r--r--app/scripts/lib/message-manager.js61
-rw-r--r--ui/app/account-detail.js3
-rw-r--r--ui/app/actions.js18
-rw-r--r--ui/app/app.js2
-rw-r--r--ui/app/components/pending-msg.js65
-rw-r--r--ui/app/components/pending-tx.js71
-rw-r--r--ui/app/components/template.js19
-rw-r--r--ui/app/conf-tx.js111
-rw-r--r--ui/app/reducers/app.js27
-rw-r--r--ui/app/reducers/metamask.js8
-rw-r--r--ui/index.js5
-rw-r--r--ui/lib/tx-helper.js8
15 files changed, 355 insertions, 145 deletions
diff --git a/app/scripts/background.js b/app/scripts/background.js
index 3c46f4693..0f9ecc1c9 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -10,6 +10,7 @@ const IdentityStore = require('./lib/idStore')
const createTxNotification = require('./lib/notifications.js').createTxNotification
const createMsgNotification = require('./lib/notifications.js').createMsgNotification
const configManager = require('./lib/config-manager-singleton')
+const messageManager = require('./lib/message-manager')
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
const HostStore = require('./lib/remote-store.js').HostStore
const Web3 = require('web3')
@@ -175,6 +176,8 @@ function setupControllerConnection(stream){
setSelectedAddress: idStore.setSelectedAddress.bind(idStore),
approveTransaction: idStore.approveTransaction.bind(idStore),
cancelTransaction: idStore.cancelTransaction.bind(idStore),
+ signMessage: idStore.signMessage.bind(idStore),
+ cancelMessage: idStore.cancelMessage.bind(idStore),
setLocked: idStore.setLocked.bind(idStore),
clearSeedWordCache: idStore.clearSeedWordCache.bind(idStore),
exportAccount: idStore.exportAccount.bind(idStore),
@@ -206,7 +209,10 @@ idStore.on('update', updateBadge)
function updateBadge(state){
var label = ''
var unconfTxs = configManager.unconfirmedTxs()
- var count = Object.keys(unconfTxs).length
+ var unconfTxLen = Object.keys(unconfTxs).length
+ var unconfMsgs = messageManager.unconfirmedMsgs()
+ var unconfMsgLen = Object.keys(unconfMsgs).length
+ var count = unconfTxLen + unconfMsgLen
if (count) {
label = String(count)
}
diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js
index 0e7454dfd..5bfb8befe 100644
--- a/app/scripts/lib/config-manager.js
+++ b/app/scripts/lib/config-manager.js
@@ -211,73 +211,6 @@ ConfigManager.prototype.updateTx = function(tx) {
this._saveTxList(transactions)
}
-//
-// Msg
-//
-
-ConfigManager.prototype.getMsgList = function() {
- var data = this.migrator.getData()
- if (data.messages !== undefined) {
- return data.messages
- } else {
- return []
- }
-}
-
-ConfigManager.prototype.unconfirmedMsgs = function() {
- var messages = this.getMsgList()
- return messages.filter(msg => msg.status === 'unconfirmed')
- .reduce((result, msg) => { result[msg.id] = msg; return result }, {})
-}
-
-ConfigManager.prototype._saveMsgList = function(msgList) {
- var data = this.migrator.getData()
- data.messages = msgList
- this.setData(data)
-}
-
-ConfigManager.prototype.addMsg = function(msg) {
- var messages = this.getMsgList()
- messages.push(msg)
- this._saveMsgList(messages)
-}
-
-ConfigManager.prototype.getMsg = function(msgId) {
- var messages = this.getMsgList()
- var matching = messages.filter(msg => msg.id === msgId)
- return matching.length > 0 ? matching[0] : null
-}
-
-ConfigManager.prototype.confirmMsg = function(msgId) {
- this._setMsgStatus(msgId, 'confirmed')
-}
-
-ConfigManager.prototype.rejectMsg = function(msgId) {
- this._setMsgStatus(msgId, 'rejected')
-}
-
-ConfigManager.prototype._setMsgStatus = function(msgId, status) {
- var msg = this.getMsg(msgId)
- msg.status = status
- this.updateMsg(msg)
-}
-
-ConfigManager.prototype.updateMsg = function(msg) {
- var messages = this.getMsgList()
- var found, index
- messages.forEach((otherMsg, i) => {
- if (otherMsg.id === msg.id) {
- found = true
- index = i
- }
- })
- if (found) {
- messages[index] = msg
- }
- this._saveMsgList(messages)
-}
-
-
// observable
diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js
index c25d83c9d..b8d825d8b 100644
--- a/app/scripts/lib/idStore.js
+++ b/app/scripts/lib/idStore.js
@@ -9,6 +9,7 @@ const extend = require('xtend')
const createId = require('web3-provider-engine/util/random-id')
const autoFaucet = require('./auto-faucet')
const configManager = require('./config-manager-singleton')
+const messageManager = require('./message-manager')
const DEFAULT_RPC = 'https://testrpc.metamask.io/'
@@ -32,6 +33,7 @@ function IdentityStore(opts = {}) {
selectedAddress: null,
identities: {},
}
+
// not part of serilized metamask state - only kept in memory
this._unconfTxCbs = {}
this._unconfMsgCbs = {}
@@ -85,6 +87,8 @@ IdentityStore.prototype.getState = function(){
seedWords: seedWords,
unconfTxs: configManager.unconfirmedTxs(),
transactions: configManager.getTxList(),
+ unconfMsgs: messageManager.unconfirmedMsgs(),
+ messages: messageManager.getMsgList(),
selectedAddress: configManager.getSelectedAccount(),
}))
}
@@ -226,7 +230,7 @@ IdentityStore.prototype.addUnconfirmedMessage = function(msgParams, cb){
time: time,
status: 'unconfirmed',
}
- configManager.addMsg(msgData)
+ messageManager.addMsg(msgData)
console.log('addUnconfirmedMessage:', msgData)
// keep the cb around for after approval (requires user interaction)
@@ -241,27 +245,27 @@ IdentityStore.prototype.addUnconfirmedMessage = function(msgParams, cb){
// comes from metamask ui
IdentityStore.prototype.approveMessage = function(msgId, cb){
- var msgData = configManager.getMsg(msgId)
+ var msgData = messageManager.getMsg(msgId)
var approvalCb = this._unconfMsgCbs[msgId] || noop
// accept msg
cb()
approvalCb(null, true)
// clean up
- configManager.confirmMsg(msgId)
+ messageManager.confirmMsg(msgId)
delete this._unconfMsgCbs[msgId]
this._didUpdate()
}
// comes from metamask ui
IdentityStore.prototype.cancelMessage = function(msgId){
- var txData = configManager.getMsg(msgId)
+ var txData = messageManager.getMsg(msgId)
var approvalCb = this._unconfMsgCbs[msgId] || noop
// reject tx
approvalCb(null, false)
// clean up
- configManager.rejectMsg(msgId)
+ messageManager.rejectMsg(msgId)
delete this._unconfTxCbs[msgId]
this._didUpdate()
}
@@ -271,7 +275,14 @@ IdentityStore.prototype.signMessage = function(msgParams, cb){
try {
console.log('signing msg...', msgParams.data)
var rawMsg = this._idmgmt.signMsg(msgParams.from, msgParams.data)
- cb(null, rawMsg)
+ if ('metamaskId' in msgParams) {
+ var id = msgParams.metamaskId
+ delete msgParams.metamaskId
+
+ this.approveMessage(id, cb)
+ } else {
+ cb(null, rawMsg)
+ }
} catch (err) {
cb(err)
}
@@ -426,7 +437,7 @@ function IdManagement(opts) {
var privKeyHex = this.exportPrivateKey(txParams.from)
var privKey = ethUtil.toBuffer(privKeyHex)
tx.sign(privKey)
-
+
// Add the tx hash to the persisted meta-tx object
var txHash = ethUtil.bufferToHex(tx.hash())
var metaTx = configManager.getTx(txParams.metamaskId)
@@ -472,4 +483,4 @@ function concatSig(v, r, s) {
s = ethUtil.toUnsigned(s).toString('hex')
v = ethUtil.stripHexPrefix(ethUtil.intToHex(v))
return ethUtil.addHexPrefix(r.concat(s, v).toString("hex"))
-} \ No newline at end of file
+}
diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js
new file mode 100644
index 000000000..91edb7759
--- /dev/null
+++ b/app/scripts/lib/message-manager.js
@@ -0,0 +1,61 @@
+module.exports = new MessageManager()
+
+function MessageManager(opts) {
+ this.messages = []
+}
+
+MessageManager.prototype.getMsgList = function() {
+ return this.messages
+}
+
+MessageManager.prototype.unconfirmedMsgs = function() {
+ var messages = this.getMsgList()
+ return messages.filter(msg => msg.status === 'unconfirmed')
+ .reduce((result, msg) => { result[msg.id] = msg; return result }, {})
+}
+
+MessageManager.prototype._saveMsgList = function(msgList) {
+ this.messages = msgList
+}
+
+MessageManager.prototype.addMsg = function(msg) {
+ var messages = this.getMsgList()
+ messages.push(msg)
+ this._saveMsgList(messages)
+}
+
+MessageManager.prototype.getMsg = function(msgId) {
+ var messages = this.getMsgList()
+ var matching = messages.filter(msg => msg.id === msgId)
+ return matching.length > 0 ? matching[0] : null
+}
+
+MessageManager.prototype.confirmMsg = function(msgId) {
+ this._setMsgStatus(msgId, 'confirmed')
+}
+
+MessageManager.prototype.rejectMsg = function(msgId) {
+ this._setMsgStatus(msgId, 'rejected')
+}
+
+MessageManager.prototype._setMsgStatus = function(msgId, status) {
+ var msg = this.getMsg(msgId)
+ if (msg) msg.status = status
+ this.updateMsg(msg)
+}
+
+MessageManager.prototype.updateMsg = function(msg) {
+ var messages = this.getMsgList()
+ var found, index
+ messages.forEach((otherMsg, i) => {
+ if (otherMsg.id === msg.id) {
+ found = true
+ index = i
+ }
+ })
+ if (found) {
+ messages[index] = msg
+ }
+ this._saveMsgList(messages)
+}
+
diff --git a/ui/app/account-detail.js b/ui/app/account-detail.js
index 250e7318c..a876b275f 100644
--- a/ui/app/account-detail.js
+++ b/ui/app/account-detail.js
@@ -13,7 +13,7 @@ function mapStateToProps(state) {
return {
identities: state.metamask.identities,
accounts: state.metamask.accounts,
- address: state.appState.currentView.context,
+ address: state.metamask.selectedAccount,
accountDetail: state.appState.accountDetail,
transactions: state.metamask.transactions,
networkVersion: state.metamask.network,
@@ -27,6 +27,7 @@ function AccountDetailScreen() {
AccountDetailScreen.prototype.render = function() {
var state = this.props
+ var selected = state.address || Object.keys(state.accounts[0]).address
var identity = state.identities[state.address]
var account = state.accounts[state.address]
var accountDetail = state.accountDetail
diff --git a/ui/app/actions.js b/ui/app/actions.js
index 12e20e0cf..72550ff15 100644
--- a/ui/app/actions.js
+++ b/ui/app/actions.js
@@ -42,6 +42,7 @@ var actions = {
SHOW_ACCOUNT_DETAIL: 'SHOW_ACCOUNT_DETAIL',
SHOW_ACCOUNTS_PAGE: 'SHOW_ACCOUNTS_PAGE',
SHOW_CONF_TX_PAGE: 'SHOW_CONF_TX_PAGE',
+ SHOW_CONF_MSG_PAGE: 'SHOW_CONF_MSG_PAGE',
// account detail screen
SHOW_SEND_PAGE: 'SHOW_SEND_PAGE',
showSendPage: showSendPage,
@@ -57,7 +58,8 @@ var actions = {
NEXT_TX: 'NEXT_TX',
PREVIOUS_TX: 'PREV_TX',
setSelectedAddress: setSelectedAddress,
- signTx: signTx,
+ signMsg: signMsg,
+ cancelMsg: cancelMsg,
sendTx: sendTx,
cancelTx: cancelTx,
completedTx: completedTx,
@@ -152,16 +154,15 @@ function setSelectedAddress(address) {
}
}
-function signTx(txData) {
+function signMsg(msgData) {
return (dispatch) => {
dispatch(this.showLoadingIndication())
- web3.eth.sendTransaction(txData, (err, data) => {
+ _accountManager.signMessage(msgData, (err) => {
dispatch(this.hideLoadingIndication())
if (err) return dispatch(this.displayWarning(err.message))
- dispatch(this.hideWarning())
- dispatch(this.goHome())
+ dispatch(this.completedTx(msgData.metamaskId))
})
}
}
@@ -193,9 +194,14 @@ function txError(err) {
}
}
+function cancelMsg(msgData){
+ _accountManager.cancelMessage(msgData.id)
+ return this.completedTx(msgData.id)
+}
+
function cancelTx(txData){
_accountManager.cancelTransaction(txData.id)
- return this.goHome()
+ return this.completedTx(txData.id)
}
//
diff --git a/ui/app/app.js b/ui/app/app.js
index fa375fb7f..fce98d8e1 100644
--- a/ui/app/app.js
+++ b/ui/app/app.js
@@ -202,7 +202,7 @@ App.prototype.renderPrimary = function(state){
return h(CreateVaultScreen, {key: 'createVault'})
default:
- return h(AccountsScreen, {key: 'accounts'})
+ return h(AccountDetailScreen, {key: 'account-detail'})
}
}
diff --git a/ui/app/components/pending-msg.js b/ui/app/components/pending-msg.js
new file mode 100644
index 000000000..cb6df2a3d
--- /dev/null
+++ b/ui/app/components/pending-msg.js
@@ -0,0 +1,65 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+
+const AccountPanel = require('./account-panel')
+const addressSummary = require('../util').addressSummary
+const readableDate = require('../util').readableDate
+const formatBalance = require('../util').formatBalance
+const dataSize = require('../util').dataSize
+
+module.exports = PendingMsg
+
+
+inherits(PendingMsg, Component)
+function PendingMsg() {
+ Component.call(this)
+}
+
+PendingMsg.prototype.render = function() {
+ var state = this.props
+ var msgData = state.txData
+
+ var msgParams = msgData.msgParams || {}
+ var address = msgParams.from || state.selectedAddress
+ var identity = state.identities[address] || { address: address }
+ var account = state.accounts[address] || { address: address }
+
+ return (
+ h('.transaction', {
+ key: msgData.id,
+ }, [
+
+ // account that will sign
+ h(AccountPanel, {
+ showFullAddress: true,
+ identity: identity,
+ account: account,
+ }),
+
+ // tx data
+ h('.tx-data.flex-column.flex-justify-center.flex-grow.select-none', [
+ h('.flex-row.flex-space-between', [
+ h('label.font-small', 'DATE'),
+ h('span.font-small', readableDate(msgData.time)),
+ ]),
+
+ h('.flex-row.flex-space-between', [
+ h('label.font-small', 'MESSAGE'),
+ h('span.font-small', msgParams.data),
+ ]),
+ ]),
+
+ // send + cancel
+ h('.flex-row.flex-space-around', [
+ h('button', {
+ onClick: state.cancelMessage,
+ }, 'Cancel'),
+ h('button', {
+ onClick: state.signMessage,
+ }, 'Sign'),
+ ]),
+ ])
+ )
+}
+
diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js
new file mode 100644
index 000000000..2519998a5
--- /dev/null
+++ b/ui/app/components/pending-tx.js
@@ -0,0 +1,71 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+
+const AccountPanel = require('./account-panel')
+const addressSummary = require('../util').addressSummary
+const readableDate = require('../util').readableDate
+const formatBalance = require('../util').formatBalance
+const dataSize = require('../util').dataSize
+
+module.exports = PendingTx
+
+
+inherits(PendingTx, Component)
+function PendingTx() {
+ Component.call(this)
+}
+
+PendingTx.prototype.render = function() {
+ var state = this.props
+ var txData = state.txData
+
+ var txParams = txData.txParams || {}
+ var address = txParams.from || state.selectedAddress
+ var identity = state.identities[address] || { address: address }
+ var account = state.accounts[address] || { address: address }
+
+ return (
+ h('.transaction', {
+ key: txData.id,
+ }, [
+
+ // account that will sign
+ h(AccountPanel, {
+ showFullAddress: true,
+ identity: identity,
+ account: account,
+ }),
+
+ // tx data
+ h('.tx-data.flex-column.flex-justify-center.flex-grow.select-none', [
+
+ h('.flex-row.flex-space-between', [
+ h('label.font-small', 'TO ADDRESS'),
+ h('span.font-small', addressSummary(txParams.to)),
+ ]),
+
+ h('.flex-row.flex-space-between', [
+ h('label.font-small', 'DATE'),
+ h('span.font-small', readableDate(txData.time)),
+ ]),
+
+ h('.flex-row.flex-space-between', [
+ h('label.font-small', 'AMOUNT'),
+ h('span.font-small', formatBalance(txParams.value)),
+ ]),
+ ]),
+
+ // send + cancel
+ h('.flex-row.flex-space-around', [
+ h('button', {
+ onClick: state.cancelTransaction,
+ }, 'Cancel'),
+ h('button', {
+ onClick: state.sendTransaction,
+ }, 'Send'),
+ ]),
+ ])
+ )
+}
+
diff --git a/ui/app/components/template.js b/ui/app/components/template.js
new file mode 100644
index 000000000..9e4eca20f
--- /dev/null
+++ b/ui/app/components/template.js
@@ -0,0 +1,19 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+
+module.exports = NewComponent
+
+
+inherits(NewComponent, Component)
+function NewComponent() {
+ Component.call(this)
+}
+
+NewComponent.prototype.render = function() {
+ var state = this.props
+
+ return (
+ h('span', 'Placeholder component')
+ )
+}
diff --git a/ui/app/conf-tx.js b/ui/app/conf-tx.js
index 983070013..28f2db39c 100644
--- a/ui/app/conf-tx.js
+++ b/ui/app/conf-tx.js
@@ -7,10 +7,10 @@ const copyToClipboard = require('copy-to-clipboard')
const actions = require('./actions')
const AccountPanel = require('./components/account-panel')
const valuesFor = require('./util').valuesFor
-const addressSummary = require('./util').addressSummary
-const readableDate = require('./util').readableDate
-const formatBalance = require('./util').formatBalance
-const dataSize = require('./util').dataSize
+const txHelper = require('../lib/tx-helper')
+
+const ConfirmTx = require('./components/pending-tx')
+const PendingMsg = require('./components/pending-msg')
module.exports = connect(mapStateToProps)(ConfirmTxScreen)
@@ -20,7 +20,9 @@ function mapStateToProps(state) {
accounts: state.metamask.accounts,
selectedAddress: state.metamask.selectedAddress,
unconfTxs: state.metamask.unconfTxs,
+ unconfMsgs: state.metamask.unconfMsgs,
index: state.appState.currentView.context,
+ warning: state.appState.warning,
}
}
@@ -32,12 +34,11 @@ function ConfirmTxScreen() {
ConfirmTxScreen.prototype.render = function() {
var state = this.props
- var unconfTxList = valuesFor(state.unconfTxs).sort(tx => tx.time)
+
+ var unconfTxs = state.unconfTxs
+ var unconfMsgs = state.unconfMsgs
+ var unconfTxList = txHelper(unconfTxs, unconfMsgs)
var txData = unconfTxList[state.index] || {}
- var txParams = txData.txParams || {}
- var address = txParams.from || state.selectedAddress
- var identity = state.identities[address] || { address: address }
- var account = state.accounts[address] || { address: address }
return (
@@ -46,7 +47,7 @@ ConfirmTxScreen.prototype.render = function() {
// subtitle and nav
h('.section-title.flex-row.flex-center', [
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
- onClick: this.navigateToAccounts.bind(this),
+ onClick: this.goHome.bind(this),
}),
h('h2.page-subtitle', 'Confirm Transaction'),
]),
@@ -72,58 +73,44 @@ ConfirmTxScreen.prototype.render = function() {
}),
]),
+ warningIfExists(state.warning),
+
h(ReactCSSTransitionGroup, {
transitionName: "main",
transitionEnterTimeout: 300,
transitionLeaveTimeout: 300,
}, [
- h('.transaction', {
+ currentTxView({
+ // Properties
+ txData: txData,
key: txData.id,
- }, [
-
- // account that will sign
- h(AccountPanel, {
- showFullAddress: true,
- identity: identity,
- account: account,
- }),
-
- // tx data
- h('.tx-data.flex-column.flex-justify-center.flex-grow.select-none', [
-
- h('.flex-row.flex-space-between', [
- h('label.font-small', 'TO ADDRESS'),
- h('span.font-small', addressSummary(txParams.to)),
- ]),
-
- h('.flex-row.flex-space-between', [
- h('label.font-small', 'DATE'),
- h('span.font-small', readableDate(txData.time)),
- ]),
-
- h('.flex-row.flex-space-between', [
- h('label.font-small', 'AMOUNT'),
- h('span.font-small', formatBalance(txParams.value)),
- ]),
-
- ]),
-
- // send + cancel
- h('.flex-row.flex-space-around', [
- h('button', {
- onClick: this.cancelTransaction.bind(this, txData),
- }, 'Cancel'),
- h('button', {
- onClick: this.sendTransaction.bind(this, txData),
- }, 'Send'),
- ]),
- ]),
+ selectedAddress: state.selectedAddress,
+ accounts: state.accounts,
+ identities: state.identities,
+ // Actions
+ sendTransaction: this.sendTransaction.bind(this, txData),
+ cancelTransaction: this.cancelTransaction.bind(this, txData),
+ signMessage: this.signMessage.bind(this, txData),
+ cancelMessage: this.cancelMessage.bind(this, txData),
+ }),
+
]),
- ]) // No comma or semicolon can go here
+ ])
)
}
+function currentTxView (opts) {
+
+ if ('txParams' in opts.txData) {
+ // This is a pending transaction
+ return h(ConfirmTx, opts)
+ } else if ('msgParams' in opts.txData) {
+ // This is a pending message to sign
+ return h(PendingMsg, opts)
+ }
+}
+
ConfirmTxScreen.prototype.sendTransaction = function(txData, event){
event.stopPropagation()
this.props.dispatch(actions.sendTx(txData))
@@ -134,7 +121,25 @@ ConfirmTxScreen.prototype.cancelTransaction = function(txData, event){
this.props.dispatch(actions.cancelTx(txData))
}
-ConfirmTxScreen.prototype.navigateToAccounts = function(event){
+ConfirmTxScreen.prototype.signMessage = function(msgData, event){
+ var params = msgData.msgParams
+ params.metamaskId = msgData.id
event.stopPropagation()
- this.props.dispatch(actions.showAccountsPage())
+ this.props.dispatch(actions.signMsg(params))
+}
+
+ConfirmTxScreen.prototype.cancelMessage = function(msgData, event){
+ event.stopPropagation()
+ this.props.dispatch(actions.cancelMsg(msgData))
+}
+
+ConfirmTxScreen.prototype.goHome = function(event){
+ event.stopPropagation()
+ this.props.dispatch(actions.goHome())
+}
+
+function warningIfExists(warning) {
+ if (warning) {
+ return h('span.error', { style: { margin: 'auto' } }, warning)
+ }
}
diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js
index 57cdccbac..fb03ffeee 100644
--- a/ui/app/reducers/app.js
+++ b/ui/app/reducers/app.js
@@ -1,6 +1,7 @@
const extend = require('xtend')
const actions = require('../actions')
const valuesFor = require('../util').valuesFor
+const txHelper = require('../../lib/tx-helper')
module.exports = reduceApp
@@ -127,10 +128,7 @@ function reduceApp(state, action) {
case actions.GO_HOME:
return extend(appState, {
- currentView: {
- name: 'accountDetail',
- context: appState.currentView.context,
- },
+ currentView: {},
accountDetail: {
accountExport: 'none',
privateKey: '',
@@ -185,9 +183,24 @@ function reduceApp(state, action) {
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 = Object.keys(state.metamask.unconfTxs).filter(tx => tx !== tx.id)
- if (unconfTxs && unconfTxs.length > 0) {
+ 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: {
@@ -202,7 +215,7 @@ function reduceApp(state, action) {
warning: null,
currentView: {
name: 'accountDetail',
- context: appState.currentView.context,
+ context: state.metamask.selectedAddress,
},
})
}
diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js
index 43bb3f761..2fe96c453 100644
--- a/ui/app/reducers/metamask.js
+++ b/ui/app/reducers/metamask.js
@@ -44,13 +44,19 @@ function reduceMetamask(state, action) {
case actions.COMPLETED_TX:
var stringId = String(action.id)
var newState = extend(metamaskState, {
- unconfTxs: {}
+ unconfTxs: {},
+ unconfMsgs: {},
})
for (var id in metamaskState.unconfTxs) {
if (id !== stringId) {
newState.unconfTxs[id] = metamaskState.unconfTxs[id]
}
}
+ for (var id in metamaskState.unconfMsgs) {
+ if (id !== stringId) {
+ newState.unconfMsgs[id] = metamaskState.unconfMsgs[id]
+ }
+ }
return newState
case actions.CLEAR_SEED_WORD_CACHE:
diff --git a/ui/index.js b/ui/index.js
index 4ecce2fbe..d67c6f096 100644
--- a/ui/index.js
+++ b/ui/index.js
@@ -43,6 +43,11 @@ function startApp(metamaskState, accountManager, opts){
store.dispatch(actions.showConfTxPage())
}
+ // if unconfirmed messages, start on msgConf page
+ if (Object.keys(metamaskState.unconfMsgs || {}).length) {
+ store.dispatch(actions.showConfTxPage())
+ }
+
accountManager.on('update', function(metamaskState){
store.dispatch(actions.updateMetamaskState(metamaskState))
})
diff --git a/ui/lib/tx-helper.js b/ui/lib/tx-helper.js
new file mode 100644
index 000000000..49845b01a
--- /dev/null
+++ b/ui/lib/tx-helper.js
@@ -0,0 +1,8 @@
+const valuesFor = require('../app/util').valuesFor
+
+module.exports = function(unconfTxs, unconfMsgs) {
+ var txValues = valuesFor(unconfTxs)
+ var msgValues = valuesFor(unconfMsgs)
+ var allValues = txValues.concat(msgValues)
+ return allValues.sort(tx => tx.time)
+}