Browse Source

proper errors handling

v0.25
pbca26 7 years ago
parent
commit
1241ce61d9
  1. 37
      react/src/actions/actions/electrum.js
  2. 43
      react/src/components/dashboard/sendCoin/sendCoin.js
  3. 71
      react/src/components/dashboard/sendCoin/sendCoin.render.js
  4. 4
      react/src/components/dashboard/walletsBalance/walletsBalance.js
  5. 122
      react/src/components/dashboard/walletsBalance/walletsBalance.render.js
  6. 22
      react/src/components/dashboard/walletsData/walletsData.js
  7. 2
      react/src/components/dashboard/walletsData/walletsData.render.js
  8. 4
      react/src/components/overrides.scss

37
react/src/actions/actions/electrum.js

@ -206,10 +206,8 @@ export function shepherdElectrumCoinsState(json) {
// value in sats
export function shepherdElectrumSend(coin, value, sendToAddress, changeAddress) {
// console.log(`http://127.0.0.1:${Config.agamaPort}/shepherd/electrum/createrawtx?coin=${coin}&address=${sendToAddress}&value=${value}&change=${changeAddress}&gui=true`);
return dispatch => {
return fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/electrum/createrawtx?coin=${coin}&address=${sendToAddress}&value=${value}&change=${changeAddress}&gui=true&push=true`, {
return fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/electrum/createrawtx?coin=${coin}&address=${sendToAddress}&value=${value}&change=${changeAddress}&gui=true&push=true&verify=true`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
@ -228,7 +226,38 @@ export function shepherdElectrumSend(coin, value, sendToAddress, changeAddress)
.then(response => response.json())
.then(json => {
console.warn(json);
dispatch(sendToAddressState(json.result));
if (json.msg === 'error') {
dispatch(sendToAddressState(json));
} else {
dispatch(sendToAddressState(json.result));
}
});
}
}
export function shepherdElectrumSendPreflight(coin, value, sendToAddress, changeAddress) {
return new Promise((resolve, reject) => {
fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/electrum/createrawtx?coin=${coin}&address=${sendToAddress}&value=${value}&change=${changeAddress}&gui=true&push=false&verify=true`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
}
})
.catch(function(error) {
console.log(error);
dispatch(
triggerToaster(
'shepherdElectrumSendPreflight',
'Error',
'error'
)
)
})
.then(response => response.json())
.then(json => {
console.warn(json);
resolve(json);
// dispatch(sendToAddressState(json.result));
});
});
}

43
react/src/components/dashboard/sendCoin/sendCoin.js

@ -8,7 +8,8 @@ import {
sendNativeTx,
getKMDOPID,
clearLastSendToResponseState,
shepherdElectrumSend
shepherdElectrumSend,
shepherdElectrumSendPreflight
} from '../../../actions/actionCreators';
import Store from '../../../store';
import {
@ -39,6 +40,8 @@ class SendCoin extends React.Component {
substractFee: false,
lastSendToResponse: null,
coin: null,
spvVerificationWarning: false,
spvPreflightSendInProgress: false,
};
this.updateInput = this.updateInput.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
@ -347,6 +350,8 @@ class SendCoin extends React.Component {
if (back) {
this.setState({
currentStep: 0,
spvVerificationWarning: false,
spvPreflightSendInProgress: false,
});
} else {
Store.dispatch(clearLastSendToResponseState());
@ -363,6 +368,8 @@ class SendCoin extends React.Component {
addressSelectorOpen: false,
renderAddressDropdown: true,
substractFee: false,
spvVerificationWarning: false,
spvPreflightSendInProgress: false,
});
}
}
@ -370,17 +377,41 @@ class SendCoin extends React.Component {
if (step === 1) {
if (!this.validateSendFormData()) {
return;
} else {
this.setState(Object.assign({}, this.state, {
spvPreflightSendInProgress: this.props.ActiveCoin.mode === 'spv' ? true : false,
currentStep: step,
}));
// spv pre tx push request
if (this.props.ActiveCoin.mode === 'spv') {
shepherdElectrumSendPreflight(
this.props.ActiveCoin.coin,
this.state.amount * 100000000,
this.state.sendTo,
this.props.Dashboard.electrumCoins[this.props.ActiveCoin.coin].pub
)
.then((sendPreflight) => {
if (sendPreflight &&
sendPreflight.msg === 'success') {
this.setState(Object.assign({}, this.state, {
spvVerificationWarning: !sendPreflight.result.utxoVerified,
spvPreflightSendInProgress: false,
}));
} else {
this.setState(Object.assign({}, this.state, {
spvPreflightSendInProgress: false,
}));
}
});
}
}
}
if (step === 1 ||
step === 2) {
if (step === 2) {
this.setState(Object.assign({}, this.state, {
currentStep: step,
}));
}
if (step === 2) {
this.handleSubmit();
}
}

71
react/src/components/dashboard/sendCoin/sendCoin.render.js

@ -216,6 +216,17 @@ export const SendRender = function() {
</div>
</div>
}
{ this.state.spvPreflightSendInProgress &&
<div className="padding-top-20">Verifying transaction data...</div>
}
{ this.state.spvVerificationWarning &&
<div
className="padding-top-20"
style={{ fontSize: '15px' }}>
<strong className="color-warning">Warning:</strong> your wallet data is verified only by a single server!<br />
If you still want to continue press "Confirm".
</div>
}
<div className="widget-body-footer">
<a
className="btn btn-default waves-effect waves-light"
@ -240,28 +251,44 @@ export const SendRender = function() {
{ translate('INDEX.TRANSACTION_RESULT') }
</h4>
<div>
<table className="table table-hover table-striped">
<thead>
<tr>
<th>{ translate('INDEX.KEY') }</th>
<th>{ translate('INDEX.INFO') }</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Result
</td>
<td>
<span className="label label-success">success</span>
</td>
</tr>
<tr>
<td>Transaction ID</td>
<td>{ this.props.ActiveCoin.mode === 'spv' ? (this.state.lastSendToResponse && this.state.lastSendToResponse.txid ? this.state.lastSendToResponse.txid : '') : this.state.lastSendToResponse }</td>
</tr>
</tbody>
</table>
{ this.state.lastSendToResponse &&
!this.state.lastSendToResponse.msg &&
<table className="table table-hover table-striped">
<thead>
<tr>
<th className="padding-left-30">{ translate('INDEX.KEY') }</th>
<th className="padding-left-30">{ translate('INDEX.INFO') }</th>
</tr>
</thead>
<tbody>
<tr>
<td className="padding-left-30">
Result
</td>
<td className="padding-left-30">
<span className="label label-success">success</span>
</td>
</tr>
<tr>
<td className="padding-left-30">Transaction ID</td>
<td className="padding-left-30">{ this.props.ActiveCoin.mode === 'spv' ? (this.state.lastSendToResponse && this.state.lastSendToResponse.txid ? this.state.lastSendToResponse.txid : '') : this.state.lastSendToResponse }</td>
</tr>
</tbody>
</table>
}
{ !this.state.lastSendToResponse &&
<div className="padding-left-30 padding-top-10">Processing transaction...</div>
}
{ this.state.lastSendToResponse &&
this.state.lastSendToResponse.msg &&
this.state.lastSendToResponse.msg === 'error' &&
<div className="padding-left-30 padding-top-10">
<div>
<strong>Error</strong>
</div>
<div>{ this.state.lastSendToResponse.result }</div>
</div>
}
</div>
<div className="widget-body-footer">
<div className="widget-actions margin-bottom-15 margin-right-15">

4
react/src/components/dashboard/walletsBalance/walletsBalance.js

@ -53,6 +53,10 @@ class WalletsBalance extends React.Component {
let _balance = 0;
const _mode = this.props.ActiveCoin.mode;
if (this.props.ActiveCoin.balance === 'connection error or incomplete data') {
_balance = '-777';
}
if (_mode === 'native') {
if (type === 'total' &&
this.props.ActiveCoin.balance &&

122
react/src/components/dashboard/walletsBalance/walletsBalance.render.js

@ -8,90 +8,92 @@ const WalletsBalanceRender = function() {
<div
id="wallet-widgets"
className="wallet-widgets">
<div className="col-xs-12 flex">
<div className={ this.props.ActiveCoin.coin === 'CHIPS' || (this.props.ActiveCoin.mode === 'spv' && this.props.ActiveCoin.coin !== 'KMD') || this.renderBalance('total') === this.renderBalance('transparent') || this.renderBalance('total') === 0 ? 'col-lg-12 col-xs-12 balance-placeholder--bold' : 'col-lg-3 col-xs-12' }>
<div className="widget widget-shadow">
<div className="widget-content">
<i
className="icon fa-refresh manual-balance-refresh pointer"
onClick={ this.refreshBalance }></i>
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
{ this.props.ActiveCoin.coin !== 'CHIPS' && this.props.ActiveCoin.mode !== 'spv' &&
<i className="icon fa-eye font-size-24 vertical-align-bottom margin-right-5"></i>
}
{ this.props.ActiveCoin.coin === 'CHIPS' || this.props.ActiveCoin.mode === 'spv' ? translate('INDEX.BALANCE') : translate('INDEX.TRANSPARENT_BALANCE') }
{ this.renderBalance('transparent') !== -777 &&
<div className="col-xs-12 flex">
<div className={ this.props.ActiveCoin.coin === 'CHIPS' || (this.props.ActiveCoin.mode === 'spv' && this.props.ActiveCoin.coin !== 'KMD') || this.renderBalance('total') === this.renderBalance('transparent') || this.renderBalance('total') === 0 ? 'col-lg-12 col-xs-12 balance-placeholder--bold' : 'col-lg-3 col-xs-12' }>
<div className="widget widget-shadow">
<div className="widget-content">
<i
className="icon fa-refresh manual-balance-refresh pointer"
onClick={ this.refreshBalance }></i>
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
{ this.props.ActiveCoin.coin !== 'CHIPS' && this.props.ActiveCoin.mode !== 'spv' &&
<i className="icon fa-eye font-size-24 vertical-align-bottom margin-right-5"></i>
}
{ this.props.ActiveCoin.coin === 'CHIPS' || this.props.ActiveCoin.mode === 'spv' ? translate('INDEX.BALANCE') : translate('INDEX.TRANSPARENT_BALANCE') }
</div>
<span
className="pull-right padding-top-10 font-size-22"
title={ this.renderBalance('transparent') }>
{ Config.roundValues ? formatValue(this.renderBalance('transparent')) : this.renderBalance('transparent') }
</span>
</div>
<span
className="pull-right padding-top-10 font-size-22"
title={ this.renderBalance('transparent') }>
{ Config.roundValues ? formatValue(this.renderBalance('transparent')) : this.renderBalance('transparent') }
</span>
</div>
</div>
</div>
</div>
</div>
<div className={ (this.props.ActiveCoin.mode === 'native' && Number(this.renderBalance('private'))) > 0 ? 'col-lg-3 col-xs-12' : 'hide' }>
<div className="widget widget-shadow">
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
<i className="icon fa-eye-slash font-size-24 vertical-align-bottom margin-right-5"></i>
{ translate('INDEX.Z_BALANCE') }
</div>
<span
className="pull-right padding-top-10 font-size-22"
title={ this.renderBalance('private') }>
{ Config.roundValues ? formatValue(this.renderBalance('private')) : this.renderBalance('private') }
</span>
</div>
</div>
</div>
</div>
<div className={ this.props.ActiveCoin.coin === 'KMD' && Number(this.renderBalance('interest')) > 0 ? 'col-lg-3 col-xs-12' : 'hide' }>
<div className="widget widget-shadow">
<div className="widget-content">
<div className={ (this.props.ActiveCoin.mode === 'native' && Number(this.renderBalance('private'))) > 0 ? 'col-lg-3 col-xs-12' : 'hide' }>
<div className="widget widget-shadow">
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
<i className="icon fa-money font-size-24 vertical-align-bottom margin-right-5"></i>
{ translate('INDEX.INTEREST_EARNED') }
<i className="icon fa-eye-slash font-size-24 vertical-align-bottom margin-right-5"></i>
{ translate('INDEX.Z_BALANCE') }
</div>
<span
className="pull-right padding-top-10 font-size-22"
title={ this.renderBalance('interest') }>
{ Config.roundValues ? formatValue(this.renderBalance('interest')) : this.renderBalance('interest') }
title={ this.renderBalance('private') }>
{ Config.roundValues ? formatValue(this.renderBalance('private')) : this.renderBalance('private') }
</span>
</div>
</div>
</div>
</div>
</div>
<div className={ this.props.ActiveCoin.coin === 'CHIPS' || (this.props.ActiveCoin.coin !== 'KMD' && this.props.ActiveCoin.mode === 'spv') || Number(this.renderBalance('total')) === 0 || this.renderBalance('total') === this.renderBalance('transparent') ? 'hide' : 'col-lg-3 col-xs-12' }>
<div className="widget widget-shadow">
<div className="widget-content">
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
<i className="icon fa-bullseye font-size-24 vertical-align-bottom margin-right-5"></i>
{ translate('INDEX.TOTAL_BALANCE') }
<div className={ this.props.ActiveCoin.coin === 'KMD' && Number(this.renderBalance('interest')) > 0 ? 'col-lg-3 col-xs-12' : 'hide' }>
<div className="widget widget-shadow">
<div className="widget-content">
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
<i className="icon fa-money font-size-24 vertical-align-bottom margin-right-5"></i>
{ translate('INDEX.INTEREST_EARNED') }
</div>
<span
className="pull-right padding-top-10 font-size-22"
title={ this.renderBalance('interest') }>
{ Config.roundValues ? formatValue(this.renderBalance('interest')) : this.renderBalance('interest') }
</span>
</div>
</div>
</div>
</div>
</div>
<div className={ this.props.ActiveCoin.coin === 'CHIPS' || (this.props.ActiveCoin.coin !== 'KMD' && this.props.ActiveCoin.mode === 'spv') || Number(this.renderBalance('total')) === 0 || this.renderBalance('total') === this.renderBalance('transparent') ? 'hide' : 'col-lg-3 col-xs-12' }>
<div className="widget widget-shadow">
<div className="widget-content">
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
<i className="icon fa-bullseye font-size-24 vertical-align-bottom margin-right-5"></i>
{ translate('INDEX.TOTAL_BALANCE') }
</div>
<span
className="pull-right padding-top-10 font-size-22"
title={ this.renderBalance('total') }>
{ Config.roundValues ? formatValue(this.renderBalance('total')) : this.renderBalance('total') }
</span>
</div>
<span
className="pull-right padding-top-10 font-size-22"
title={ this.renderBalance('total') }>
{ Config.roundValues ? formatValue(this.renderBalance('total')) : this.renderBalance('total') }
</span>
</div>
</div>
</div>
</div>
</div>
</div>
}
</div>
);
};

22
react/src/components/dashboard/walletsData/walletsData.js

@ -211,6 +211,8 @@ class WalletsData extends React.Component {
if (this.props.ActiveCoin.txhistory &&
this.props.ActiveCoin.txhistory !== 'loading' &&
this.props.ActiveCoin.txhistory !== 'no data' &&
this.props.ActiveCoin.txhistory !== 'connection error or incomplete data' &&
this.props.ActiveCoin.txhistory !== 'cant get current height' &&
this.props.ActiveCoin.txhistory.length) {
_stateChange = Object.assign({}, _stateChange, {
itemsList: this.props.ActiveCoin.txhistory,
@ -230,6 +232,11 @@ class WalletsData extends React.Component {
_stateChange = Object.assign({}, _stateChange, {
itemsList: 'loading',
});
} else if ((this.props.ActiveCoin.txhistory && this.props.ActiveCoin.txhistory === 'connection error or incomplete data') ||
(this.props.ActiveCoin.txhistory && this.props.ActiveCoin.txhistory === 'cant get current height')) {
_stateChange = Object.assign({}, _stateChange, {
itemsList: 'connection error',
});
}
this.setState(Object.assign({}, _stateChange));
@ -270,6 +277,17 @@ class WalletsData extends React.Component {
<td colSpan="7" className="table-cell-offset-16">{ translate('INDEX.NO_DATA') }</td>
</tr>
);
} else if (this.state.itemsList === 'connection error') {
return (
<tr className="hover--none">
<td colSpan="7" className="table-cell-offset-16 color-warning">
Connection error!
<span className={ this.props.Dashboard.electrumCoins[this.props.ActiveCoin.coin].serverList !== 'none' ? '' : 'hide' }>
<br/>Try to connect to another SPV server.
</span>
</td>
</tr>
);
} else if (this.state.itemsList && this.state.itemsList.length) {
return TxHistoryListRender.call(this);
}
@ -448,9 +466,7 @@ const mapStateToProps = (state) => {
showTransactionInfo: state.ActiveCoin.showTransactionInfo,
progress: state.ActiveCoin.progress,
},
Main: {
coins: state.Main.coins,
},
Main: state.Main,
Dashboard: state.Dashboard,
};
};

2
react/src/components/dashboard/walletsData/walletsData.render.js

@ -211,7 +211,7 @@ export const WalletsDataRender = function() {
</header>
<div className="panel-body">
<div className="row padding-bottom-30 padding-top-10">
{ (this.props.ActiveCoin.txhistory !== 'loading' && this.props.ActiveCoin.txhistory !== 'no data') &&
{ (this.props.ActiveCoin.txhistory !== 'loading' && this.props.ActiveCoin.txhistory !== 'no data' && this.props.ActiveCoin.txhistory !== 'connection error') &&
<div className="col-sm-4 search-box">
<input
className="form-control"

4
react/src/components/overrides.scss

@ -453,4 +453,8 @@ select{
color: #f2a654;
font-size: 18px;
}
}
.color-warning {
color: #FF6600;
}
Loading…
Cancel
Save