Commit 4cb00d95 authored by Kenny Tran's avatar Kenny Tran Committed by Chi Kei Chan

Handle errors in send page and add summary (#79)

* Handle errors in send page and add summary

* Remove output balance check

* Remove unused variables and methods
parent 509ddaea
...@@ -39,7 +39,6 @@ class Send extends Component { ...@@ -39,7 +39,6 @@ class Send extends Component {
pathname: PropTypes.string.isRequired, pathname: PropTypes.string.isRequired,
currentAddress: PropTypes.string, currentAddress: PropTypes.string,
isConnected: PropTypes.bool.isRequired, isConnected: PropTypes.bool.isRequired,
isValid: PropTypes.bool.isRequired,
updateField: PropTypes.func.isRequired, updateField: PropTypes.func.isRequired,
input: PropTypes.string, input: PropTypes.string,
output: PropTypes.string, output: PropTypes.string,
...@@ -47,8 +46,6 @@ class Send extends Component { ...@@ -47,8 +46,6 @@ class Send extends Component {
outputCurrency: PropTypes.string, outputCurrency: PropTypes.string,
recipient: PropTypes.string, recipient: PropTypes.string,
lastEditedField: PropTypes.string, lastEditedField: PropTypes.string,
inputErrors: PropTypes.arrayOf(PropTypes.string),
outputErrors: PropTypes.arrayOf(PropTypes.string),
}; };
static contextTypes = { static contextTypes = {
...@@ -315,24 +312,98 @@ class Send extends Component { ...@@ -315,24 +312,98 @@ class Send extends Component {
} }
} }
renderSubButtonText() { validate() {
if (this.getApprovalStatus() === 'pending') { const {
return [ selectors,
(<img key="pending" className="swap__sub-icon" src={Pending} />), account,
(<span key="text" className="swap__sub-text">Pending</span>) input,
]; output,
} else { inputCurrency,
return '🔒 Unlock' outputCurrency
} = this.props;
let inputError;
let isValid = true;
if (!input || !output || !inputCurrency || !outputCurrency) {
isValid = false;
} }
const { value: inputBalance, decimals: inputDecimals } = inputCurrency === 'ETH' ?
selectors().getBalance(account)
: selectors().getTokenBalance(inputCurrency, account);
if (inputBalance.isLessThan(BN(input * 10 ** inputDecimals))) {
inputError = 'Insufficient Balance';
}
return {
inputError,
outputError: '',
isValid: isValid && !inputError,
};
}
renderSummary(inputError, outputError, inputLabel, outputLabel) {
const {
selectors,
input,
output,
inputCurrency,
outputCurrency,
recipient,
} = this.props;
const { exchangeRate } = this.state;
let nextStepMessage;
if (inputError || outputError) {
nextStepMessage = inputError || outputError;
} else if (!inputCurrency || !outputCurrency) {
nextStepMessage = 'Select a token to continue.';
} else if (inputCurrency === outputCurrency) {
nextStepMessage = 'Must be different token.';
} else if (!input || !output) {
const missingCurrencyValue = !input ? inputCurrency : outputCurrency;
nextStepMessage = `Enter a ${missingCurrencyValue} value to continue.`;
} else if (!recipient) {
nextStepMessage = 'Enter a wallet address to send to.';
}
if (nextStepMessage) {
return (
<div className="swap__summary-wrapper">
<div>{nextStepMessage}</div>
</div>
)
}
const SLIPPAGE = 0.025;
const exchangedOutput = BN(input).multipliedBy(BN(exchangeRate));
const minOutput = exchangedOutput.multipliedBy(1 - SLIPPAGE).toFixed(8);
const maxOutput = exchangedOutput.multipliedBy(1 + SLIPPAGE).toFixed(8);
return (
<div className="swap__summary-wrapper">
<div>
You are selling {b(`${input} ${inputLabel}`)}
</div>
<div className="send__last-summary-text">
<span className="swap__highlight-text">{recipient.slice(0, 6)}</span>
will receive between {b(`${minOutput} ${outputLabel}`)} and {b(`${maxOutput} ${outputLabel}`)}
</div>
</div>
)
} }
render() { render() {
const { lastEditedField, inputCurrency, outputCurrency, input, output, recipient, isValid, outputErrors, inputErrors } = this.props; const { lastEditedField, inputCurrency, outputCurrency, input, output, recipient } = this.props;
const { exchangeRate } = this.state; const { exchangeRate } = this.state;
const inputLabel = this.getTokenLabel(inputCurrency); const inputLabel = this.getTokenLabel(inputCurrency);
const outputLabel = this.getTokenLabel(outputCurrency); const outputLabel = this.getTokenLabel(outputCurrency);
const estimatedText = '(estimated)'; const estimatedText = '(estimated)';
// 0xc41c71CAeA8ccc9AE19c6d8a66c6870C6E9c3632
const { inputError, outputError, isValid } = this.validate();
return ( return (
<div className="send"> <div className="send">
<Header /> <Header />
...@@ -350,9 +421,7 @@ class Send extends Component { ...@@ -350,9 +421,7 @@ class Send extends Component {
}} }}
onValueChange={d => this.updateInput(d)} onValueChange={d => this.updateInput(d)}
selectedTokens={[inputCurrency, outputCurrency]} selectedTokens={[inputCurrency, outputCurrency]}
addError={error => this.props.addError('inputErrors', error)} errorMessage={inputError}
removeError={error => this.props.removeError('inputErrors', error)}
errors={inputErrors}
value={input} value={input}
selectedTokenAddress={inputCurrency} selectedTokenAddress={inputCurrency}
extraText={this.getBalance(inputCurrency)} extraText={this.getBalance(inputCurrency)}
...@@ -371,9 +440,7 @@ class Send extends Component { ...@@ -371,9 +440,7 @@ class Send extends Component {
}} }}
onValueChange={d => this.updateOutput(d)} onValueChange={d => this.updateOutput(d)}
selectedTokens={[inputCurrency, outputCurrency]} selectedTokens={[inputCurrency, outputCurrency]}
addError={error => this.props.addError('outputErrors', error)} errorMessage={outputError}
removeError={error => this.props.removeError('outputErrors', error)}
errors={outputErrors}
value={output} value={output}
selectedTokenAddress={outputCurrency} selectedTokenAddress={outputCurrency}
extraText={this.getBalance(outputCurrency)} extraText={this.getBalance(outputCurrency)}
...@@ -395,24 +462,14 @@ class Send extends Component { ...@@ -395,24 +462,14 @@ class Send extends Component {
</span> </span>
</div> </div>
</OversizedPanel> </OversizedPanel>
{ { this.renderSummary(inputError, outputError, inputLabel, outputLabel) }
inputLabel && input
? (
<div className="swap__summary-wrapper">
<div>You are selling <span className="swap__highlight-text">{`${input} ${inputLabel}`}</span></div>
<div>You will receive between <span className="swap__highlight-text">12.80</span> and <span
className="swap__highlight-text">12.83 BAT</span></div>
</div>
)
: null
}
</div> </div>
<button <button
className={classnames('swap__cta-btn', { className={classnames('swap__cta-btn', {
'swap--inactive': !this.props.isConnected, 'swap--inactive': !this.props.isConnected,
'swap__cta-btn--inactive': !this.props.isValid, 'swap__cta-btn--inactive': !isValid,
})} })}
disabled={!this.props.isValid} disabled={!isValid}
onClick={this.onSend} onClick={this.onSend}
> >
Send Send
...@@ -448,9 +505,6 @@ export default withRouter( ...@@ -448,9 +505,6 @@ export default withRouter(
recipient: state.send.recipient, recipient: state.send.recipient,
lastEditedField: state.send.lastEditedField, lastEditedField: state.send.lastEditedField,
exchangeAddresses: state.addresses.exchangeAddresses, exchangeAddresses: state.addresses.exchangeAddresses,
isValid: isValidSend(state),
inputErrors: state.send.inputErrors,
outputErrors: state.send.outputErrors,
}), }),
dispatch => ({ dispatch => ({
updateField: (name, value) => dispatch(updateField({ name, value })), updateField: (name, value) => dispatch(updateField({ name, value })),
...@@ -462,3 +516,7 @@ export default withRouter( ...@@ -462,3 +516,7 @@ export default withRouter(
}) })
), ),
); );
function b(text) {
return <span className="swap__highlight-text">{text}</span>
}
...@@ -4,4 +4,8 @@ ...@@ -4,4 +4,8 @@
@extend %col-nowrap; @extend %col-nowrap;
height: 100%; height: 100%;
background-color: $white; background-color: $white;
&__last-summary-text {
margin-top: 1rem;
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment