Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Cancel tx JS #4958

Merged
merged 45 commits into from
Apr 25, 2017
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
49ed3d8
Remove transaction RPC
tomusdrw Mar 17, 2017
a9ae42c
Bumping multihash and libc
tomusdrw Mar 17, 2017
eb8fe28
Updating nanomsg
tomusdrw Mar 17, 2017
3d31031
bump nanomsg
arkpar Mar 17, 2017
eb3e79c
cancel tx
CraigglesO Mar 18, 2017
45d1641
cancel-tx-js
CraigglesO Mar 18, 2017
f871389
cancel-tx-js
CraigglesO Mar 18, 2017
aa47572
cancel-tx-js
CraigglesO Mar 18, 2017
35d959e
cancel-tx-hs
CraigglesO Mar 18, 2017
2235923
cancel-tx-js
CraigglesO Mar 18, 2017
65c6390
cancel-tx-js
CraigglesO Mar 18, 2017
14dd162
cancel-tx-js
CraigglesO Mar 18, 2017
9766508
small fixes
CraigglesO Mar 19, 2017
b57aecd
Merge remote-tracking branch 'origin/master' into cancel-tx-js
CraigglesO Mar 19, 2017
03c19fd
edit & time till submit
CraigglesO Mar 20, 2017
42dd28a
edit & time till submit
CraigglesO Mar 20, 2017
a9662fa
updates
CraigglesO Mar 20, 2017
b7c8c16
updates
CraigglesO Mar 20, 2017
89b4343
udpates
CraigglesO Mar 22, 2017
1aeec64
udpates
CraigglesO Mar 22, 2017
eb8e56d
grumbles
CraigglesO Mar 24, 2017
131b837
step 1
CraigglesO Mar 24, 2017
c56ce69
Merge branch 'master' of github.com:paritytech/parity into cancel-tx-js
CraigglesO Mar 24, 2017
c2ce35c
Wonderful updates
CraigglesO Mar 25, 2017
06c9951
ready
CraigglesO Mar 25, 2017
8e17b08
small refact
CraigglesO Mar 27, 2017
b8a7d62
small refact
CraigglesO Mar 27, 2017
4d9ca26
grumbles 1
CraigglesO Mar 27, 2017
684ab6c
ffx2
CraigglesO Apr 4, 2017
c6195d6
ffx2
CraigglesO Apr 4, 2017
85929ea
good ol' fashioned updates
CraigglesO Apr 4, 2017
35aad6c
latest and greatest
CraigglesO Apr 4, 2017
acf79fe
removeHash
CraigglesO Apr 6, 2017
3c4199b
removeHash
CraigglesO Apr 6, 2017
2c04f54
spec
CraigglesO Apr 6, 2017
2d03df7
fix 1
CraigglesO Apr 10, 2017
c9535bf
fix 1
CraigglesO Apr 10, 2017
8d01b28
fix 2
CraigglesO Apr 10, 2017
666f59f
fix 2
CraigglesO Apr 10, 2017
10eda45
ff
CraigglesO Apr 10, 2017
ca73bc8
ff
CraigglesO Apr 10, 2017
bd05a8c
ff
CraigglesO Apr 10, 2017
0f4f40d
ff
CraigglesO Apr 10, 2017
3bf3972
updates
CraigglesO Apr 21, 2017
fb72ab4
lol
CraigglesO Apr 23, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
# mac stuff
.DS_Store

# npm stuff
npm-debug.log

# gdb files
.gdb_history

Expand Down
1 change: 1 addition & 0 deletions js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@
"blockies": "0.0.2",
"brace": "0.9.0",
"bytes": "2.4.0",
"date-difference": "1.0.0",
"debounce": "1.0.0",
"es6-error": "4.0.0",
"es6-promise": "4.0.5",
Expand Down
5 changes: 5 additions & 0 deletions js/src/api/rpc/parity/parity.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,11 @@ export default class Parity {
.execute('parity_removeReservedPeer', encode);
}

removeTransaction (transactionId) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transactionHash would be more adequate

return this._transport
.execute('parity_removeTransaction', inHex(transactionId));
}

rpcSettings () {
return this._transport
.execute('parity_rpcSettings');
Expand Down
37 changes: 36 additions & 1 deletion js/src/jsonrpc/interfaces/parity.js
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,34 @@ export default {
}
},

removeTransaction: {
section: SECTION_ACCOUNTS,
desc: 'Cancel a pending transaction. If the transaction has already been pushed to the network, there is no guarantee that the transaction can be removed.',
params: [
{
type: Data,
desc: 'transactionId, 32-byte hex',
example: '0x1db2c0cf57505d0f4a3d589414f0a0025ca97421d2cd596a9486bc7e2cd2bf8b'
}
],
returns: {
type: Object,
desc: 'the removed transaction if cancellation was successful, an error if not.',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: it's rather "the removed transaction if found, an error if not" (no guarantees about success state here as well)

example: {
condition: {},
from: '0x00d0f4d320c54b44f9fe852af1215a528c99f1ab',
gas: '0x5208',
gasPrice: '0x2540be400',
hash: '0x9f771b70b3d33eae61064432f7398593d28d7bfa49004bc43004dfbe0777ab0e',
input: '0x',
networkId: 42,
nonce: '0x10',
to: '0x00a3755a680f9b906a4465923ea5ad3c960ddcec',
value: '0xde0b6b3a7640000'
}
}
},

registryAddress: {
section: SECTION_NET,
desc: 'The address for the global registry.',
Expand Down Expand Up @@ -1622,7 +1650,14 @@ export default {
example: {
from: '0xb60e8dd61c5d32be8058bb8eb970870f07233155',
to: '0xd46e8dd67c5d32be8058bb8eb970870f07244567',
value: fromDecimal(2441406250)
gas: fromDecimal(30400),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would just remove the fromDecimal wrappers here, i.e. the response should rather be what we receive via the actual RPC, raw.

gasPrice: fromDecimal(10000000000000),
value: fromDecimal(2441406250),
data: '0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675',
condition: {
block: 354221,
time: new Date()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same with these.

}
}
}
],
Expand Down
38 changes: 21 additions & 17 deletions js/src/ui/MethodDecoding/methodDecoding.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,16 @@ class MethodDecoding extends Component {
);

return (
<FormattedMessage
id='ui.methodDecoding.condition.block'
defaultMessage=', {historic, select, true {Submitted} false {Submission}} at block {blockNumber}'
values={ {
historic,
blockNumber
} }
/>
<div>
<FormattedMessage
id='ui.methodDecoding.condition.block'
defaultMessage='{historic, select, true {Will be submitted} false {To be submitted}} at block {blockNumber}'
values={ {
historic,
blockNumber
} }
/>
</div>
);
}

Expand All @@ -197,14 +199,16 @@ class MethodDecoding extends Component {
);

return (
<FormattedMessage
id='ui.methodDecoding.condition.time'
defaultMessage=', {historic, select, true {Submitted} false {Submission}} at {timestamp}'
values={ {
historic,
timestamp
} }
/>
<div>
<FormattedMessage
id='ui.methodDecoding.condition.time'
defaultMessage='{historic, select, true {Will be submitted} false {To be submitted}} {timestamp}'
values={ {
historic,
timestamp
} }
/>
</div>
);
}

Expand Down Expand Up @@ -493,7 +497,7 @@ class MethodDecoding extends Component {
<div className={ styles.description }>
<FormattedMessage
id='ui.methodDecoding.signature.info'
defaultMessage='{historic, select, true {Executed} false {Will execute}} the {method} function on the contract {address} trsansferring {ethValue}{inputLength, plural, zero {,} other {passing the following {inputLength, plural, one {parameter} other {parameters}}}}'
defaultMessage='{historic, select, true {Executed} false {Will execute}} the {method} function on the contract {address} transferring {ethValue}{inputLength, plural, zero {,} other {passing the following {inputLength, plural, one {parameter} other {parameters}}}}'
values={ {
historic,
method,
Expand Down
158 changes: 157 additions & 1 deletion js/src/ui/TxList/TxRow/txRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import moment from 'moment';
import dateDifference from 'date-difference';
import { FormattedMessage } from 'react-intl';
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router';
Expand All @@ -35,19 +37,29 @@ class TxRow extends Component {
static propTypes = {
accountAddresses: PropTypes.array.isRequired,
address: PropTypes.string.isRequired,
blockNumber: PropTypes.object,
contractAddresses: PropTypes.array.isRequired,
netVersion: PropTypes.string.isRequired,
tx: PropTypes.object.isRequired,

block: PropTypes.object,
className: PropTypes.string,
cancelTransaction: PropTypes.func,
editTransaction: PropTypes.func,
historic: PropTypes.bool
};

static defaultProps = {
historic: true
};

state = {
isCancelOpen: false,
isEditOpen: false,
canceled: false,
editing: false
};

render () {
const { address, className, historic, netVersion, tx } = this.props;

Expand Down Expand Up @@ -137,11 +149,113 @@ class TxRow extends Component {
return (
<td className={ styles.timestamp }>
<div>{ blockNumber && block ? moment(block.timestamp).fromNow() : null }</div>
<div>{ blockNumber ? _blockNumber.toFormat() : 'Pending' }</div>
<div>{ blockNumber ? _blockNumber.toFormat() : this.renderCancelToggle() }</div>
</td>
);
}

renderCancelToggle () {
const { canceled, editing, isCancelOpen, isEditOpen } = this.state;

if (canceled) {
return (
<div className={ styles.pending }>
<FormattedMessage
id='ui.txList.txRow.canceled'
defaultMessage='CANCELED'
/>
</div>
);
}

if (editing) {
return (
<div className={ styles.pending }>
<FormattedMessage
id='ui.txList.txRow.editing'
defaultMessage='EDITING'
Copy link
Contributor

@jacogr jacogr Mar 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It probably would make more sense having the defaultMessage as editing/Editing and using text-transform to make it uppercase. (That way we don't need to edit the text and get translations to update when we change the way we want the display the look)

(Same for SUBMITTING, SCHEDULED, EDIT & CANCEL)

/>
</div>
);
}

if (!isCancelOpen && !isEditOpen) {
const pendingStatus = this.getCondition();

if (pendingStatus === 'submitting...') {
Copy link
Contributor

@jacogr jacogr Mar 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I'm 100% on-board with the submitting... - would rather make the state checking against a defined constant (e.g. const STATUS_SUBMITTING = 'submitting') and not have the ... in there

return (
<div className={ styles.pending }>
<div />
<div>
<FormattedMessage
id='ui.txList.txRow.submitting'
defaultMessage='SUBMITTING'
/>
</div>
</div>
);
}
return (
<div className={ styles.pending }>
<span>
<FormattedMessage
id='ui.txList.txRow.time'
defaultMessage='{ which }'
values={ { which: pendingStatus } }
/>
</span>
<div>
<FormattedMessage
id='ui.txList.txRow.scheduled'
defaultMessage='SCHEDULED'
/>
</div>
<a onClick={ this.setEdit }>
<FormattedMessage
id='ui.txList.txRow.edit'
defaultMessage='EDIT'
/>
</a>
<span>{' | '}</span>
<a onClick={ this.setCancel }>
<FormattedMessage
id='ui.txList.txRow.cancel'
defaultMessage='CANCEL'
/>
</a>
</div>
);
}

return (
<div className={ styles.pending }>
<div />
<div>
<FormattedMessage
id='ui.txList.txRow.verify'
defaultMessage='ARE YOU SURE?'
/>
</div>
<a onClick={ (isCancelOpen) ? this.cancelTx : this.editTx }>
<FormattedMessage
id='ui.txList.txRow.verify.cancelEdit'
defaultMessage='{ which }'
values={ {
which: `${(isCancelOpen) ? 'Cancel' : 'Edit'}`
Copy link
Collaborator

@tomusdrw tomusdrw Mar 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should get a big red/yellow warning for transaction cancellation since it's not reliable as mentioned in RPC docs.

There are two separate cases:

  1. Scheduled transactions and transactions that were not propagated to other peers - such transactions can be safely canceled, it will be removed from our local queue and never propagated to the network so it's fine.
  2. Other transactions - those transactions cannot be simply "canceled" since they are already floating around a network and there is a very high chance that other peers have accepted the transaction and are relaying it further.
    For those transactions we should display a warning (but still allow that) and offer another "cancelation" mechanism decribed here: Force-cancel transaction #4519, so: Increase gas price, remove data, lower gas and submit transaction again.

When editing transaction we should also differentiate those two cases. (1) is safe to edit, but (2) should always increase the gas price when edited (it increases the chance of actually replacing the transaction that was already propagated).

PM me for more details :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(2) should also zero-out the value and, for sanity, replace to with 0x000...000.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be FormattedMessage as well (Should also be translatable)

} }
/>
</a>
<span>{' | '}</span>
<a onClick={ this.nevermind }>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would name this something else, e.g. not nevermind (revertEdit or cancelEdit or ...)

<FormattedMessage
id='ui.txList.txRow.verify.nevermind'
defaultMessage='Nevermind'
/>
</a>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FormattedMessage & inline closures.

);
}

getIsKnownContract (address) {
const { contractAddresses } = this.props;

Expand All @@ -165,6 +279,48 @@ class TxRow extends Component {

return `/addresses/${address}`;
}

getCondition = () => {
const { blockNumber, tx } = this.props;
let { time, block } = tx.condition;

if (time) {
if ((time.getTime() - Date.now()) >= 0) {
return `${dateDifference(new Date(), time, { compact: true })} left`;
} else {
return 'submitting...';
}
} else if (blockNumber) {
block = blockNumber.minus(block);
return (block.toNumber() < 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FormattedMessage here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All string returns pulled from getCondition as seen here are formatted on line 205

? block.abs().toFormat(0) + ' blocks left'
: 'submitting...';
}
}

cancelTx = () => {
const { cancelTransaction, tx } = this.props;

cancelTransaction(this, tx);
}

editTx = () => {
const { editTransaction, tx } = this.props;

editTransaction(this, tx);
}

setCancel = () => {
this.setState({ isCancelOpen: true });
}

setEdit = () => {
this.setState({ isEditOpen: true });
}

nevermind = () => {
this.setState({ isCancelOpen: false, isEditOpen: false });
}
}

function mapStateToProps (initState) {
Expand Down
Loading