Cancel a Check
This tutorial shows how to cancel a Check, which removes the Check object from the ledger without sending money.
You may want to cancel an incoming Check if you do not want it. You might cancel an outgoing Check if you made a mistake when sending it or if circumstances have changed. If a Check expires, it's also necessary to cancel it to remove it from the ledger so the sender gets their owner reserve back.
Prerequisites
To cancel a Check with this tutorial, you need the following:
- You need the ID of a Check object currently in the ledger.
- For example, this tutorial includes examples that cancel a Check with the ID
49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0
, although you must use a different ID to go through these steps yourself.
- For example, this tutorial includes examples that cancel a Check with the ID
- The address and secret key of a funded account to send the CheckCancel transaction. This address must be either the sender or the recipient of the Check, unless the Check is expired.
- A secure way to sign transactions.
- A client library or any HTTP or WebSocket library.
1. Prepare the CheckCancel transaction
Figure out the values of the CheckCancel transaction fields. The following fields are the bare minimum; everything else is either optional or can be auto-filled when signing:
Field | Value | Description |
---|---|---|
TransactionType | String | Use the string CheckCancel when canceling a Check. |
Account | String (Address) | The address of the sender who is canceling the Check. (In other words, your address.) |
CheckID | String | The ID of the Check object in the ledger to cancel. You can get this information by looking up the metadata of the CheckCreate transaction using the tx method or by looking for Checks using the account_objects method. |
Example CheckCancel Preparation
The following examples show how to cancel a Check.
{ "TransactionType": "CheckCancel", "Account": "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", "CheckID": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0", "Fee": "12" }
2. Sign the CheckCancel transaction
The most secure way to sign a transaction is to sign locally with a client library. Alternatively, if you run your own rippled
node you can sign the transaction using the sign method, but this must be done through a trusted and encrypted connection, or through a local (same-machine) connection.
In all cases, note the signed transaction's identifying hash for later.
Example Request
'use strict' const RippleAPI = require('ripple-lib').RippleAPI // Can sign offline if the txJSON has all required fields const api = new RippleAPI() const txJSON = '{"Account":"rBXsgNkPcDN2runsvWmwxk3Lh97zdgo9za","TransactionType":"CheckCancel","CheckID":"2E0AD0740B79BE0AAE5EDD1D5FC79E3C5C221D23C6A7F771D85569B5B91195C2","Flags":2147483648,"LastLedgerSequence":8004884,"Fee":"12","Sequence":7}' // Be careful where you store your real secret. const secret = 's████████████████████████████' const signed = api.sign(txJSON, secret) console.log("tx_blob is:", signed.signedTransaction) console.log("tx hash is:", signed.id)
Example Response
tx_blob is: 12001222800000002400000007201B007A251450182E0AD0740B79BE0AAE5EDD1D5FC79E3C5C221D23C6A7F771D85569B5B91195C268400000000000000C732103B6FCD7FAC4F665FE92415DD6E8450AD90F7D6B3D45A6CFCF2E359045FF4BB4007446304402205D77451B0D7BCDA1FE5B98763C5B3B2837453371FE93C2B86157C44B1867AE36022003800273848BC2F8E1C6EC7EE4B0CB2425A888AE80E586886C306C796B25678B8114735FF88E5269C80CD7F7AF10530DAB840BBF6FDF tx hash is: 54A7A917BE9AC13962251BCF1D09803C7BBE75882B8BFC987B5933A566A48215
3. Submit the signed CheckCancel transaction
Take the signed transaction blob from the previous step and submit it to a rippled
server. You can do this safely even if you do not run the rippled
server. The response contains a provisional result, which should be tesSUCCESS
, but this result is usually not final. A provisional response of terQUEUED
is also OK, since queued transactions are generally included in the next open ledger version (usually about 10 seconds after submission).
Tip: If the preliminary result is tefMAX_LEDGER
, the transaction has failed permanently because its LastLedgerSequence
parameter is lower than the current ledger. This happens when you take longer than the expected number of ledger versions between preparing and submitting the transaction. If this occurs, start over from step 1 with a higher LastLedgerSequence
value.
Example Request
'use strict' const RippleAPI = require('ripple-lib').RippleAPI // This example connects to a public Test Net server const api = new RippleAPI({server: 'wss://s.altnet.rippletest.net:51233'}) api.connect().then(() => { console.log('Connected') const tx_blob = "12001222800000002400000007201B007A251450182E0AD0740B79BE0AAE5EDD1D5FC79E3C5C221D23C6A7F771D85569B5B91195C268400000000000000C732103B6FCD7FAC4F665FE92415DD6E8450AD90F7D6B3D45A6CFCF2E359045FF4BB4007446304402205D77451B0D7BCDA1FE5B98763C5B3B2837453371FE93C2B86157C44B1867AE36022003800273848BC2F8E1C6EC7EE4B0CB2425A888AE80E586886C306C796B25678B8114735FF88E5269C80CD7F7AF10530DAB840BBF6FDF" return api.submit(tx_blob) }).then(response => { console.log("Preliminary transaction result:", response.resultCode) // Disconnect and return }).then(() => { api.disconnect().then(() => { console.log('Disconnected') process.exit() }) }).catch(console.error)
Example Response
Connected
Preliminary transaction result: tesSUCCESS
Disconnected
4. Wait for validation
On a live network (including Mainnet, Testnet, or Devnet), you can wait 4-7 seconds for the ledger to close automatically.
If you're running rippled
in stand-alone mode, use the [ledger_accept method][] to manually close the ledger.
5. Confirm final result
Use the tx method with the CheckCancel transaction's identifying hash to check its status. Look for a "TransactionResult": "tesSUCCESS"
field in the transaction's metadata, indicating that the transaction succeeded, and the field "validated": true
in the result, indicating that this result is final.
Look for a DeletedNode
object in the transaction metadata with "LedgerEntryType": "Check"
to indicate that the transaction removed a Check ledger object. The LedgerIndex
of this object should match the ID of the Check.
Example Request
'use strict' const RippleAPI = require('ripple-lib').RippleAPI // This example connects to a public Test Net server const api = new RippleAPI({server: 'wss://s.altnet.rippletest.net:51233'}) api.connect().then(() => { console.log('Connected') const tx_hash = "54A7A917BE9AC13962251BCF1D09803C7BBE75882B8BFC987B5933A566A48215" return api.getTransaction(tx_hash) }).then(response => { console.log("Final transaction result:", response) // Disconnect and return }).then(() => { api.disconnect().then(() => { console.log('Disconnected') process.exit() }) }).catch(console.error)
Example Response
Connected Final transaction result: { type: 'checkCancel', address: 'rBXsgNkPcDN2runsvWmwxk3Lh97zdgo9za', sequence: 7, id: '54A7A917BE9AC13962251BCF1D09803C7BBE75882B8BFC987B5933A566A48215', specification: { checkID: '2E0AD0740B79BE0AAE5EDD1D5FC79E3C5C221D23C6A7F771D85569B5B91195C2' }, outcome: { result: 'tesSUCCESS', timestamp: '2018-04-02T23:42:22.000Z', fee: '0.000012', balanceChanges: { rBXsgNkPcDN2runsvWmwxk3Lh97zdgo9za: [Array] }, orderbookChanges: {}, ledgerVersion: 8004870, indexInLedger: 3 } } Disconnected