zepio/app/containers/send.js

150 lines
4.4 KiB
JavaScript
Raw Normal View History

2018-12-20 10:56:45 -08:00
// @flow
import { connect } from 'react-redux';
2018-12-21 07:44:11 -08:00
import eres from 'eres';
2019-01-09 05:14:02 -08:00
import { BigNumber } from 'bignumber.js';
2018-12-20 10:56:45 -08:00
2019-01-24 06:56:49 -08:00
import store from '../../config/electron-store';
2018-12-21 07:44:11 -08:00
import rpc from '../../services/api';
2018-12-20 10:56:45 -08:00
import { SendView } from '../views/send';
2018-12-21 07:44:11 -08:00
import {
2019-01-24 06:56:49 -08:00
loadZECPrice,
2018-12-21 07:44:11 -08:00
sendTransaction,
sendTransactionSuccess,
sendTransactionError,
resetSendTransaction,
2019-01-24 06:56:49 -08:00
validateAddressSuccess,
validateAddressError,
2018-12-21 07:44:11 -08:00
} from '../redux/modules/send';
2019-01-29 07:36:13 -08:00
import { filterObjectNullKeys } from '../utils/filter-object-null-keys';
2019-01-07 10:59:27 -08:00
2018-12-20 10:56:45 -08:00
import type { AppState } from '../types/app-state';
2018-12-21 07:44:11 -08:00
import type { Dispatch } from '../types/redux';
2019-01-24 11:26:03 -08:00
import { loadAddressesSuccess, loadAddressesError } from '../redux/modules/receive';
2019-01-24 06:56:49 -08:00
2018-12-21 07:44:11 -08:00
export type SendTransactionInput = {
from: string,
to: string,
2019-01-07 10:59:27 -08:00
amount: string,
2018-12-21 07:44:11 -08:00
fee: number,
memo: string,
};
2018-12-20 10:56:45 -08:00
2019-01-24 06:56:49 -08:00
const mapStateToProps = ({ walletSummary, sendStatus, receive }: AppState) => ({
2018-12-20 10:56:45 -08:00
balance: walletSummary.total,
2019-01-24 06:56:49 -08:00
zecPrice: sendStatus.zecPrice,
addresses: receive.addresses,
2018-12-21 07:44:11 -08:00
error: sendStatus.error,
isSending: sendStatus.isSending,
operationId: sendStatus.operationId,
2019-01-24 06:56:49 -08:00
isToAddressValid: sendStatus.isToAddressValid,
2018-12-21 07:44:11 -08:00
});
const mapDispatchToProps = (dispatch: Dispatch) => ({
sendTransaction: async ({
2019-01-24 11:26:03 -08:00
from, to, amount, fee, memo,
2018-12-21 07:44:11 -08:00
}: SendTransactionInput) => {
dispatch(sendTransaction());
2019-01-28 16:34:07 -08:00
// $FlowFixMe
const [sendErr, operationId] = await eres(
2019-01-07 10:59:27 -08:00
rpc.z_sendmany(
from,
// $FlowFixMe
[
filterObjectNullKeys({
address: to,
2019-01-09 05:14:02 -08:00
amount: new BigNumber(amount).toNumber(),
2019-01-07 10:59:27 -08:00
memo,
}),
],
1,
2019-01-09 05:14:02 -08:00
new BigNumber(fee).toNumber(),
2019-01-07 10:59:27 -08:00
),
2018-12-21 07:44:11 -08:00
);
2019-01-24 06:56:49 -08:00
// eslint-disable-next-line max-len
if (sendErr || !operationId) return dispatch(sendTransactionError({ error: sendErr.message }));
2018-12-21 07:44:11 -08:00
2019-01-24 06:56:49 -08:00
/**
Output is a list of operation status objects.
[
{operationid: opid-12ee,
status: queued},
{operationid: opd-098a, status: executing},
{operationid: opid-9876, status: failed}
]
When the operation succeeds, the status object will also include the result.
{operationid: opid-0e0e, status:success, execution_time:25, result: {txid:af3887654,...}}
then the promise will only be resolved when a "success" or "failure" status is obtained
*/
const interval = setInterval(async () => {
const [, status] = await eres(rpc.z_getoperationstatus());
const operationStatus = status.find(({ id }) => operationId === id);
if (operationStatus && operationStatus.status === 'success') {
clearInterval(interval);
2019-01-24 11:26:03 -08:00
dispatch(sendTransactionSuccess({ operationId: operationStatus.result.txid }));
2019-01-24 06:56:49 -08:00
}
if (operationStatus && operationStatus.status === 'failed') {
clearInterval(interval);
2019-01-24 11:26:03 -08:00
dispatch(sendTransactionError({ error: operationStatus.error.message }));
2019-01-24 06:56:49 -08:00
}
}, 2000);
2018-12-21 07:44:11 -08:00
},
resetSendView: () => dispatch(resetSendTransaction()),
2019-01-24 06:56:49 -08:00
validateAddress: async ({ address }: { address: string }) => {
if (address.startsWith('z')) {
const [, validationResult] = await eres(rpc.z_validateaddress(address));
return dispatch(
validateAddressSuccess({
isValid: Boolean(validationResult && validationResult.isvalid),
}),
);
}
const [, validationResult] = await eres(rpc.validateaddress(address));
if (validationResult) {
return dispatch(
validateAddressSuccess({
isValid: Boolean(validationResult && validationResult.isvalid),
}),
);
}
return dispatch(validateAddressError());
},
loadAddresses: async () => {
const [zAddressesErr, zAddresses] = await eres(rpc.z_listaddresses());
2019-01-24 11:26:03 -08:00
const [tAddressesErr, transparentAddresses] = await eres(rpc.getaddressesbyaccount(''));
2019-01-24 06:56:49 -08:00
if (zAddressesErr || tAddressesErr) return dispatch(loadAddressesError({ error: 'Something went wrong!' }));
dispatch(
loadAddressesSuccess({
addresses: [...zAddresses, ...transparentAddresses],
}),
);
},
loadZECPrice: () => dispatch(
loadZECPrice({
2019-01-28 16:34:07 -08:00
value: Number(store.get('ZEC_DOLLAR_PRICE')),
2019-01-24 06:56:49 -08:00
}),
),
2018-12-20 10:56:45 -08:00
});
// $FlowFixMe
2018-12-21 07:44:11 -08:00
export const SendContainer = connect(
mapStateToProps,
mapDispatchToProps,
)(SendView);