2018-01-02 22:18:10 -05:00
|
|
|
import React from 'react';
|
|
|
|
import { connect } from 'react-redux';
|
2018-06-17 20:53:00 -05:00
|
|
|
import BN from 'bn.js';
|
|
|
|
|
2018-01-02 22:18:10 -05:00
|
|
|
import translate from 'translations';
|
|
|
|
import { IWallet } from 'libs/wallet';
|
2018-03-14 15:51:37 -04:00
|
|
|
import { validPositiveNumber, validDecimal } from 'libs/validators';
|
2018-01-02 22:18:10 -05:00
|
|
|
import { buildEIP681EtherRequest, buildEIP681TokenRequest } from 'libs/values';
|
2018-06-17 20:53:00 -05:00
|
|
|
import { ICurrentTo, ICurrentValue } from 'features/types';
|
|
|
|
import { AppState } from 'features/reducers';
|
|
|
|
import * as derivedSelectors from 'features/selectors';
|
|
|
|
import { getNetworkConfig, isNetworkUnit } from 'features/config';
|
2018-04-23 19:35:24 -04:00
|
|
|
import {
|
2018-06-17 20:53:00 -05:00
|
|
|
transactionFieldsTypes,
|
|
|
|
transactionFieldsActions,
|
|
|
|
transactionFieldsSelectors,
|
|
|
|
transactionMetaSelectors,
|
|
|
|
transactionActions
|
|
|
|
} from 'features/transaction';
|
|
|
|
import { AddressField, AmountField, TXMetaDataPanel } from 'components';
|
|
|
|
import { QRCode, CodeBlock } from 'components/ui';
|
2018-02-12 15:43:07 -05:00
|
|
|
import { NetworkConfig } from 'types/network';
|
2018-06-17 20:53:00 -05:00
|
|
|
import './RequestPayment.scss';
|
2018-01-02 22:18:10 -05:00
|
|
|
|
|
|
|
interface OwnProps {
|
|
|
|
wallet: AppState['wallet']['inst'];
|
|
|
|
}
|
|
|
|
|
|
|
|
interface StateProps {
|
|
|
|
unit: string;
|
|
|
|
currentTo: ICurrentTo;
|
|
|
|
currentValue: ICurrentValue;
|
2018-06-17 20:53:00 -05:00
|
|
|
gasLimit: transactionFieldsTypes.SetGasLimitFieldAction['payload'];
|
2018-02-12 15:43:07 -05:00
|
|
|
networkConfig: NetworkConfig;
|
2018-01-02 22:18:10 -05:00
|
|
|
decimal: number;
|
|
|
|
tokenContractAddress: string;
|
2018-03-01 20:24:14 -05:00
|
|
|
isNetworkUnit: boolean;
|
2018-01-02 22:18:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
interface ActionProps {
|
2018-06-17 20:53:00 -05:00
|
|
|
resetTransactionRequested: transactionFieldsActions.TResetTransactionRequested;
|
|
|
|
setCurrentTo: transactionActions.TSetCurrentTo;
|
2018-01-02 22:18:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
type Props = OwnProps & StateProps & ActionProps;
|
|
|
|
|
2018-03-07 18:36:05 -05:00
|
|
|
const isValidAmount = (decimal: number) => (amount: string) =>
|
2018-03-14 15:51:37 -04:00
|
|
|
validPositiveNumber(+amount) && validDecimal(amount, decimal);
|
2018-01-02 22:18:10 -05:00
|
|
|
|
|
|
|
class RequestPayment extends React.Component<Props, {}> {
|
|
|
|
public state = {
|
|
|
|
recipientAddress: ''
|
|
|
|
};
|
|
|
|
|
|
|
|
public componentDidMount() {
|
2018-04-23 19:35:24 -04:00
|
|
|
this.props.resetTransactionRequested();
|
2018-01-02 22:18:10 -05:00
|
|
|
if (this.props.wallet) {
|
|
|
|
this.setWalletAsyncState(this.props.wallet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public componentWillUnmount() {
|
2018-04-23 19:35:24 -04:00
|
|
|
this.props.resetTransactionRequested();
|
2018-01-02 22:18:10 -05:00
|
|
|
}
|
|
|
|
|
2018-05-10 22:34:27 -04:00
|
|
|
public UNSAFE_componentWillReceiveProps(nextProps: Props) {
|
2018-01-02 22:18:10 -05:00
|
|
|
if (nextProps.wallet && this.props.wallet !== nextProps.wallet) {
|
|
|
|
this.setWalletAsyncState(nextProps.wallet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public render() {
|
|
|
|
const {
|
|
|
|
tokenContractAddress,
|
|
|
|
gasLimit,
|
|
|
|
currentTo,
|
|
|
|
currentValue,
|
|
|
|
networkConfig,
|
|
|
|
unit,
|
|
|
|
decimal
|
|
|
|
} = this.props;
|
|
|
|
const chainId = networkConfig ? networkConfig.chainId : undefined;
|
|
|
|
|
|
|
|
const eip681String = this.generateEIP681String(
|
|
|
|
currentTo.raw,
|
|
|
|
tokenContractAddress,
|
|
|
|
currentValue,
|
|
|
|
gasLimit,
|
|
|
|
unit,
|
|
|
|
decimal,
|
|
|
|
chainId
|
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="RequestPayment">
|
|
|
|
<div className="Tab-content-pane">
|
2018-04-02 14:38:54 -05:00
|
|
|
<AddressField isReadOnly={true} isCheckSummed={true} />
|
2018-01-02 22:18:10 -05:00
|
|
|
|
|
|
|
<div className="row form-group">
|
2018-03-22 14:30:51 -04:00
|
|
|
<div className="col-xs-12">
|
2018-01-02 22:18:10 -05:00
|
|
|
<AmountField
|
|
|
|
hasUnitDropdown={true}
|
|
|
|
showAllTokens={true}
|
|
|
|
customValidator={isValidAmount(decimal)}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="row form-group">
|
2018-03-22 14:30:51 -04:00
|
|
|
<div className="col-xs-12">
|
2018-01-24 22:43:27 -05:00
|
|
|
<TXMetaDataPanel
|
|
|
|
initialState="advanced"
|
|
|
|
disableToggle={true}
|
|
|
|
advancedGasOptions={{
|
|
|
|
gasPriceField: false,
|
|
|
|
nonceField: false,
|
|
|
|
dataField: false,
|
|
|
|
feeSummary: false
|
|
|
|
}}
|
|
|
|
/>
|
2018-01-02 22:18:10 -05:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
{!!eip681String.length && (
|
|
|
|
<div className="row form-group">
|
2018-03-21 23:50:25 -04:00
|
|
|
<label className="RequestPayment-title">
|
|
|
|
{translate('REQUEST_PAYMENT_QR_TITLE')}
|
|
|
|
</label>
|
2018-01-02 22:18:10 -05:00
|
|
|
<div className="col-xs-6">
|
|
|
|
<div className="RequestPayment-qr well well-lg">
|
|
|
|
<QRCode data={eip681String} />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="col-xs-6 RequestPayment-codeContainer">
|
2018-03-23 12:41:47 -04:00
|
|
|
<CodeBlock className="wrap">{eip681String}</CodeBlock>
|
2018-01-02 22:18:10 -05:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-02-21 12:23:04 -06:00
|
|
|
private setWalletAsyncState(wallet: IWallet) {
|
|
|
|
this.props.setCurrentTo(wallet.getAddressString());
|
2018-01-02 22:18:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
private generateEIP681String(
|
|
|
|
currentTo: string,
|
|
|
|
tokenContractAddress: string,
|
2018-03-07 18:36:05 -05:00
|
|
|
currentValue: { raw: string; value: BN | null },
|
2018-01-02 22:18:10 -05:00
|
|
|
gasLimit: { raw: string; value: BN | null },
|
|
|
|
unit: string,
|
|
|
|
decimal: number,
|
|
|
|
chainId?: number
|
|
|
|
) {
|
|
|
|
if (
|
|
|
|
!isValidAmount(decimal)(currentValue.raw) ||
|
|
|
|
!chainId ||
|
|
|
|
!gasLimit ||
|
|
|
|
!gasLimit.raw.length ||
|
|
|
|
!currentTo.length ||
|
2018-03-01 23:31:27 -06:00
|
|
|
(unit !== 'ETH' && !tokenContractAddress.length)
|
2018-01-02 22:18:10 -05:00
|
|
|
) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
2018-03-07 18:36:05 -05:00
|
|
|
const currentValueIsEther = (
|
|
|
|
_: AppState['transaction']['fields']['value'] | AppState['transaction']['meta']['tokenTo']
|
|
|
|
): _ is AppState['transaction']['fields']['value'] => this.props.isNetworkUnit;
|
|
|
|
|
|
|
|
if (currentValueIsEther(currentValue)) {
|
2018-01-02 22:18:10 -05:00
|
|
|
return buildEIP681EtherRequest(currentTo, chainId, currentValue);
|
|
|
|
} else {
|
|
|
|
return buildEIP681TokenRequest(
|
|
|
|
currentTo,
|
|
|
|
tokenContractAddress,
|
|
|
|
chainId,
|
|
|
|
currentValue,
|
|
|
|
decimal,
|
|
|
|
gasLimit
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function mapStateToProps(state: AppState): StateProps {
|
|
|
|
return {
|
2018-06-17 20:53:00 -05:00
|
|
|
unit: derivedSelectors.getUnit(state),
|
|
|
|
currentTo: derivedSelectors.getCurrentTo(state),
|
|
|
|
currentValue: derivedSelectors.getCurrentValue(state),
|
|
|
|
gasLimit: transactionFieldsSelectors.getGasLimit(state),
|
2018-01-02 22:18:10 -05:00
|
|
|
networkConfig: getNetworkConfig(state),
|
2018-06-17 20:53:00 -05:00
|
|
|
decimal: transactionMetaSelectors.getDecimal(state),
|
|
|
|
tokenContractAddress: derivedSelectors.getSelectedTokenContractAddress(state),
|
|
|
|
isNetworkUnit: isNetworkUnit(state, derivedSelectors.getUnit(state))
|
2018-01-02 22:18:10 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-06-17 20:53:00 -05:00
|
|
|
export default connect(mapStateToProps, {
|
|
|
|
resetTransactionRequested: transactionFieldsActions.resetTransactionRequested,
|
|
|
|
setCurrentTo: transactionActions.setCurrentTo
|
|
|
|
})(RequestPayment);
|