mirror of
https://github.com/status-im/MyCrypto.git
synced 2025-01-21 08:28:51 +00:00
0d5d0cea9a
* Add disclaimer modal to footer * Remove duplicate code & unnecessary styles * Fix formatting noise * remove un-used css style * Fix tslint error & add media query for modals * Nest Media Query * Replace '???' with Spinner & update spinner * Add loading states for wallet balances * Update wallet test * Remove excess data passed to wallet balance reducer & Fix wallet balance types * Merge 'develop' into 'loading-indicator' * Add 'light' prop to Spinner * Only show spinners when fetching data * Remove format diff * Apply naming conventions * Remove network name when offline
243 lines
7.1 KiB
TypeScript
243 lines
7.1 KiB
TypeScript
import Identicon from 'components/ui/Identicon';
|
|
import Modal, { IButton } from 'components/ui/Modal';
|
|
import Spinner from 'components/ui/Spinner';
|
|
import { NetworkConfig, NodeConfig } from 'config/data';
|
|
import EthTx from 'ethereumjs-tx';
|
|
import {
|
|
BroadcastTransactionStatus,
|
|
getTransactionFields,
|
|
decodeTransaction
|
|
} from 'libs/transaction';
|
|
import React from 'react';
|
|
import { connect } from 'react-redux';
|
|
import {
|
|
getLanguageSelection,
|
|
getNetworkConfig,
|
|
getNodeConfig
|
|
} from 'selectors/config';
|
|
import { getTokens, getTxFromState, MergedToken } from 'selectors/wallet';
|
|
import translate, { translateRaw } from 'translations';
|
|
import { UnitDisplay } from 'components/ui';
|
|
import './ConfirmationModal.scss';
|
|
|
|
interface Props {
|
|
signedTx: string;
|
|
transaction: EthTx;
|
|
node: NodeConfig;
|
|
token: MergedToken;
|
|
network: NetworkConfig;
|
|
lang: string;
|
|
broadCastTxStatus: BroadcastTransactionStatus;
|
|
decimal: number;
|
|
onConfirm(signedTx: string): void;
|
|
onClose(): void;
|
|
}
|
|
|
|
interface State {
|
|
timeToRead: number;
|
|
hasBroadCasted: boolean;
|
|
}
|
|
|
|
class ConfirmationModal extends React.Component<Props, State> {
|
|
public state = {
|
|
timeToRead: 5,
|
|
hasBroadCasted: false
|
|
};
|
|
|
|
private readTimer = 0;
|
|
|
|
public componentDidUpdate() {
|
|
if (
|
|
this.state.hasBroadCasted &&
|
|
this.props.broadCastTxStatus &&
|
|
!this.props.broadCastTxStatus.isBroadcasting
|
|
) {
|
|
this.props.onClose();
|
|
}
|
|
}
|
|
|
|
// Count down 5 seconds before allowing them to confirm
|
|
public componentDidMount() {
|
|
this.readTimer = window.setInterval(() => {
|
|
if (this.state.timeToRead > 0) {
|
|
this.setState({ timeToRead: this.state.timeToRead - 1 });
|
|
} else {
|
|
window.clearInterval(this.readTimer);
|
|
}
|
|
}, 1000);
|
|
}
|
|
|
|
public render() {
|
|
const {
|
|
node,
|
|
token,
|
|
network,
|
|
onClose,
|
|
broadCastTxStatus,
|
|
transaction,
|
|
decimal
|
|
} = this.props;
|
|
const { timeToRead } = this.state;
|
|
const { toAddress, value, gasPrice, data, from, nonce } = decodeTransaction(
|
|
transaction,
|
|
token
|
|
);
|
|
|
|
const buttonPrefix = timeToRead > 0 ? `(${timeToRead}) ` : '';
|
|
const buttons: IButton[] = [
|
|
{
|
|
text: buttonPrefix + translateRaw('SENDModal_Yes'),
|
|
type: 'primary',
|
|
disabled: timeToRead > 0,
|
|
onClick: this.confirm
|
|
},
|
|
{
|
|
text: translateRaw('SENDModal_No'),
|
|
type: 'default',
|
|
onClick: onClose
|
|
}
|
|
];
|
|
|
|
const symbol = token ? token.symbol : network.unit;
|
|
|
|
const isBroadcasting =
|
|
broadCastTxStatus && broadCastTxStatus.isBroadcasting;
|
|
|
|
return (
|
|
<div className="ConfModalWrap">
|
|
<Modal
|
|
title="Confirm Your Transaction"
|
|
buttons={buttons}
|
|
handleClose={onClose}
|
|
disableButtons={isBroadcasting}
|
|
isOpen={true}
|
|
>
|
|
<div className="ConfModal">
|
|
{isBroadcasting ? (
|
|
<div className="ConfModal-loading">
|
|
<Spinner size="x5" />
|
|
</div>
|
|
) : (
|
|
<div>
|
|
<div className="ConfModal-summary">
|
|
<div className="ConfModal-summary-icon ConfModal-summary-icon--from">
|
|
<Identicon size="100%" address={from} />
|
|
</div>
|
|
<div className="ConfModal-summary-amount">
|
|
<div className="ConfModal-summary-amount-arrow" />
|
|
<div className="ConfModal-summary-amount-currency">
|
|
<UnitDisplay
|
|
decimal={decimal}
|
|
value={value}
|
|
symbol={symbol}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="ConfModal-summary-icon ConfModal-summary-icon--to">
|
|
<Identicon size="100%" address={toAddress} />
|
|
</div>
|
|
</div>
|
|
<ul className="ConfModal-details">
|
|
<li className="ConfModal-details-detail">
|
|
You are sending from <code>{from}</code>
|
|
</li>
|
|
<li className="ConfModal-details-detail">
|
|
You are sending to <code>{toAddress}</code>
|
|
</li>
|
|
<li className="ConfModal-details-detail">
|
|
You are sending with a nonce of <code>{nonce}</code>
|
|
</li>
|
|
<li className="ConfModal-details-detail">
|
|
You are sending{' '}
|
|
<strong>
|
|
<UnitDisplay
|
|
decimal={decimal}
|
|
value={value}
|
|
symbol={symbol}
|
|
/>
|
|
</strong>{' '}
|
|
with a gas price of{' '}
|
|
<strong>
|
|
<UnitDisplay
|
|
unit={'gwei'}
|
|
value={gasPrice}
|
|
symbol={'gwei'}
|
|
/>
|
|
</strong>
|
|
</li>
|
|
<li className="ConfModal-details-detail">
|
|
You are interacting with the <strong>{node.network}</strong>{' '}
|
|
network provided by <strong>{node.service}</strong>
|
|
</li>
|
|
{!token && (
|
|
<li className="ConfModal-details-detail">
|
|
{data ? (
|
|
<span>
|
|
You are sending the following data:{' '}
|
|
<textarea
|
|
className="form-control"
|
|
value={data}
|
|
rows={3}
|
|
disabled={true}
|
|
/>
|
|
</span>
|
|
) : (
|
|
'There is no data attached to this transaction'
|
|
)}
|
|
</li>
|
|
)}
|
|
</ul>
|
|
|
|
<div className="ConfModal-confirm">
|
|
{translate('SENDModal_Content_3')}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</Modal>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
public componentWillUnmount() {
|
|
window.clearInterval(this.readTimer);
|
|
}
|
|
|
|
private confirm = () => {
|
|
if (this.state.timeToRead < 1) {
|
|
this.props.onConfirm(this.props.signedTx);
|
|
this.setState({ hasBroadCasted: true });
|
|
}
|
|
};
|
|
}
|
|
|
|
function mapStateToProps(state, props) {
|
|
// Convert the signedTx to an EthTx transaction
|
|
const transaction = new EthTx(props.signedTx);
|
|
|
|
// Network config for defaults
|
|
const network = getNetworkConfig(state);
|
|
|
|
const node = getNodeConfig(state);
|
|
|
|
const lang = getLanguageSelection(state);
|
|
|
|
const broadCastTxStatus = getTxFromState(state, props.signedTx);
|
|
|
|
// Determine if we're sending to a token from the transaction to address
|
|
const { to, data } = getTransactionFields(transaction);
|
|
const tokens = getTokens(state);
|
|
const token = data && tokens.find(t => t.address === to);
|
|
|
|
return {
|
|
node,
|
|
broadCastTxStatus,
|
|
transaction,
|
|
token,
|
|
network,
|
|
lang
|
|
};
|
|
}
|
|
|
|
export default connect(mapStateToProps)(ConfirmationModal);
|