aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/actions.js
diff options
context:
space:
mode:
Diffstat (limited to 'ui/app/actions.js')
-rw-r--r--ui/app/actions.js324
1 files changed, 291 insertions, 33 deletions
diff --git a/ui/app/actions.js b/ui/app/actions.js
index 3ea092e5..7b0b0d9c 100644
--- a/ui/app/actions.js
+++ b/ui/app/actions.js
@@ -1,3 +1,4 @@
+const abi = require('human-standard-token-abi')
const getBuyEthUrl = require('../../app/scripts/lib/buy-eth-url')
var actions = {
@@ -5,6 +6,21 @@ var actions = {
GO_HOME: 'GO_HOME',
goHome: goHome,
+ // modal state
+ MODAL_OPEN: 'UI_MODAL_OPEN',
+ MODAL_CLOSE: 'UI_MODAL_CLOSE',
+ showModal: showModal,
+ hideModal: hideModal,
+ // sidebar state
+ SIDEBAR_OPEN: 'UI_SIDEBAR_OPEN',
+ SIDEBAR_CLOSE: 'UI_SIDEBAR_CLOSE',
+ showSidebar: showSidebar,
+ hideSidebar: hideSidebar,
+ // network dropdown open
+ NETWORK_DROPDOWN_OPEN: 'UI_NETWORK_DROPDOWN_OPEN',
+ NETWORK_DROPDOWN_CLOSE: 'UI_NETWORK_DROPDOWN_CLOSE',
+ showNetworkDropdown: showNetworkDropdown,
+ hideNetworkDropdown: hideNetworkDropdown,
// menu state
getNetworkStatus: 'getNetworkStatus',
// transition state
@@ -68,6 +84,8 @@ var actions = {
hideWarning: hideWarning,
// accounts screen
SET_SELECTED_ACCOUNT: 'SET_SELECTED_ACCOUNT',
+ SET_SELECTED_TOKEN: 'SET_SELECTED_TOKEN',
+ setSelectedToken,
SHOW_ACCOUNT_DETAIL: 'SHOW_ACCOUNT_DETAIL',
SHOW_ACCOUNTS_PAGE: 'SHOW_ACCOUNTS_PAGE',
SHOW_CONF_TX_PAGE: 'SHOW_CONF_TX_PAGE',
@@ -78,6 +96,8 @@ var actions = {
// account detail screen
SHOW_SEND_PAGE: 'SHOW_SEND_PAGE',
showSendPage: showSendPage,
+ SHOW_SEND_TOKEN_PAGE: 'SHOW_SEND_TOKEN_PAGE',
+ showSendTokenPage,
ADD_TO_ADDRESS_BOOK: 'ADD_TO_ADDRESS_BOOK',
addToAddressBook: addToAddressBook,
REQUEST_ACCOUNT_EXPORT: 'REQUEST_ACCOUNT_EXPORT',
@@ -86,6 +106,7 @@ var actions = {
exportAccount: exportAccount,
SHOW_PRIVATE_KEY: 'SHOW_PRIVATE_KEY',
showPrivateKey: showPrivateKey,
+ exportAccountComplete,
SAVE_ACCOUNT_LABEL: 'SAVE_ACCOUNT_LABEL',
saveAccountLabel: saveAccountLabel,
// tx conf screen
@@ -97,7 +118,9 @@ var actions = {
cancelMsg: cancelMsg,
signPersonalMsg,
cancelPersonalMsg,
+ sendTx: sendTx,
signTx: signTx,
+ signTokenTx: signTokenTx,
updateAndApproveTx,
cancelTx: cancelTx,
completedTx: completedTx,
@@ -107,6 +130,9 @@ var actions = {
cancelAllTx: cancelAllTx,
viewPendingTx: viewPendingTx,
VIEW_PENDING_TX: 'VIEW_PENDING_TX',
+ // send screen
+ estimateGas,
+ getGasPrice,
// app messages
confirmSeedWords: confirmSeedWords,
showAccountDetail: showAccountDetail,
@@ -123,6 +149,10 @@ var actions = {
SHOW_ADD_TOKEN_PAGE: 'SHOW_ADD_TOKEN_PAGE',
showAddTokenPage,
addToken,
+ addTokens,
+ removeToken,
+ updateTokens,
+ UPDATE_TOKENS: 'UPDATE_TOKENS',
setRpcTarget: setRpcTarget,
setProviderType: setProviderType,
// loading overlay
@@ -139,6 +169,8 @@ var actions = {
coinBaseSubview: coinBaseSubview,
SHAPESHIFT_SUBVIEW: 'SHAPESHIFT_SUBVIEW',
shapeShiftSubview: shapeShiftSubview,
+ UPDATE_TOKEN_EXCHANGE_RATE: 'UPDATE_TOKEN_EXCHANGE_RATE',
+ updateTokenExchangeRate,
PAIR_UPDATE: 'PAIR_UPDATE',
pairUpdate: pairUpdate,
coinShiftRquest: coinShiftRquest,
@@ -323,7 +355,24 @@ function navigateToNewAccountScreen () {
function addNewAccount () {
log.debug(`background.addNewAccount`)
- return callBackgroundThenUpdate(background.addNewAccount)
+ return (dispatch, getState) => {
+ const oldIdentities = getState().metamask.identities
+ dispatch(actions.showLoadingIndication())
+ return new Promise((resolve, reject) => {
+ background.addNewAccount((err, { identities: newIdentities}) => {
+ if (err) {
+ dispatch(actions.displayWarning(err.message))
+ return reject(err)
+ }
+ const newAccountAddress = Object.keys(newIdentities).find(address => !oldIdentities[address])
+
+ dispatch(actions.hideLoadingIndication())
+
+ forceUpdateMetamaskState(dispatch)
+ return resolve(newAccountAddress)
+ })
+ });
+ }
}
function showInfoPage () {
@@ -334,16 +383,16 @@ function showInfoPage () {
function setCurrentCurrency (currencyCode) {
return (dispatch) => {
- dispatch(this.showLoadingIndication())
+ dispatch(actions.showLoadingIndication())
log.debug(`background.setCurrentCurrency`)
background.setCurrentCurrency(currencyCode, (err, data) => {
- dispatch(this.hideLoadingIndication())
+ dispatch(actions.hideLoadingIndication())
if (err) {
log.error(err.stack)
return dispatch(actions.displayWarning(err.message))
}
dispatch({
- type: this.SET_CURRENT_FIAT,
+ type: actions.SET_CURRENT_FIAT,
value: {
currentCurrency: data.currentCurrency,
conversionRate: data.conversionRate,
@@ -397,10 +446,67 @@ function signTx (txData) {
dispatch(actions.showLoadingIndication())
global.ethQuery.sendTransaction(txData, (err, data) => {
dispatch(actions.hideLoadingIndication())
- if (err) dispatch(actions.displayWarning(err.message))
- dispatch(this.goHome())
+ if (err) return dispatch(actions.displayWarning(err.message))
+ dispatch(actions.hideWarning())
})
- dispatch(actions.showConfTxPage())
+ dispatch(actions.showConfTxPage({}))
+ }
+}
+
+function estimateGas (params = {}) {
+ return (dispatch) => {
+ return new Promise((resolve, reject) => {
+ global.ethQuery.estimateGas(params, (err, data) => {
+ if (err) {
+ dispatch(actions.displayWarning(err.message))
+ return reject(err)
+ }
+ dispatch(actions.hideWarning())
+ return resolve(data)
+ })
+ })
+ }
+}
+
+function getGasPrice () {
+ return (dispatch) => {
+ return new Promise((resolve, reject) => {
+ global.ethQuery.gasPrice((err, data) => {
+ if (err) {
+ dispatch(actions.displayWarning(err.message))
+ return reject(err)
+ }
+ dispatch(actions.hideWarning())
+ return resolve(data)
+ })
+ })
+ }
+}
+
+function sendTx (txData) {
+ log.info(`actions - sendTx: ${JSON.stringify(txData.txParams)}`)
+ return (dispatch) => {
+ log.debug(`actions calling background.approveTransaction`)
+ background.approveTransaction(txData.id, (err) => {
+ if (err) {
+ dispatch(actions.txError(err))
+ return log.error(err.message)
+ }
+ dispatch(actions.completedTx(txData.id))
+ })
+ }
+}
+
+function signTokenTx (tokenAddress, toAddress, amount, txData) {
+ return dispatch => {
+ dispatch(actions.showLoadingIndication())
+ const token = global.eth.contract(abi).at(tokenAddress)
+ token.transfer(toAddress, amount, txData)
+ .catch(err => {
+ dispatch(actions.hideLoadingIndication())
+ dispatch(actions.displayWarning(err.message))
+ })
+ dispatch(actions.showConfTxPage({}))
}
}
@@ -565,6 +671,13 @@ function setCurrentAccountTab (newTabName) {
return callBackgroundThenUpdateNoSpinner(background.setCurrentAccountTab, newTabName)
}
+function setSelectedToken (tokenAddress) {
+ return {
+ type: actions.SET_SELECTED_TOKEN,
+ value: tokenAddress || null,
+ }
+}
+
function showAccountDetail (address) {
return (dispatch) => {
dispatch(actions.showLoadingIndication())
@@ -578,6 +691,7 @@ function showAccountDetail (address) {
type: actions.SHOW_ACCOUNT_DETAIL,
value: address,
})
+ dispatch(actions.setSelectedToken())
})
}
}
@@ -595,10 +709,11 @@ function showAccountsPage () {
}
}
-function showConfTxPage (transForward = true) {
+function showConfTxPage ({transForward = true, id}) {
return {
type: actions.SHOW_CONF_TX_PAGE,
- transForward: transForward,
+ transForward,
+ id,
}
}
@@ -628,28 +743,71 @@ function showConfigPage (transitionForward = true) {
}
}
-function showAddTokenPage (transitionForward = true) {
+function showAddTokenPage () {
return {
type: actions.SHOW_ADD_TOKEN_PAGE,
- value: transitionForward,
}
}
function addToken (address, symbol, decimals) {
return (dispatch) => {
dispatch(actions.showLoadingIndication())
- background.addToken(address, symbol, decimals, (err) => {
- dispatch(actions.hideLoadingIndication())
- if (err) {
- return dispatch(actions.displayWarning(err.message))
- }
- setTimeout(() => {
- dispatch(actions.goHome())
- }, 250)
+ return new Promise((resolve, reject) => {
+ background.addToken(address, symbol, decimals, (err, tokens) => {
+ dispatch(actions.hideLoadingIndication())
+ if (err) {
+ dispatch(actions.displayWarning(err.message))
+ reject(err)
+ }
+ dispatch(actions.updateTokens(tokens))
+ resolve(tokens)
+ })
+ })
+ }
+}
+
+function removeToken (address) {
+ return (dispatch) => {
+ dispatch(actions.showLoadingIndication())
+ return new Promise((resolve, reject) => {
+ background.removeToken(address, (err, tokens) => {
+ dispatch(actions.hideLoadingIndication())
+ if (err) {
+ dispatch(actions.displayWarning(err.message))
+ reject(err)
+ }
+ dispatch(actions.updateTokens(tokens))
+ resolve(tokens)
+ })
})
}
}
+function addTokens (tokens) {
+ return dispatch => {
+ if (Array.isArray(tokens)) {
+ return Promise.all(tokens.map(({ address, symbol, decimals }) => (
+ dispatch(addToken(address, symbol, decimals))
+ )))
+ } else {
+ return Promise.all(
+ Object
+ .entries(tokens)
+ .map(([_, { address, symbol, decimals }]) => (
+ dispatch(addToken(address, symbol, decimals))
+ ))
+ )
+ }
+ }
+}
+
+function updateTokens(newTokens) {
+ return {
+ type: actions.UPDATE_TOKENS,
+ newTokens
+ }
+}
+
function goBackToInitView () {
return {
type: actions.BACK_TO_INIT_MENU,
@@ -744,6 +902,63 @@ function addToAddressBook (recipient, nickname) {
}
}
+function setProviderType (type) {
+ log.debug(`background.setProviderType`)
+ background.setProviderType(type)
+ return {
+ type: actions.SET_PROVIDER_TYPE,
+ value: type,
+ }
+}
+
+function useEtherscanProvider () {
+ log.debug(`background.useEtherscanProvider`)
+ background.useEtherscanProvider()
+ return {
+ type: actions.USE_ETHERSCAN_PROVIDER,
+ }
+}
+
+function showNetworkDropdown () {
+ return {
+ type: actions.NETWORK_DROPDOWN_OPEN,
+ }
+}
+
+function hideNetworkDropdown () {
+ return {
+ type: actions.NETWORK_DROPDOWN_CLOSE,
+ }
+}
+
+
+function showModal (payload) {
+ return {
+ type: actions.MODAL_OPEN,
+ payload,
+ }
+}
+
+function hideModal (payload) {
+ return {
+ type: actions.MODAL_CLOSE,
+ payload,
+ }
+}
+
+function showSidebar () {
+ return {
+ type: actions.SIDEBAR_OPEN,
+ }
+}
+
+function hideSidebar () {
+ return {
+ type: actions.SIDEBAR_CLOSE,
+ }
+}
+
+
function showLoadingIndication (message) {
return {
type: actions.SHOW_LOADING,
@@ -795,27 +1010,39 @@ function exportAccount (password, address) {
dispatch(self.showLoadingIndication())
log.debug(`background.submitPassword`)
- background.submitPassword(password, function (err) {
- if (err) {
- log.error('Error in submiting password.')
- dispatch(self.hideLoadingIndication())
- return dispatch(self.displayWarning('Incorrect Password.'))
- }
- log.debug(`background.exportAccount`)
- background.exportAccount(address, function (err, result) {
- dispatch(self.hideLoadingIndication())
-
+ return new Promise((resolve, reject) => {
+ background.submitPassword(password, function (err) {
if (err) {
- log.error(err)
- return dispatch(self.displayWarning('Had a problem exporting the account.'))
+ log.error('Error in submiting password.')
+ dispatch(self.hideLoadingIndication())
+ dispatch(self.displayWarning('Incorrect Password.'))
+ return reject(err)
}
+ log.debug(`background.exportAccount`)
+ return background.exportAccount(address, function (err, result) {
+ dispatch(self.hideLoadingIndication())
+
+ if (err) {
+ log.error(err)
+ dispatch(self.displayWarning('Had a problem exporting the account.'))
+ return reject(err)
+ }
- dispatch(self.showPrivateKey(result))
+ dispatch(self.exportAccountComplete())
+
+ return resolve(result)
+ })
})
})
}
}
+function exportAccountComplete() {
+ return {
+ type: actions.EXPORT_ACCOUNT,
+ }
+}
+
function showPrivateKey (key) {
return {
type: actions.SHOW_PRIVATE_KEY,
@@ -846,6 +1073,12 @@ function showSendPage () {
}
}
+function showSendTokenPage () {
+ return {
+ type: actions.SHOW_SEND_TOKEN_PAGE,
+ }
+}
+
function buyEth (opts) {
return (dispatch) => {
const url = getBuyEthUrl(opts)
@@ -943,7 +1176,10 @@ function reshowQrCode (data, coin) {
]
dispatch(actions.hideLoadingIndication())
- return dispatch(actions.showQrView(data, message))
+ return dispatch(actions.showModal({
+ name: 'SHAPESHIFT_DEPOSIT_TX',
+ Qr: { data, message },
+ }))
})
}
}
@@ -972,6 +1208,28 @@ function shapeShiftRequest (query, options, cb) {
}
}
+function updateTokenExchangeRate (token = '') {
+ const pair = `${token.toLowerCase()}_eth`
+
+ return dispatch => {
+ if (!token) {
+ return
+ }
+
+ shapeShiftRequest('marketinfo', { pair }, marketinfo => {
+ if (!marketinfo.error) {
+ dispatch({
+ type: actions.UPDATE_TOKEN_EXCHANGE_RATE,
+ payload: {
+ pair,
+ marketinfo,
+ },
+ })
+ }
+ })
+ }
+}
+
// Call Background Then Update
//
// A function generator for a common pattern wherein: