aboutsummaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-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
11 files changed, 268 insertions, 69 deletions
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)
+}