diff --git a/__tests__/components/Claim.test.js b/__tests__/components/Claim.test.js index 1bcfe9ad0..786a2f0d8 100644 --- a/__tests__/components/Claim.test.js +++ b/__tests__/components/Claim.test.js @@ -66,9 +66,8 @@ describe('Claim', () => { }) describe('when do gas claim button is clicked', () => { - test('should dispatch transaction failure event', (done) => { + test('should dispatch transaction failure event', async () => { const { wrapper, store } = setup() - const response = Promise.resolve('pause') neonjs.doSendAsset = jest.fn(() => { return new Promise((resolve, reject) => { resolve({ result: undefined }) @@ -76,34 +75,27 @@ describe('Claim', () => { }) wrapper.dive().find('#claim button').simulate('click') - response.then(() => { - try { - const actions = store.getActions() - expect(actions.length).toEqual(2) - expect(actions[0]).toEqual({ - payload: { - message: 'Sending Neo to Yourself...', - type: 'INFO' - }, - type: 'SHOW_NOTIFICATION' - }) - expect(actions[1]).toEqual({ - payload: { - message: 'Transaction failed!', - type: 'ERROR' - }, - type: 'SHOW_NOTIFICATION' - }) - done() - } catch (e) { - done.fail(e) - } + await Promise.resolve().then().then().then() + const actions = store.getActions() + expect(actions.length).toEqual(2) + expect(actions[0]).toEqual({ + payload: { + message: 'Sending Neo to Yourself...', + type: 'INFO' + }, + type: 'SHOW_NOTIFICATION' + }) + expect(actions[1]).toEqual({ + payload: { + message: 'Transaction failed!', + type: 'ERROR' + }, + type: 'SHOW_NOTIFICATION' }) }) - test('should dispatch transaction waiting, set claim request and disable claim event', (done) => { + test('should dispatch transaction waiting, set claim request and disable claim event', async () => { const { wrapper, store } = setup() - const response = Promise.resolve('pause') neonjs.doSendAsset = jest.fn(() => { return new Promise((resolve, reject) => { resolve({ result: true }) @@ -112,31 +104,25 @@ describe('Claim', () => { wrapper.dive().find('#claim button').simulate('click') - response.then(() => { - try { - const actions = store.getActions() - expect(actions.length).toEqual(4) - expect(actions[0]).toEqual({ - payload: { - message: 'Sending Neo to Yourself...', - type: 'INFO' - }, - type: 'SHOW_NOTIFICATION' - }) - expect(actions[1]).toEqual({ - payload: { - message: 'Waiting for transaction to clear...', - type: 'INFO' - }, - type: 'SHOW_NOTIFICATION' - }) - expect(actions[2]).toEqual(setClaimRequest(true)) - expect(actions[3]).toEqual(disableClaim(true)) - done() - } catch (e) { - done.fail(e) - } + await Promise.resolve().then().then().then() + const actions = store.getActions() + expect(actions.length).toEqual(4) + expect(actions[0]).toEqual({ + payload: { + message: 'Sending Neo to Yourself...', + type: 'INFO' + }, + type: 'SHOW_NOTIFICATION' + }) + expect(actions[1]).toEqual({ + payload: { + message: 'Waiting for transaction to clear...', + type: 'INFO' + }, + type: 'SHOW_NOTIFICATION' }) + expect(actions[2]).toEqual(setClaimRequest(true)) + expect(actions[3]).toEqual(disableClaim(true)) }) }) }) diff --git a/__tests__/components/NetworkSwitch.test.js b/__tests__/components/NetworkSwitch.test.js index ec62b0ad1..8373cef1b 100644 --- a/__tests__/components/NetworkSwitch.test.js +++ b/__tests__/components/NetworkSwitch.test.js @@ -57,7 +57,7 @@ describe('NetworkSwitch', () => { done() }) - test('switches to TestNet when clicked', (done) => { + test('switches to TestNet when clicked', async () => { const { wrapper, store } = setup() const state = store.getState() const deepWrapper = wrapper.dive() @@ -70,13 +70,12 @@ describe('NetworkSwitch', () => { SET_BALANCE ] deepWrapper.find('.netName').simulate('click') - setTimeout(() => { - const actions = store.getActions() - actions.forEach(action => { - expect(actionTypes.indexOf(action.type) > -1).toEqual(true) - }) - expect(actions.length).toEqual(5) - done() - }, 0) + + await Promise.resolve().then().then().then() + const actions = store.getActions() + actions.forEach(action => { + expect(actionTypes.indexOf(action.type) > -1).toEqual(true) + }) + expect(actions.length).toEqual(5) }) }) diff --git a/__tests__/components/Send.test.js b/__tests__/components/Send.test.js index 584cb04a6..be5bd4389 100644 --- a/__tests__/components/Send.test.js +++ b/__tests__/components/Send.test.js @@ -11,7 +11,6 @@ import axios from 'axios' import MockAdapter from 'axios-mock-adapter' jest.useFakeTimers() -jest.mock('neon-js') const axiosMock = new MockAdapter(axios) axiosMock.onAny().reply(200) @@ -298,7 +297,7 @@ describe('Send', () => { wrapper.find('#confirmPane').simulate('click') - Promise.resolve('pause').then(() => { + Promise.resolve('pause').then().then().then(() => { jest.runAllTimers() const actions = store.getActions() expect(actions.length).toEqual(3) diff --git a/app/modules/account.js b/app/modules/account.js index ed76df9e7..7436a590d 100644 --- a/app/modules/account.js +++ b/app/modules/account.js @@ -44,24 +44,21 @@ export function setKeys (accountKeys: any) { } export const loginNep2 = (passphrase: string, wif: string, history: Object) => (dispatch: DispatchType) => { + const dispatchError = (message: string) => dispatch(showErrorNotification({ message })) + if (!validatePassphrase(passphrase)) { - dispatch(showErrorNotification({ message: 'Passphrase too short' })) + return dispatchError('Passphrase too short') } dispatch(showInfoNotification({ message: 'Decrypting encoded key...' })) - const wrongPassphraseOrEncryptedKeyError = () => { - dispatch(showErrorNotification({ message: 'Wrong passphrase or invalid encrypted key' })) - } - setTimeout(() => { + + setTimeout(async () => { try { - decryptWIF(wif, passphrase).then((wif) => { - dispatch(hideNotification({ noAnimation: true })) - dispatch(login(wif)) - history.push(ROUTES.DASHBOARD) - }).catch(() => { - wrongPassphraseOrEncryptedKeyError() - }) + const [_err, responseWif] = await asyncWrap(decryptWIF(wif, passphrase)) // eslint-disable-line + dispatch(hideNotification({ noAnimation: true })) + dispatch(login(responseWif)) + return history.push(ROUTES.DASHBOARD) } catch (e) { - wrongPassphraseOrEncryptedKeyError() + return dispatchError('Wrong passphrase or invalid encrypted key') } }, 500) } @@ -90,9 +87,9 @@ export function hardwarePublicKey (publicKey: string) { export const loginWithPrivateKey = (wif: string, history: Object, route?: RouteType) => (dispatch: DispatchType) => { if (verifyPrivateKey(wif)) { dispatch(login(wif)) - history.push(route || ROUTES.DASHBOARD) + return history.push(route || ROUTES.DASHBOARD) } else { - dispatch(showErrorNotification({ message: 'That is not a valid private key' })) + return dispatch(showErrorNotification({ message: 'That is not a valid private key' })) } } diff --git a/app/modules/claim.js b/app/modules/claim.js index 54576e679..54115677d 100644 --- a/app/modules/claim.js +++ b/app/modules/claim.js @@ -7,6 +7,7 @@ import { FIVE_MINUTES_MS } from '../core/time' import { getWif, getAddress, getSigningFunction, getPublicKey } from './account' import { getNetwork } from './metadata' import { getNeo } from './wallet' +import asyncWrap from '../core/asyncHelper' // Constants export const SET_CLAIM = 'SET_CLAIM' @@ -38,13 +39,12 @@ export function disableClaim (disableClaimButton: boolean) { } } -export const syncAvailableClaim = (net: NetworkType, address: string) => (dispatch: DispatchType) => { - getClaimAmounts(net, address).then((result) => { - return dispatch(setClaim(result.available, result.unavailable)) - }) +export const syncAvailableClaim = (net: NetworkType, address: string) => async (dispatch: DispatchType) => { + const [_err, result] = await asyncWrap(getClaimAmounts(net, address)) // eslint-disable-line + return dispatch(setClaim(result.available, result.unavailable)) } -export const doClaimNotify = () => (dispatch: DispatchType, getState: GetStateType) => { +export const doClaimNotify = () => async (dispatch: DispatchType, getState: GetStateType) => { const state = getState() const wif = getWif(state) const address = getAddress(state) @@ -67,21 +67,20 @@ export const doClaimNotify = () => (dispatch: DispatchType, getState: GetStateTy claimGasFn = () => doClaimAllGas(net, wif) } - claimGasFn().then((response) => { - if (response.result) { - dispatch(showSuccessNotification({ - message: 'Claim was successful! Your balance will update once the blockchain has processed it.' - })) - setTimeout(() => dispatch(disableClaim(false)), FIVE_MINUTES_MS) - } else { - dispatch(showErrorNotification({ message: 'Claim failed' })) - } - }) + const [err, response] = await asyncWrap(claimGasFn()) + if (!err && response.result) { + dispatch(showSuccessNotification({ + message: 'Claim was successful! Your balance will update once the blockchain has processed it.' + })) + setTimeout(() => dispatch(disableClaim(false)), FIVE_MINUTES_MS) + } else { + return dispatch(showErrorNotification({ message: 'Claim failed' })) + } } // To initiate claim, first send all Neo to own address, the set claimRequest state // When new claims are available, this will trigger the claim -export const doGasClaim = () => (dispatch: DispatchType, getState: GetStateType) => { +export const doGasClaim = () => async (dispatch: DispatchType, getState: GetStateType) => { const state = getState() const wif = getWif(state) const address = getAddress(state) @@ -92,7 +91,7 @@ export const doGasClaim = () => (dispatch: DispatchType, getState: GetStateType) // if no neo in account, no need to send to self first if (neo === 0) { - dispatch(doClaimNotify()) + return dispatch(doClaimNotify()) } else { dispatch(showInfoNotification({ message: 'Sending Neo to Yourself...', dismissible: false })) log(net, 'SEND', address, { to: address, amount: neo, asset: ASSETS.NEO }) @@ -110,15 +109,14 @@ export const doGasClaim = () => (dispatch: DispatchType, getState: GetStateType) sendAssetFn = () => doSendAsset(net, address, wif, { [ASSETS.NEO]: neo }) } - sendAssetFn().then((response) => { - if (response.result === undefined || response.result === false) { - dispatch(showErrorNotification({ message: 'Transaction failed!' })) - } else { - dispatch(showInfoNotification({ message: 'Waiting for transaction to clear...', dismissible: false })) - dispatch(setClaimRequest(true)) - dispatch(disableClaim(true)) - } - }) + const [err, response] = await asyncWrap(sendAssetFn()) + if (err || response.result === undefined || response.result === false) { + return dispatch(showErrorNotification({ message: 'Transaction failed!' })) + } else { + dispatch(showInfoNotification({ message: 'Waiting for transaction to clear...', dismissible: false })) + dispatch(setClaimRequest(true)) + return dispatch(disableClaim(true)) + } } } diff --git a/app/modules/generateWallet.js b/app/modules/generateWallet.js index 54cb28815..b8b950ce1 100644 --- a/app/modules/generateWallet.js +++ b/app/modules/generateWallet.js @@ -3,6 +3,7 @@ import storage from 'electron-json-storage' import { generateEncryptedWif, getAccountFromWIFKey, generatePrivateKey, getWIFFromPrivateKey, encryptWIF, encryptWifAccount } from 'neon-js' import { showErrorNotification, showInfoNotification, hideNotification } from './notification' import { validatePassphrase, checkMatchingPassphrases } from '../core/wallet' +import asyncWrap from '../core/asyncHelper' // Constants export const NEW_WALLET_KEYS = 'NEW_WALLET_KEYS' @@ -47,68 +48,54 @@ export const saveKey = (keyName: string, passphraseKey: string) => (dispatch: Di if (!keyName) { return null } // eslint-disable-next-line - storage.get('keys', (error, data) => { + return storage.get('keys', (error, data) => { data[keyName] = passphraseKey dispatch(showInfoNotification({ message: `Saved key as ${keyName}` })) storage.set('keys', data) }) } -export const generateWalletFromWif = (passphrase: string, passphrase2: string, wif: string) => (dispatch: DispatchType): Promise<*> => { - return new Promise((resolve, reject) => { - const rejectPromise = (error) => { - dispatch(showErrorNotification({ message: error })) - reject(new Error(error)) - } +export const generateWalletFromWif = (passphrase: string, passphrase2: string, wif: string) => async (dispatch: DispatchType): Promise<*> => { + const dispatchError = (message: string) => dispatch(showErrorNotification({ message })) - if (checkMatchingPassphrases(passphrase, passphrase2)) { - rejectPromise('Passphrases do not match') - } else if (validatePassphrase(passphrase)) { - dispatch(showInfoNotification({ message: 'Generating encoded key...', dismissible: false })) - setTimeout(() => { - try { - encryptWifAccount(wif, passphrase).then((result) => { - dispatch(hideNotification({ noAnimation: true })) - dispatch(newWallet(result)) - resolve() - }) - } catch (e) { - rejectPromise('The private key is not valid') - } - }, 500) - } else { - rejectPromise('Please choose a longer passphrase') - } - }) + if (checkMatchingPassphrases(passphrase, passphrase2)) { + return dispatchError('Passphrases do not match') + } else if (validatePassphrase(passphrase)) { + dispatch(showInfoNotification({ message: 'Generating encoded key...', dismissible: false })) + setTimeout(async () => { + try { + const [_err, result] = await asyncWrap(encryptWifAccount(wif, passphrase)) // eslint-disable-line + dispatch(hideNotification({ noAnimation: true })) + return dispatch(newWallet(result)) + } catch (e) { + return dispatchError('The private key is not valid') + } + }, 500) + } else { + return dispatchError('Please choose a longer passphrase') + } } -export const generateNewWallet = (passphrase: string, passphrase2: string) => (dispatch: DispatchType): Promise<*> => { - return new Promise((resolve, reject) => { - const rejectPromise = (error) => { - dispatch(showErrorNotification({ message: error })) - reject(new Error(error)) - } +export const generateNewWallet = (passphrase: string, passphrase2: string) => async (dispatch: DispatchType): Promise<*> => { + const dispatchError = (message: string) => dispatch(showErrorNotification({ message })) - if (checkMatchingPassphrases(passphrase, passphrase2)) { - rejectPromise('Passphrases do not match') - } else if (validatePassphrase(passphrase)) { - dispatch(showInfoNotification({ message: 'Generating encoded key...', dismissible: false })) - setTimeout(() => { - try { - generateEncryptedWif(passphrase).then((result) => { - dispatch(hideNotification({ noAnimation: true })) - dispatch(newWallet(result)) - // dispatch(showSuccessNotification({ message: 'Wallet created successfully' })) - resolve() - }) - } catch (e) { - rejectPromise('An error occured while trying to generate a new wallet') - } - }, 500) - } else { - rejectPromise('Please choose a longer passphrase') - } - }) + if (checkMatchingPassphrases(passphrase, passphrase2)) { + return dispatchError('Passphrases do not match') + } else if (validatePassphrase(passphrase)) { + dispatch(showInfoNotification({ message: 'Generating encoded key...', dismissible: false })) + setTimeout(async () => { + try { + const [_err, result] = await asyncWrap(generateEncryptedWif(passphrase)) //eslint-disable-line + dispatch(hideNotification({ noAnimation: true })) + return dispatch(newWallet(result)) + // dispatch(showSuccessNotification({ message: 'Wallet created successfully' })) + } catch (e) { + return dispatchError('An error occured while trying to generate a new wallet') + } + }, 500) + } else { + return dispatchError('Please choose a longer passphrase') + } } // state getters diff --git a/app/modules/metadata.js b/app/modules/metadata.js index 601292171..109c4ecfa 100644 --- a/app/modules/metadata.js +++ b/app/modules/metadata.js @@ -6,6 +6,7 @@ import { showWarningNotification } from './notification' import { NETWORK, EXPLORER, NEON_WALLET_RELEASE_LINK } from '../core/constants' import { openExternal } from '../core/electron' import { FIVE_MINUTES_MS } from '../core/time' +import asyncWrap from '../core/asyncHelper' // Constants export const SET_HEIGHT = 'SET_HEIGHT' @@ -35,27 +36,27 @@ export function setBlockExplorer (blockExplorer: ExplorerType) { } } -export const checkVersion = () => (dispatch: DispatchType, getState: GetStateType) => { +export const checkVersion = () => async (dispatch: DispatchType, getState: GetStateType) => { const state = getState().metadata const { net } = state const apiEndpoint = getAPIEndpoint(net) - return axios.get(`${apiEndpoint}/v2/version`).then((res) => { - const shouldUpdate = res && res.data && res.data.version !== version && res.data.version !== '0.0.5' - if (shouldUpdate) { - dispatch(showWarningNotification({ - message: `Your wallet is out of date! Please download the latest version from ${NEON_WALLET_RELEASE_LINK}`, - dismissAfter: FIVE_MINUTES_MS, - onClick: () => openExternal(NEON_WALLET_RELEASE_LINK) - })) - } - }).catch((e) => {}) + const [err, res] = await asyncWrap(axios.get(`${apiEndpoint}/v2/version`)) + const shouldUpdate = res && res.data && res.data.version !== version && res.data.version !== '0.0.5' + if (err || shouldUpdate) { + const message = err ? `Error checking wallet version! Please make sure you have downloaded the latest version: ${NEON_WALLET_RELEASE_LINK}` + : `Your wallet is out of date! Please download the latest version from ${NEON_WALLET_RELEASE_LINK}` + return dispatch(showWarningNotification({ + message, + dismissAfter: FIVE_MINUTES_MS, + onClick: () => openExternal(NEON_WALLET_RELEASE_LINK) + })) + } } -export const syncBlockHeight = (net: NetworkType) => (dispatch: DispatchType) => { - getWalletDBHeight(net).then((blockHeight) => { - return dispatch(setBlockHeight(blockHeight)) - }) +export const syncBlockHeight = (net: NetworkType) => async (dispatch: DispatchType) => { + const [_err, blockHeight] = await asyncWrap(getWalletDBHeight(net)) // eslint-disable-line + return dispatch(setBlockHeight(blockHeight)) } // state getters diff --git a/app/modules/notification.js b/app/modules/notification.js index c0135040d..0db2fe0af 100644 --- a/app/modules/notification.js +++ b/app/modules/notification.js @@ -71,7 +71,7 @@ const getDefaultNotificationArgs = ({ dismissAfter, dismissible }: NotificationA }) export const showSuccessNotification = (args: NotificationArgsType) => (dispatch: DispatchType, getState: GetStateType) => { - notificationFactory({ + return notificationFactory({ ...args, ...getDefaultNotificationArgs(args, dispatch, getState), type: NOTIFICATION_TYPES.SUCCESS @@ -79,11 +79,11 @@ export const showSuccessNotification = (args: NotificationArgsType) => (dispatch } export const showStickySuccessNotification = (args: NotificationArgsType) => (dispatch: DispatchType, getState: GetStateType) => { - dispatch(showSuccessNotification({ ...args, dismissible: false })) + return dispatch(showSuccessNotification({ ...args, dismissible: false })) } export const showErrorNotification = (args: NotificationArgsType) => (dispatch: DispatchType, getState: GetStateType) => { - notificationFactory({ + return notificationFactory({ ...args, ...getDefaultNotificationArgs(args, dispatch, getState), type: NOTIFICATION_TYPES.ERROR @@ -91,11 +91,11 @@ export const showErrorNotification = (args: NotificationArgsType) => (dispatch: } export const showStickyErrorNotification = (args: NotificationArgsType) => (dispatch: DispatchType, getState: GetStateType) => { - dispatch(showErrorNotification({ ...args, dismissible: false })) + return dispatch(showErrorNotification({ ...args, dismissible: false })) } export const showWarningNotification = (args: NotificationArgsType) => (dispatch: DispatchType, getState: GetStateType) => { - notificationFactory({ + return notificationFactory({ ...args, ...getDefaultNotificationArgs(args, dispatch, getState), type: NOTIFICATION_TYPES.WARNING @@ -103,11 +103,11 @@ export const showWarningNotification = (args: NotificationArgsType) => (dispatch } export const showStickyWarningNotification = (args: NotificationArgsType) => (dispatch: DispatchType, getState: GetStateType) => { - dispatch(showErrorNotification({ ...args, dismissible: false })) + return dispatch(showErrorNotification({ ...args, dismissible: false })) } export const showInfoNotification = (args: NotificationArgsType) => (dispatch: DispatchType, getState: GetStateType) => { - notificationFactory({ + return notificationFactory({ ...args, ...getDefaultNotificationArgs(args, dispatch, getState), type: NOTIFICATION_TYPES.INFO @@ -115,7 +115,7 @@ export const showInfoNotification = (args: NotificationArgsType) => (dispatch: D } export const showStickyInfoNotification = (args: NotificationArgsType) => (dispatch: DispatchType, getState: GetStateType) => { - dispatch(showInfoNotification({ ...args, dismissible: false })) + return dispatch(showInfoNotification({ ...args, dismissible: false })) } // state Getters diff --git a/app/modules/transactions.js b/app/modules/transactions.js index 3706bbaa3..02a730be4 100644 --- a/app/modules/transactions.js +++ b/app/modules/transactions.js @@ -9,6 +9,7 @@ import { log } from '../util/Logs' import { showErrorNotification, showInfoNotification, showSuccessNotification } from './notification' import { getWif, getPublicKey, getSigningFunction, getAddress } from './account' import { getNetwork } from './metadata' +import asyncWrap from '../core/asyncHelper' // Constants export const TOGGLE_ASSET = 'TOGGLE_ASSET' @@ -19,68 +20,59 @@ export function toggleAsset () { } } -export const syncTransactionHistory = (net: NetworkType, address: string) => (dispatch: DispatchType) => - getTransactionHistory(net, address).then((transactions) => { - const txs = transactions.map(({ NEO, GAS, txid, block_index, neo_sent, neo_gas }: TransactionHistoryType) => ({ - type: neo_sent ? ASSETS.NEO : ASSETS.GAS, - amount: neo_sent ? NEO : GAS, - txid, - block_index - })) - dispatch(setTransactionHistory(txs)) - }) +export const syncTransactionHistory = (net: NetworkType, address: string) => async (dispatch: DispatchType) => { + const [_err, transactions] = await asyncWrap(getTransactionHistory(net, address)) // eslint-disable-line + const txs = transactions.map(({ NEO, GAS, txid, block_index, neo_sent, neo_gas }: TransactionHistoryType) => ({ + type: neo_sent ? ASSETS.NEO : ASSETS.GAS, + amount: neo_sent ? NEO : GAS, + txid, + block_index + })) + return dispatch(setTransactionHistory(txs)) +} -export const sendTransaction = (sendAddress: string, sendAmount: string) => (dispatch: DispatchType, getState: GetStateType): Promise<*> => { - return new Promise((resolve, reject) => { - const state = getState() - const wif = getWif(state) - const address = getAddress(state) - const net = getNetwork(state) - const neo = getNeo(state) - const gas = getGas(state) - const selectedAsset = getSelectedAsset(state) - const signingFunction = getSigningFunction(state) - const publicKey = getPublicKey(state) +export const sendTransaction = (sendAddress: string, sendAmount: string) => async (dispatch: DispatchType, getState: GetStateType): Promise<*> => { + const state = getState() + const wif = getWif(state) + const address = getAddress(state) + const net = getNetwork(state) + const neo = getNeo(state) + const gas = getGas(state) + const selectedAsset = getSelectedAsset(state) + const signingFunction = getSigningFunction(state) + const publicKey = getPublicKey(state) - const rejectTransaction = (error: string) => { - dispatch(showErrorNotification({ message: error })) - reject(new Error(error)) - } + const rejectTransaction = (message: string) => dispatch(showErrorNotification({ message })) - const { error, valid } = validateTransactionBeforeSending(neo, gas, selectedAsset, sendAddress, sendAmount) - if (valid) { - const selfAddress = address - const assetName = selectedAsset === ASSETS_LABELS.NEO ? ASSETS.NEO : ASSETS.GAS - let sendAsset = {} - sendAsset[assetName] = sendAmount + const { error, valid } = validateTransactionBeforeSending(neo, gas, selectedAsset, sendAddress, sendAmount) + if (valid) { + const selfAddress = address + const assetName = selectedAsset === ASSETS_LABELS.NEO ? ASSETS.NEO : ASSETS.GAS + let sendAsset = {} + sendAsset[assetName] = sendAmount - dispatch(showInfoNotification({ message: 'Processing...', dismissible: false })) - log(net, 'SEND', selfAddress, { to: sendAddress, asset: selectedAsset, amount: sendAmount }) + dispatch(showInfoNotification({ message: 'Processing...', dismissible: false })) + log(net, 'SEND', selfAddress, { to: sendAddress, asset: selectedAsset, amount: sendAmount }) - const isHardwareSend = !!publicKey + const isHardwareSend = !!publicKey - let sendAssetFn - if (isHardwareSend) { - dispatch(showInfoNotification({ message: 'Please sign the transaction on your hardware device', dismissible: false })) - sendAssetFn = () => hardwareDoSendAsset(net, sendAddress, publicKey, sendAsset, signingFunction) - } else { - sendAssetFn = () => doSendAsset(net, sendAddress, wif, sendAsset) - } + let sendAssetFn + if (isHardwareSend) { + dispatch(showInfoNotification({ message: 'Please sign the transaction on your hardware device', dismissible: false })) + sendAssetFn = () => hardwareDoSendAsset(net, sendAddress, publicKey, sendAsset, signingFunction) + } else { + sendAssetFn = () => doSendAsset(net, sendAddress, wif, sendAsset) + } - sendAssetFn().then((response) => { - if (response.result === undefined || response.result === false) { - rejectTransaction('Transaction failed!') - } else { - dispatch(showSuccessNotification({ message: 'Transaction complete! Your balance will automatically update when the blockchain has processed it.' })) - } - resolve() - }).catch((e) => { - rejectTransaction('Transaction failed!') - }) + const [err, response] = await asyncWrap(sendAssetFn()) + if (err || response.result === undefined || response.result === false) { + return rejectTransaction('Transaction failed!') } else { - rejectTransaction(error) + return dispatch(showSuccessNotification({ message: 'Transaction complete! Your balance will automatically update when the blockchain has processed it.' })) } - }) + } else { + return rejectTransaction(error) + } } // state getters diff --git a/app/modules/wallet.js b/app/modules/wallet.js index 55bc9ec30..ff42ed227 100644 --- a/app/modules/wallet.js +++ b/app/modules/wallet.js @@ -5,6 +5,7 @@ import { getBalance } from 'neon-js' import { syncTransactionHistory } from './transactions' import { syncAvailableClaim } from './claim' import { syncBlockHeight } from './metadata' +import asyncWrap from '../core/asyncHelper' // Constants export const SET_BALANCE = 'SET_BALANCE' @@ -48,30 +49,24 @@ export function setTransactionHistory (transactions: Array) { } } -export const getMarketPriceUSD = () => (dispatch: DispatchType) => { - return axios.get('https://api.coinmarketcap.com/v1/ticker/neo/?convert=USD').then((response) => { - let lastUSDNEO = Number(response.data[0].price_usd) - dispatch(setNeoPrice(lastUSDNEO)) - }).catch((e) => { - // If API dies, still display balance - }) +export const getMarketPriceUSD = () => async (dispatch: DispatchType) => { + // If API dies, still display balance - ignore _err + const [_err, response] = await asyncWrap(axios.get('https://api.coinmarketcap.com/v1/ticker/neo/?convert=USD')) // eslint-disable-line + let lastUSDNEO = Number(response.data[0].price_usd) + return dispatch(setNeoPrice(lastUSDNEO)) } -export const getGasMarketPriceUSD = () => (dispatch: DispatchType) => { - return axios.get('https://api.coinmarketcap.com/v1/ticker/gas/?convert=USD').then((response) => { - let lastUSDGAS = Number(response.data[0].price_usd) - dispatch(setGasPrice(lastUSDGAS)) - }).catch((e) => { - // If API dies, still display balance - }) +export const getGasMarketPriceUSD = () => async (dispatch: DispatchType) => { + // If API dies, still display balance - ignore _err + const [_err, response] = await asyncWrap(axios.get('https://api.coinmarketcap.com/v1/ticker/gas/?convert=USD')) // eslint-disable-line + let lastUSDGAS = Number(response.data[0].price_usd) + return dispatch(setGasPrice(lastUSDGAS)) } -export const retrieveBalance = (net: NetworkType, address: string) => (dispatch: DispatchType) => { - return getBalance(net, address).then((resultBalance) => { - dispatch(setBalance(resultBalance.NEO.balance, resultBalance.GAS.balance)) - }).catch((result) => { - // If API dies, still display balance - }) +export const retrieveBalance = (net: NetworkType, address: string) => async (dispatch: DispatchType) => { + // If API dies, still display balance - ignore _err + const [_err, resultBalance] = await asyncWrap(getBalance(net, address)) // eslint-disable-line + return dispatch(setBalance(resultBalance.NEO.balance, resultBalance.GAS.balance)) } export const initiateGetBalance = (net: NetworkType, address: string) => (dispatch: DispatchType) => {