From 7f0ac129451f56290ecd9c39436e2241efc5654a Mon Sep 17 00:00:00 2001 From: mDuo13 Date: Tue, 26 Sep 2017 18:37:08 -0700 Subject: [PATCH] EscrowCancel tutorial: skeleton (waiting for expiration) EscrowCancel updates for corrected escrow EscrowCancel tutorial, finished draft --- .../account_objects-request-expiration.json | 7 + .../account_objects-response-expiration.json | 26 ++++ .../websocket/ledger-request-expiration.json | 5 + .../websocket/ledger-response-expiration.json | 19 +++ .../submit-request-escrowcancel.json | 11 ++ .../submit-response-escrowcancel.json | 23 ++++ .../websocket/tx-request-escrowcancel.json | 5 + .../websocket/tx-response-escrowcancel.json | 101 ++++++++++++++ content/tutorial-escrow.md | 128 ++++++++++++++++++ 9 files changed, 325 insertions(+) create mode 100644 content/code_samples/escrow/websocket/account_objects-request-expiration.json create mode 100644 content/code_samples/escrow/websocket/account_objects-response-expiration.json create mode 100644 content/code_samples/escrow/websocket/ledger-request-expiration.json create mode 100644 content/code_samples/escrow/websocket/ledger-response-expiration.json create mode 100644 content/code_samples/escrow/websocket/submit-request-escrowcancel.json create mode 100644 content/code_samples/escrow/websocket/submit-response-escrowcancel.json create mode 100644 content/code_samples/escrow/websocket/tx-request-escrowcancel.json create mode 100644 content/code_samples/escrow/websocket/tx-response-escrowcancel.json diff --git a/content/code_samples/escrow/websocket/account_objects-request-expiration.json b/content/code_samples/escrow/websocket/account_objects-request-expiration.json new file mode 100644 index 0000000000..cc1ed6a617 --- /dev/null +++ b/content/code_samples/escrow/websocket/account_objects-request-expiration.json @@ -0,0 +1,7 @@ +{ + "id": 2, + "command": "account_objects", + "account": "r3wN3v2vTUkr5qd6daqDc2xE4LSysdVjkT", + "ledger": "validated", + "type": "escrow" +} diff --git a/content/code_samples/escrow/websocket/account_objects-response-expiration.json b/content/code_samples/escrow/websocket/account_objects-response-expiration.json new file mode 100644 index 0000000000..ea01415a17 --- /dev/null +++ b/content/code_samples/escrow/websocket/account_objects-response-expiration.json @@ -0,0 +1,26 @@ +{ + "id": 2, + "status": "success", + "type": "response", + "result": { + "account": "r3wN3v2vTUkr5qd6daqDc2xE4LSysdVjkT", + "account_objects": [ + { + "Account": "r3wN3v2vTUkr5qd6daqDc2xE4LSysdVjkT", + "Amount": "10000", + "CancelAfter": 559913895, + "Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "FinishAfter": 559892324, + "Flags": 0, + "LedgerEntryType": "Escrow", + "OwnerNode": "0000000000000000", + "PreviousTxnID": "4756C22BBB7FC23D9081FDB180806939D6FEBC967BE0EC2DB95B166AF9C086E9", + "PreviousTxnLgrSeq": 2764813, + "index": "7243A9750FA4BE3E63F75F6DACFD79AD6B6C76947F6BDC46CD0F52DBEEF64C89" + } + ], + "ledger_hash": "82F24FFA72AED16F467BBE79D387E92FDA39F29038B26E79464CDEDFB506E366", + "ledger_index": 2764826, + "validated": true + } +} diff --git a/content/code_samples/escrow/websocket/ledger-request-expiration.json b/content/code_samples/escrow/websocket/ledger-request-expiration.json new file mode 100644 index 0000000000..fe3c8e9f55 --- /dev/null +++ b/content/code_samples/escrow/websocket/ledger-request-expiration.json @@ -0,0 +1,5 @@ +{ + "id": 4, + "command": "ledger", + "ledger_index": "validated" +} diff --git a/content/code_samples/escrow/websocket/ledger-response-expiration.json b/content/code_samples/escrow/websocket/ledger-response-expiration.json new file mode 100644 index 0000000000..07f4be2a13 --- /dev/null +++ b/content/code_samples/escrow/websocket/ledger-response-expiration.json @@ -0,0 +1,19 @@ +{ + "id": 1, + "status": "success", + "type": "response", + "result": { + "ledger": { + ... (trimmed) ... + + "close_time": 560302643, + "close_time_human": "2017-Oct-02 23:37:23", + "close_time_resolution": 10, + + ... (trimmed) ... + }, + "ledger_hash": "668F0647A6F3CC277496245DBBE9BD2E3B8E70E7AA824E97EF3237FE7E1EE3F2", + "ledger_index": 2906341, + "validated": true + } +} diff --git a/content/code_samples/escrow/websocket/submit-request-escrowcancel.json b/content/code_samples/escrow/websocket/submit-request-escrowcancel.json new file mode 100644 index 0000000000..47dd33a56d --- /dev/null +++ b/content/code_samples/escrow/websocket/submit-request-escrowcancel.json @@ -0,0 +1,11 @@ +{ + "id": 5, + "command": "submit", + "secret": "s████████████████████████████", + "tx_json": { + "Account": "rhgdnc82FwHFUKXp9ZcpgwXWRAxKf5Buqp", + "TransactionType": "EscrowCancel", + "Owner": "r3wN3v2vTUkr5qd6daqDc2xE4LSysdVjkT", + "OfferSequence": 1 + } +} diff --git a/content/code_samples/escrow/websocket/submit-response-escrowcancel.json b/content/code_samples/escrow/websocket/submit-response-escrowcancel.json new file mode 100644 index 0000000000..9e7a7c0fe3 --- /dev/null +++ b/content/code_samples/escrow/websocket/submit-response-escrowcancel.json @@ -0,0 +1,23 @@ +{ + "id": 5, + "status": "success", + "type": "response", + "result": { + "engine_result": "tesSUCCESS", + "engine_result_code": 0, + "engine_result_message": "The transaction was applied. Only final in a validated ledger.", + "tx_blob": "1200042280000000240000000320190000000168400000000000000A7321027FB1CF34395F18901CD294F77752EEE25277C6E87A224FC7388AA7EF872DB43D74473045022100AC45749FC4291F7811B2D8AC01CA04FEE38910CB7216FB0C5C0AEBC9C0A95F4302203F213C71C00136A0ADC670EFE350874BCB2E559AC02059CEEDFB846685948F2B81142866B7B47574C8A70D5E71FFB95FFDB18951427B82144E87970CD3EA984CF48B1AA6AB6C77DC4AB059FC", + "tx_json": { + "Account": "rhgdnc82FwHFUKXp9ZcpgwXWRAxKf5Buqp", + "Fee": "10", + "Flags": 2147483648, + "OfferSequence": 1, + "Owner": "r3wN3v2vTUkr5qd6daqDc2xE4LSysdVjkT", + "Sequence": 3, + "SigningPubKey": "027FB1CF34395F18901CD294F77752EEE25277C6E87A224FC7388AA7EF872DB43D", + "TransactionType": "EscrowCancel", + "TxnSignature": "3045022100AC45749FC4291F7811B2D8AC01CA04FEE38910CB7216FB0C5C0AEBC9C0A95F4302203F213C71C00136A0ADC670EFE350874BCB2E559AC02059CEEDFB846685948F2B", + "hash": "65F36C5514153D94F0ADE5CE747061A5E70B73B56B4C66DA5040D99CAF252831" + } + } +} diff --git a/content/code_samples/escrow/websocket/tx-request-escrowcancel.json b/content/code_samples/escrow/websocket/tx-request-escrowcancel.json new file mode 100644 index 0000000000..25e1cdcdf2 --- /dev/null +++ b/content/code_samples/escrow/websocket/tx-request-escrowcancel.json @@ -0,0 +1,5 @@ +{ + "id": 6, + "command": "tx", + "transaction": "65F36C5514153D94F0ADE5CE747061A5E70B73B56B4C66DA5040D99CAF252831" +} diff --git a/content/code_samples/escrow/websocket/tx-response-escrowcancel.json b/content/code_samples/escrow/websocket/tx-response-escrowcancel.json new file mode 100644 index 0000000000..084c5ef710 --- /dev/null +++ b/content/code_samples/escrow/websocket/tx-response-escrowcancel.json @@ -0,0 +1,101 @@ +{ + "id": 6, + "status": "success", + "type": "response", + "result": { + "Account": "rhgdnc82FwHFUKXp9ZcpgwXWRAxKf5Buqp", + "Fee": "10", + "Flags": 2147483648, + "OfferSequence": 1, + "Owner": "r3wN3v2vTUkr5qd6daqDc2xE4LSysdVjkT", + "Sequence": 3, + "SigningPubKey": "027FB1CF34395F18901CD294F77752EEE25277C6E87A224FC7388AA7EF872DB43D", + "TransactionType": "EscrowCancel", + "TxnSignature": "3045022100AC45749FC4291F7811B2D8AC01CA04FEE38910CB7216FB0C5C0AEBC9C0A95F4302203F213C71C00136A0ADC670EFE350874BCB2E559AC02059CEEDFB846685948F2B", + "date": 560302841, + "hash": "65F36C5514153D94F0ADE5CE747061A5E70B73B56B4C66DA5040D99CAF252831", + "inLedger": 2906406, + "ledger_index": 2906406, + "meta": { + "AffectedNodes": [ + { + "ModifiedNode": { + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8", + "PreviousTxnID": "4756C22BBB7FC23D9081FDB180806939D6FEBC967BE0EC2DB95B166AF9C086E9", + "PreviousTxnLgrSeq": 2764813 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "rhgdnc82FwHFUKXp9ZcpgwXWRAxKf5Buqp", + "Balance": "9999999970", + "Flags": 0, + "OwnerCount": 0, + "Sequence": 4 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "3430FA3A160FA8F9842FA4A8B5549ECDCB3783E585D0F9796A1736DEAE35F6FE", + "PreviousFields": { + "Balance": "9999999980", + "Sequence": 3 + }, + "PreviousTxnID": "DA6F5CA8CE13A03B8BC58515E085F2FEF90B3C08230B5AEC8DE4FAF39F79010B", + "PreviousTxnLgrSeq": 2906391 + } + }, + { + "DeletedNode": { + "FinalFields": { + "Account": "r3wN3v2vTUkr5qd6daqDc2xE4LSysdVjkT", + "Amount": "10000", + "CancelAfter": 559913895, + "Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "FinishAfter": 559892324, + "Flags": 0, + "OwnerNode": "0000000000000000", + "PreviousTxnID": "4756C22BBB7FC23D9081FDB180806939D6FEBC967BE0EC2DB95B166AF9C086E9", + "PreviousTxnLgrSeq": 2764813 + }, + "LedgerEntryType": "Escrow", + "LedgerIndex": "7243A9750FA4BE3E63F75F6DACFD79AD6B6C76947F6BDC46CD0F52DBEEF64C89" + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Flags": 0, + "Owner": "r3wN3v2vTUkr5qd6daqDc2xE4LSysdVjkT", + "RootIndex": "DACDBEBD31D14EAC4207A45DB88734AD14D26D908507F41D2FC623BDD91C582F" + }, + "LedgerEntryType": "DirectoryNode", + "LedgerIndex": "DACDBEBD31D14EAC4207A45DB88734AD14D26D908507F41D2FC623BDD91C582F" + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "r3wN3v2vTUkr5qd6daqDc2xE4LSysdVjkT", + "Balance": "9999999990", + "Flags": 0, + "OwnerCount": 0, + "Sequence": 2 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "F5F1834B80A8B5DA878270AB4DE4EA444281181349375F1D21E46D5F3F0ABAC8", + "PreviousFields": { + "Balance": "9999989990", + "OwnerCount": 1 + }, + "PreviousTxnID": "4756C22BBB7FC23D9081FDB180806939D6FEBC967BE0EC2DB95B166AF9C086E9", + "PreviousTxnLgrSeq": 2764813 + } + } + ], + "TransactionIndex": 2, + "TransactionResult": "tesSUCCESS" + }, + "validated": true + } +} diff --git a/content/tutorial-escrow.md b/content/tutorial-escrow.md index 3c81e4a973..41101bda82 100644 --- a/content/tutorial-escrow.md +++ b/content/tutorial-escrow.md @@ -4,6 +4,7 @@ The XRP Ledger supports held payments, or _escrows_, that can be executed only a - [Send a time-held escrow](#send-a-time-held-escrow) - [Send a conditionally-held escrow](#send-a-conditionally-held-escrow) +- [Cancel an expired escrow](#cancel-an-expired-escrow) - [Look up escrows by sender](#look-up-escrows-by-sender) @@ -145,6 +146,8 @@ Response: [Sign and submit](reference-transaction-format.html#signing-and-submitting-transactions) an [EscrowFinish transaction][] to execute the release of the funds after the `FinishAfter` time has passed. Set the `Owner` field of the transaction to the `Account` address from the EscrowCreate transaction, and the `OfferSequence` to the `Sequence` number from the EscrowCreate transaction. For an escrow held only by time, omit the `Condition` and `Fulfillment` fields. +If the escrow has expired, you can only [cancel the escrow](#cancel-an-expired-escrow) instead. + **Tip:** The EscrowFinish transaction is necessary because the XRP Ledger's state can only be modified by transactions. The sender of this transaction may be the recipient of the escrow, the original sender of the escrow, or any other XRP Ledger address. {% include 'snippets/secret-key-warning.md' %} @@ -334,6 +337,8 @@ Response: [Sign and submit](reference-transaction-format.html#signing-and-submitting-transactions) an [EscrowFinish transaction][] to execute the release of the funds after the `FinishAfter` time has passed. Set the `Owner` field of the transaction to the `Account` address from the EscrowCreate transaction, and the `OfferSequence` to the `Sequence` number from the EscrowCreate transaction. Set the `Condition` and `Fulfillment` fields to the condition and fulfillment values, in hexadecimal, that you generated in step 1. Set the `Fee` ([transaction cost](concept-transaction-cost.html)) value based on the size of the fulfillment in bytes: a conditional EscrowFinish requires at least 330 drops of XRP plus 10 drops per 16 bytes in the size of the fulfillment. +If the escrow has expired, you can only [cancel the escrow](#cancel-an-expired-escrow) instead. + **Note:** If you included a `FinishAfter` field in the EscrowCreate transaction, you cannot execute it before that time has passed, even if you provide the correct fulfillment for the Escrow's condition. The EscrowFinish transaction fails with the [result code](reference-transaction-format.html#transaction-results) `tecNO_PERMISSION` if the previously-closed ledger's close time is before the `FinishAfter` time. {% include 'snippets/secret-key-warning.md' %} @@ -382,6 +387,129 @@ Response: {% include 'code_samples/escrow/websocket/tx-response-escrowfinish-condition.json' %} ``` +## Cancel an expired escrow + +### 1. Confirm the expired escrow + +An escrow in the XRP Ledger is expired when its `CancelAfter` time is lower than the `close_time` of a validated ledger version. (If the escrow does not have a `CancelAfter` time, it never expires.) You can look up the close time of the latest validated ledger with the [`ledger` command](reference-rippled.html#ledger): + +Request: + + + +_Websocket_ + +```json +{% include 'code_samples/escrow/websocket/ledger-request-expiration.json' %} +``` + + + +Response: + + + +_Websocket_ + +```json +{% include 'code_samples/escrow/websocket/ledger-response-expiration.json' %} +``` + + + + +You can look up the escrow and compare to the `CancelAfter` time using the [`account_objects` command](reference-rippled.html#account-objects): + +Request: + + + +_Websocket_ + +```json +{% include 'code_samples/escrow/websocket/account_objects-request-expiration.json' %} +``` + + + +Response: + + + +_Websocket_ + +```json +{% include 'code_samples/escrow/websocket/account_objects-response-expiration.json' %} +``` + + + +### 2. Submit EscrowCancel transaction + +***Anyone*** can cancel an expired escrow in the XRP Ledger by [signing and submitting](reference-transaction-format.html#signing-and-submitting-transactions) an [EscrowCancel transaction][]. Set the `Owner` field of the transaction to the `Account` of the `EscrowCreate` transaction that created this escrow. Set the `OfferSequence` field to the `Sequence` of the `EscrowCreate` transaction. + +{% include 'snippets/secret-key-warning.md' %} + +Request: + + + +_Websocket_ + +```json +{% include 'code_samples/escrow/websocket/submit-request-escrowcancel.json' %} +``` + + + +Response: + + + +_Websocket_ + +```json +{% include 'code_samples/escrow/websocket/submit-response-escrowcancel.json' %} +``` + + + +Take note of the transaction's identifying `hash` value so you can check its final status when it is included in a validated ledger version. + +### 3. Wait for validation + +{% include 'snippets/wait-for-validation.md' %} + +### 4. Confirm final result + +Use the [`tx` command](reference-rippled.html#tx) with the EscrowCancel transaction's identifying hash to check its final status.Look in the transaction metadata for a `DeletedNode` with `LedgerEntryType` of `Escrow`. Also look for a `ModifiedNode` of type `AccountRoot` for the sender of the escrowed payment. The `FinalFields` of the object should reflect the increase in XRP in the `Balance` field for the returned XRP. + +Request: + + + +_Websocket_ + + +```json +{% include 'code_samples/escrow/websocket/tx-request-escrowcancel.json' %} +``` + + + +Response: + + + +_Websocket_ + +```json +{% include 'code_samples/escrow/websocket/tx-response-escrowcancel.json' %} +``` + + + +In the above example, `r3wN3v2vTUkr5qd6daqDc2xE4LSysdVjkT` is the sender of the escrow, and the increase in `Balance` from 99999**8**9990 drops to 99999**9**9990 drops represents the return of the escrowed 10,000 drops of XRP (0.01 XRP). ## Look up escrows by sender