MyCrypto/common/containers/Tabs/SendTransaction/index.jsx

284 lines
8.0 KiB
React
Raw Normal View History

2017-06-26 22:27:55 +00:00
// @flow
import React from 'react';
import PropTypes from 'prop-types';
import translate from 'translations';
import { UnlockHeader } from 'components/ui';
import {
2017-07-02 05:49:06 +00:00
Donate,
DataField,
CustomMessage,
GasField,
AmountField,
AddressField
2017-06-26 22:27:55 +00:00
} from './components';
import pickBy from 'lodash/pickBy';
2017-06-29 23:03:11 +00:00
import type { State as AppState } from 'reducers';
import { connect } from 'react-redux';
import BaseWallet from 'libs/wallet/base';
2017-06-26 22:27:55 +00:00
// import type { Transaction } from './types';
import customMessages from './messages';
import { donationAddressMap } from 'config/data';
2017-06-26 22:27:55 +00:00
type State = {
2017-07-02 05:49:06 +00:00
hasQueryString: boolean,
readOnly: boolean,
to: string,
value: string,
unit: string,
gasLimit: string,
data: string,
gasChanged: boolean
2017-06-26 22:27:55 +00:00
};
function getParam(query: { [string]: string }, key: string) {
2017-07-02 05:49:06 +00:00
const keys = Object.keys(query);
const index = keys.findIndex(k => k.toLowerCase() === key.toLowerCase());
if (index === -1) {
return null;
}
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
return query[keys[index]];
2017-06-26 22:27:55 +00:00
}
// TODO query string
// TODO how to handle DATA?
export class SendTransaction extends React.Component {
2017-07-02 05:49:06 +00:00
static propTypes = {
location: PropTypes.object.isRequired
};
props: {
location: {
query: {
[string]: string
}
2017-07-04 03:21:19 +00:00
},
wallet: BaseWallet
2017-07-02 05:49:06 +00:00
};
state: State = {
hasQueryString: false,
readOnly: false,
// FIXME use correct defaults
to: '',
value: '999.11',
unit: 'ether',
gasLimit: '21000',
data: '',
gasChanged: false
};
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
componentDidMount() {
const queryPresets = pickBy(this.parseQuery());
if (Object.keys(queryPresets).length) {
this.setState({ ...queryPresets, hasQueryString: true });
2017-06-26 22:27:55 +00:00
}
2017-07-02 05:49:06 +00:00
}
render() {
2017-07-04 03:21:19 +00:00
const unlocked = !!this.props.wallet;
2017-07-02 05:49:06 +00:00
const unitReadable = 'UNITREADABLE';
const nodeUnit = 'NODEUNIT';
const hasEnoughBalance = false;
const {
to,
value,
unit,
gasLimit,
data,
readOnly,
hasQueryString
} = this.state;
const customMessage = customMessages.find(m => m.to === to);
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
// tokens
// ng-show="token.balance!=0 && token.balance!='loading' || token.type!=='default' || tokenVisibility=='shown'"
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
return (
<section className="container" style={{ minHeight: '50%' }}>
<div className="tab-content">
<main className="tab-pane active">
2017-07-02 05:49:06 +00:00
{hasQueryString &&
<div className="alert alert-info">
<p>
{translate('WARN_Send_Link')}
</p>
</div>}
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
<UnlockHeader title={'NAV_SendEther'} />
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
{unlocked &&
<article className="row">
{'' /* <!-- Sidebar --> */}
<section className="col-sm-4">
<div style={{ maxWidth: 350 }}>
{'' /* <wallet-balance-drtv /> */}
<hr />
<Donate onDonate={this.onNewTx} />
</div>
</section>
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
<section className="col-sm-8">
{readOnly &&
!hasEnoughBalance &&
<div className="row form-group">
<div className="alert alert-danger col-xs-12 clearfix">
<strong>
Warning! You do not have enough funds to
complete this swap.
2017-07-04 03:21:19 +00:00
</strong>{' '}
2017-07-02 05:49:06 +00:00
<br />
Please add more funds or access a different wallet.
</div>
</div>}
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
<div className="row form-group">
<h4 className="col-xs-12">
{translate('SEND_trans')}
</h4>
</div>
<AddressField
placeholder={donationAddressMap.ETH}
2017-07-02 05:49:06 +00:00
value={this.state.to}
onChange={readOnly ? null : this.onAddressChange}
/>
<AmountField
value={value}
unit={unit}
onChange={readOnly ? void 0 : this.onAmountChange}
/>
<GasField
value={gasLimit}
onChange={readOnly ? void 0 : this.onGasChange}
/>
{unit === 'ether' &&
<DataField
value={data}
onChange={readOnly ? void 0 : this.onDataChange}
/>}
<CustomMessage message={customMessage} />
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
<div className="row form-group">
<div className="col-xs-12 clearfix">
<a
className="btn btn-info btn-block"
onClick={this.generateTx}
>
{translate('SEND_generate')}
</a>
</div>
</div>
2017-06-26 22:27:55 +00:00
<div className="row form-group">
2017-07-02 05:49:06 +00:00
<div className="col-sm-6">
<label> {translate('SEND_raw')} </label>
2017-07-02 05:49:06 +00:00
<textarea className="form-control" rows="4" readOnly>
{'' /*rawTx*/}
</textarea>
</div>
<div className="col-sm-6">
<label>
{translate('SEND_signed')}
2017-07-02 05:49:06 +00:00
</label>
<textarea className="form-control" rows="4" readOnly>
{'' /*signedTx*/}
</textarea>
</div>
</div>
2017-06-26 22:27:55 +00:00
<div className="form-group">
2017-07-02 05:49:06 +00:00
<a
className="btn btn-primary btn-block col-sm-11"
data-toggle="modal"
data-target="#sendTransaction"
>
{translate('SEND_trans')}
2017-07-02 05:49:06 +00:00
</a>
</div>
</section>
{'' /* <!-- / Content --> */}
{
'' /* @@if (site === 'mew' ) { @@include( './sendTx-content.tpl', { "site": "mew" } ) }
2017-06-26 22:27:55 +00:00
@@if (site === 'cx' ) { @@include( './sendTx-content.tpl', { "site": "cx" } ) }
@@if (site === 'mew' ) { @@include( './sendTx-modal.tpl', { "site": "mew" } ) }
@@if (site === 'cx' ) { @@include( './sendTx-modal.tpl', { "site": "cx" } ) } */
2017-07-02 05:49:06 +00:00
}
</article>}
</main>
</div>
</section>
);
}
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
parseQuery() {
const query = this.props.location.query;
const to = getParam(query, 'to');
const data = getParam(query, 'data');
// FIXME validate token against presets
const unit = getParam(query, 'tokenSymbol');
const value = getParam(query, 'value');
let gasLimit = getParam(query, 'gas');
if (gasLimit === null) {
gasLimit = getParam(query, 'limit');
2017-06-26 22:27:55 +00:00
}
2017-07-02 05:49:06 +00:00
const readOnly = getParam(query, 'readOnly') == null ? false : true;
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
return { to, data, value, unit, gasLimit, readOnly };
}
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
// FIXME use mkTx instead or something that could take care of default gas/data and whatnot,
// FIXME also should it reset gasChanged?
onNewTx = (
address: string,
amount: string,
unit: string,
data: string = '',
gasLimit: string = '21000'
) => {
this.setState({
to: address,
value: amount,
unit,
data,
gasLimit,
gasChanged: false
});
};
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
onAddressChange = (value: string) => {
this.setState({
to: value
});
};
onDataChange = (value: string) => {
if (this.state.unit !== 'ether') {
return;
}
this.setState({
...this.state,
data: value
});
};
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
onGasChange = (value: string) => {
this.setState({ gasLimit: value, gasChanged: true });
};
2017-06-26 22:27:55 +00:00
2017-07-02 05:49:06 +00:00
onAmountChange = (value: string, unit: string) => {
this.setState({
value,
unit
});
};
2017-06-26 22:27:55 +00:00
}
2017-06-29 23:03:11 +00:00
function mapStateToProps(state: AppState) {
2017-07-04 03:21:19 +00:00
return {
wallet: state.wallet.inst
};
2017-06-29 23:03:11 +00:00
}
export default connect(mapStateToProps)(SendTransaction);