James Prado c631f45ab7 Improve Gas Price UX (Part 2) (#850)
* Remove gas dropdown & Add gas sliders

* Update styles

* Revert changes made to requestpayment.tsx

* Update style & add custom labels to GasLimitField

* Update styles

* Update confirm transaction modal

* Revert "Update confirm transaction modal"

This reverts commit 743c9a505fe070feb55f7af550ad918a3d8899d1.

* Add transaction fee to tx confirmation modal

* Update styles

* Remove old gasPriceDropdown files & use network units in tx fee

* Add option to lock gaslimit data

* fix tslint errors

* Rename lockData to readOnly

* Add option to check if validAmount before generating transaction

* Add nonce field if gas slider is readonly

* Automatically set nonce in  <Send/>

* Update snapshot

* Move getNonceRequested to GasSlider component

* Add optional to check value for isValidAmount selector

* Add selector for transaction fee

* Update GasSlider component & Rename to Gas

* update snapshots

* Fix subtabs className

* Update styles

* Remove dataField on contract interact

* rename <Gas/> to <TXMetaDataPanel/>
2018-01-24 21:43:27 -06:00

196 lines
5.3 KiB
TypeScript

import React from 'react';
import { connect } from 'react-redux';
import { AppState } from 'reducers';
import translate from 'translations';
import { IWallet } from 'libs/wallet';
import { QRCode } from 'components/ui';
import { getUnit, getDecimal } from 'selectors/transaction/meta';
import {
getCurrentTo,
getCurrentValue,
ICurrentTo,
ICurrentValue
} from 'selectors/transaction/current';
import BN from 'bn.js';
import { NetworkConfig } from 'config';
import { validNumber, validDecimal } from 'libs/validators';
import { getGasLimit } from 'selectors/transaction';
import { AddressField, AmountField, TXMetaDataPanel } from 'components';
import { SetGasLimitFieldAction } from 'actions/transaction/actionTypes/fields';
import { buildEIP681EtherRequest, buildEIP681TokenRequest } from 'libs/values';
import { getNetworkConfig, getSelectedTokenContractAddress } from 'selectors/config';
import './RequestPayment.scss';
import { reset, TReset, setCurrentTo, TSetCurrentTo } from 'actions/transaction';
interface OwnProps {
wallet: AppState['wallet']['inst'];
}
interface StateProps {
unit: string;
currentTo: ICurrentTo;
currentValue: ICurrentValue;
gasLimit: SetGasLimitFieldAction['payload'];
networkConfig: NetworkConfig | undefined;
decimal: number;
tokenContractAddress: string;
}
interface ActionProps {
reset: TReset;
setCurrentTo: TSetCurrentTo;
}
type Props = OwnProps & StateProps & ActionProps;
const isValidAmount = decimal => amount => validNumber(+amount) && validDecimal(amount, decimal);
class RequestPayment extends React.Component<Props, {}> {
public state = {
recipientAddress: ''
};
public componentDidMount() {
if (this.props.wallet) {
this.setWalletAsyncState(this.props.wallet);
}
this.props.reset();
}
public componentWillUnmount() {
this.props.reset();
}
public componentWillReceiveProps(nextProps: Props) {
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">
<AddressField isReadOnly={true} />
<div className="row form-group">
<div className="col-xs-11">
<AmountField
hasUnitDropdown={true}
showAllTokens={true}
customValidator={isValidAmount(decimal)}
/>
</div>
</div>
<div className="row form-group">
<div className="col-xs-11">
<TXMetaDataPanel
initialState="advanced"
disableToggle={true}
advancedGasOptions={{
gasPriceField: false,
nonceField: false,
dataField: false,
feeSummary: false
}}
/>
</div>
</div>
{!!eip681String.length && (
<div className="row form-group">
<div className="col-xs-6">
<label>{translate('Payment QR & Code')}</label>
<div className="RequestPayment-qr well well-lg">
<QRCode data={eip681String} />
</div>
</div>
<div className="col-xs-6 RequestPayment-codeContainer">
<textarea
className="RequestPayment-codeBox form-control"
value={eip681String}
disabled={true}
/>
</div>
</div>
)}
</div>
</div>
);
}
private async setWalletAsyncState(wallet: IWallet) {
this.props.setCurrentTo(await wallet.getAddressString());
}
private generateEIP681String(
currentTo: string,
tokenContractAddress: string,
currentValue,
gasLimit: { raw: string; value: BN | null },
unit: string,
decimal: number,
chainId?: number
) {
if (
!isValidAmount(decimal)(currentValue.raw) ||
!chainId ||
!gasLimit ||
!gasLimit.raw.length ||
!currentTo.length ||
(unit !== 'ether' && !tokenContractAddress.length)
) {
return '';
}
if (unit === 'ether') {
return buildEIP681EtherRequest(currentTo, chainId, currentValue);
} else {
return buildEIP681TokenRequest(
currentTo,
tokenContractAddress,
chainId,
currentValue,
decimal,
gasLimit
);
}
}
}
function mapStateToProps(state: AppState): StateProps {
return {
unit: getUnit(state),
currentTo: getCurrentTo(state),
currentValue: getCurrentValue(state),
gasLimit: getGasLimit(state),
networkConfig: getNetworkConfig(state),
decimal: getDecimal(state),
tokenContractAddress: getSelectedTokenContractAddress(state)
};
}
export default connect(mapStateToProps, { reset, setCurrentTo })(RequestPayment);