# Send a Time-Held Escrow The [EscrowCreate transaction](/docs/references/protocol/transactions/types/escrowcreate) type can create an escrow whose only condition for release is that a specific time has passed. To do this, use the `FinishAfter` field and omit the `Condition` field. ## 1. Calculate release time You must specify the time as whole **[seconds since the Ripple Epoch](/docs/references/protocol/data-types/basic-data-types#specifying-time)**, which is 946684800 seconds after the UNIX epoch. For example, to release funds at midnight UTC on November 13, 2017: JavaScript ```js // JavaScript Date() is natively expressed in milliseconds; convert to seconds const release_date_unix = Math.floor( new Date("2017-11-13T00:00:00Z") / 1000 ); const release_date_ripple = release_date_unix - 946684800; console.log(release_date_ripple); // 563846400 ``` Python 3 ```python import datetime release_date_utc = datetime.datetime(2017,11,13,0,0,0,tzinfo=datetime.timezone.utc) release_date_ripple = int(release_date_utc.timestamp()) - 946684800 print(release_date_ripple) # 563846400 ``` If you use a UNIX time in the `FinishAfter` field without converting to the equivalent Ripple time first, that sets the unlock time to an extra **30 years** in the future! ## 2. Submit EscrowCreate transaction [Sign and submit](/docs/concepts/transactions#signing-and-submitting-transactions) an [EscrowCreate transaction](/docs/references/protocol/transactions/types/escrowcreate). Set the `FinishAfter` field of the transaction to the time when the held payment should be released. Omit the `Condition` field to make time the only condition for releasing the held payment. Set the `Destination` to the recipient, which may be the same address as the sender. Set the `Amount` to the total amount of [XRP, in drops](/docs/references/protocol/data-types/basic-data-types#specifying-currency-amounts), to escrow. Caution Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network. Websocket Request: { "id": 2, "command": "submit", "secret": "s████████████████████████████", "tx_json": { "Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "TransactionType": "EscrowCreate", "Amount": "10000", "Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "FinishAfter": 557020800 } } Response: { "id": 2, "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": "1200012280000000240000000120252133768061400000000000271068400000000000000A732103C3555B7339FFDDB43495A8371A3A87B4C66B67D49D06CB9BA1FDBFEEB57B6E437446304402203C9AA4C21E1A1A7427D41583283E7A513DDBDD967B246CADD3B2705D858A7A8E02201BEA7B923B18910EEB9F306F6DE3B3F53549BBFAD46335B62B4C34A6DCB4A47681143EEB46C355B04EE8D08E8EED00F422895C79EA6A83144B4E9C06F24296074F7BC48F92A97916C6DC5EA9", "tx_json": { "Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "Amount": "10000", "Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "Fee": "10", "FinishAfter": 557020800, "Flags": 2147483648, "Sequence": 1, "SigningPubKey": "03C3555B7339FFDDB43495A8371A3A87B4C66B67D49D06CB9BA1FDBFEEB57B6E43", "TransactionType": "EscrowCreate", "TxnSignature": "304402203C9AA4C21E1A1A7427D41583283E7A513DDBDD967B246CADD3B2705D858A7A8E02201BEA7B923B18910EEB9F306F6DE3B3F53549BBFAD46335B62B4C34A6DCB4A476", "hash": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263" } } } Javascript // Prepare EscrowCreate transaction ------------------------------------ const escrowCreateTransaction = { "TransactionType": "EscrowCreate", "Account": wallet.address, "Destination": wallet.address, "Amount": "6000000", //drops XRP "DestinationTag": 2023, "Condition": conditionHex, // Omit this for time-held escrows "Fee": "12", "FinishAfter": xrpl.isoTimeToRippleTime(finishAfter.toISOString()), }; xrpl.validate(escrowCreateTransaction); // Sign and submit the transaction ---------------------------------------- console.log('Signing and submitting the transaction:', JSON.stringify(escrowCreateTransaction, null, "\t"), "\n" ); const response = await client.submitAndWait(escrowCreateTransaction, { wallet }); console.log(`Sequence number: ${response.result.tx_json.Sequence}`); console.log(`Finished submitting! ${JSON.stringify(response.result, null, "\t")}`); Python # Build escrow create transaction create_txn = EscrowCreate( account=sender_wallet.address, amount=xrp_to_drops(amount_to_escrow), destination=receiver_addr, finish_after=claim_date, cancel_after=expiry_date, condition=condition # Omit this for time-held escrows ) # Autofill, sign, then submit transaction and wait for result stxn_response = submit_and_wait(create_txn, client, sender_wallet) # Return result of transaction stxn_result = stxn_response.result # Parse result and print out the neccesary info print(stxn_result["tx_json"]["Account"]) print(stxn_result["tx_json"]["Sequence"]) print(stxn_result["meta"]["TransactionResult"]) print(stxn_result["hash"]) 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 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](/docs/references/http-websocket-apis/admin-api-methods/server-control-methods/ledger_accept) to manually close the ledger. ## 4. Confirm that the escrow was created Use the [tx method](/docs/references/http-websocket-apis/public-api-methods/transaction-methods/tx) with the transaction's identifying hash to check its final status. Look for a `CreatedNode` in the transaction metadata to indicate that it created an [Escrow ledger object](/docs/concepts/payment-types/escrow). Request: Websocket { "id": 3, "command": "tx", "transaction": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263" } Response: Websocket { "id": 3, "status": "success", "type": "response", "result": { "Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "Amount": "10000", "Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "Fee": "10", "FinishAfter": 557020800, "Flags": 2147483648, "Sequence": 1, "SigningPubKey": "03C3555B7339FFDDB43495A8371A3A87B4C66B67D49D06CB9BA1FDBFEEB57B6E43", "TransactionType": "EscrowCreate", "TxnSignature": "304402203C9AA4C21E1A1A7427D41583283E7A513DDBDD967B246CADD3B2705D858A7A8E02201BEA7B923B18910EEB9F306F6DE3B3F53549BBFAD46335B62B4C34A6DCB4A476", "date": 557014081, "hash": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263", "inLedger": 1828796, "ledger_index": 1828796, "meta": { "AffectedNodes": [ { "ModifiedNode": { "LedgerEntryType": "AccountRoot", "LedgerIndex": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8", "PreviousTxnID": "613B28E0890FC975F2CBA3D700F75116F623B1E3FE48CB7CB2EB216EAD6F097D", "PreviousTxnLgrSeq": 1799920 } }, { "CreatedNode": { "LedgerEntryType": "Escrow", "LedgerIndex": "2B9845CB9DF686B9615BF04F3EC66095A334D985E03E71B893B90FCF6D4DC9E6", "NewFields": { "Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "Amount": "10000", "Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "FinishAfter": 557020800 } } }, { "ModifiedNode": { "FinalFields": { "Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "Balance": "9999989990", "Flags": 0, "OwnerCount": 1, "Sequence": 2 }, "LedgerEntryType": "AccountRoot", "LedgerIndex": "AE5AB6584A76C37C7382B6880609FC7792D90CDA36FF362AF412EB914C1715D3", "PreviousFields": { "Balance": "10000000000", "OwnerCount": 0, "Sequence": 1 }, "PreviousTxnID": "F181D45FD094A7417926F791D9DF958B84CE4B7B3D92CC9DDCACB1D5EC59AAAA", "PreviousTxnLgrSeq": 1828732 } }, { "CreatedNode": { "LedgerEntryType": "DirectoryNode", "LedgerIndex": "D623EBEEEE701D4323D0ADA5320AF35EA8CC6520EBBEF69343354CD593DABC88", "NewFields": { "Owner": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "RootIndex": "D623EBEEEE701D4323D0ADA5320AF35EA8CC6520EBBEF69343354CD593DABC88" } } } ], "TransactionIndex": 3, "TransactionResult": "tesSUCCESS" }, "validated": true } } ## 5. Wait for the release time Held payments with a `FinishAfter` time cannot be finished until a ledger has already closed with a [`close_time` header field](/docs/references/protocol/ledger-data/ledger-header) that is later than the Escrow node's `FinishAfter` time. You can check the close time of the most recently-validated ledger with the [ledger method](/docs/references/http-websocket-apis/public-api-methods/ledger-methods/ledger): Request: Websocket { "id": 4, "command": "ledger", "ledger_index": "validated" } Response: Websocket { "id": 4, "status": "success", "type": "response", "result": { "ledger": { "accepted": true, "account_hash": "3B5A8FF5334F94F4D3D09F236F9D1B4C028FCAE30948ACC986D461DDEE1D886B", "close_flags": 0, "close_time": 557256670, "close_time_human": "2017-Aug-28 17:31:10", "close_time_resolution": 10, "closed": true, "hash": "A999223A80174A7CB39D766B625C9E476F24AD2F15860A712CD029EE5ED1C320", "ledger_hash": "A999223A80174A7CB39D766B625C9E476F24AD2F15860A712CD029EE5ED1C320", "ledger_index": "1908253", "parent_close_time": 557256663, "parent_hash": "6A70C5336ACFDA05760D827776079F7A544D2361CFD5B21BD55A92AA20477A61", "seqNum": "1908253", "totalCoins": "99997280690562728", "total_coins": "99997280690562728", "transaction_hash": "49A51DFB1CAB2F134D93D5D1C5FF55A15B12DA36DAF9F5862B17C47EE966647D" }, "ledger_hash": "A999223A80174A7CB39D766B625C9E476F24AD2F15860A712CD029EE5ED1C320", "ledger_index": 1908253, "validated": true } } ## 6. Submit EscrowFinish transaction [Sign and submit](/docs/concepts/transactions#signing-and-submitting-transactions) an [EscrowFinish transaction](/docs/references/protocol/transactions/types/escrowfinish) 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. 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. If the escrow has expired, you can only [cancel the escrow](/docs/tutorials/how-tos/use-specialized-payment-types/use-escrows/cancel-an-expired-escrow) instead. Caution Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network. Websocket Request: { "id": 5, "command": "submit", "secret": "s████████████████████████████", "tx_json": { "Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "TransactionType": "EscrowFinish", "Owner": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "OfferSequence": 1 } } Response: { "id": 21, "status": "success", "type": "response", "result": { "Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "Fee": "10", "Flags": 2147483648, "OfferSequence": 1, "Owner": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "Sequence": 2, "SigningPubKey": "03C3555B7339FFDDB43495A8371A3A87B4C66B67D49D06CB9BA1FDBFEEB57B6E43", "TransactionType": "EscrowFinish", "TxnSignature": "3045022100923B91BA4FD6450813F5335D71C64BA9EB81304A86859A631F2AD8571424A46502200CCE660D36781B84634C5F23619EB6CFCCF942709F54DCCF27CF6F499AE78C9B", "date": 557256681, "hash": "41856A742B3CAF307E7B4D0B850F302101F0F415B785454F7501E9960A2A1F6B", "inLedger": 1908257, "ledger_index": 1908257, "meta": { "AffectedNodes": [ { "ModifiedNode": { "FinalFields": { "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "Balance": "400210000", "Flags": 0, "OwnerCount": 0, "Sequence": 1 }, "LedgerEntryType": "AccountRoot", "LedgerIndex": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8", "PreviousFields": { "Balance": "400200000" }, "PreviousTxnID": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263", "PreviousTxnLgrSeq": 1828796 } }, { "DeletedNode": { "FinalFields": { "Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "Amount": "10000", "Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "FinishAfter": 557020800, "Flags": 0, "OwnerNode": "0000000000000000", "PreviousTxnID": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263", "PreviousTxnLgrSeq": 1828796 }, "LedgerEntryType": "Escrow", "LedgerIndex": "2B9845CB9DF686B9615BF04F3EC66095A334D985E03E71B893B90FCF6D4DC9E6" } }, { "ModifiedNode": { "FinalFields": { "Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "Balance": "9999989980", "Flags": 0, "OwnerCount": 0, "Sequence": 3 }, "LedgerEntryType": "AccountRoot", "LedgerIndex": "AE5AB6584A76C37C7382B6880609FC7792D90CDA36FF362AF412EB914C1715D3", "PreviousFields": { "Balance": "9999989990", "OwnerCount": 1, "Sequence": 2 }, "PreviousTxnID": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263", "PreviousTxnLgrSeq": 1828796 } }, { "ModifiedNode": { "FinalFields": { "Flags": 0, "Owner": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "RootIndex": "D623EBEEEE701D4323D0ADA5320AF35EA8CC6520EBBEF69343354CD593DABC88" }, "LedgerEntryType": "DirectoryNode", "LedgerIndex": "D623EBEEEE701D4323D0ADA5320AF35EA8CC6520EBBEF69343354CD593DABC88" } } ], "TransactionIndex": 2, "TransactionResult": "tesSUCCESS" }, "validated": true } } Javascript // Prepare EscrowFinish transaction --------------------------------- const escrowFinishTransaction = { "Account": wallet.address, "TransactionType": "EscrowFinish", "Owner": wallet.address, // This should equal the sequence number of the escrow transaction "OfferSequence": offerSequence, // Crypto condition that must be met before escrow can be completed, passed on escrow creation. // Omit this for time-held escrows. "Condition": condition, // Fulfillment of the condition, passed on escrow creation. // Omit this for time-held escrows. "Fulfillment": fulfillment, }; xrpl.validate(escrowFinishTransaction); // Sign and submit the transaction ---------------------------------------- console.log('Signing and submitting the transaction:', JSON.stringify(escrowFinishTransaction, null, "\t")); const response = await client.submitAndWait(escrowFinishTransaction, { wallet }); console.log(`Finished submitting! ${JSON.stringify(response.result, null, "\t")}`); Python # Build escrow finish transaction finish_txn = EscrowFinish( account=sender_wallet.address, owner=escrow_creator, offer_sequence=escrow_sequence, # The sequence number of the escrow transaction condition=condition, # Omit this for time-held escrows fulfillment=fulfillment # Omit this for time-held escrows ) # Autofill, sign, then submit transaction and wait for result stxn_response = submit_and_wait(finish_txn, client, sender_wallet) # Parse response and return result stxn_result = stxn_response.result # Parse result and print out the transaction result and transaction hash print(stxn_result["meta"]["TransactionResult"]) print(stxn_result["hash"]) 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. ## 7. 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](/docs/references/http-websocket-apis/admin-api-methods/server-control-methods/ledger_accept) to manually close the ledger. ## 8. Confirm final result Use the [tx method](/docs/references/http-websocket-apis/public-api-methods/transaction-methods/tx) with the EscrowFinish transaction's identifying hash to check its final status. In particular, look in the transaction metadata for a `ModifiedNode` of type `AccountRoot` for the destination of the escrowed payment. The `FinalFields` of the object should show the increase in XRP in the `Balance` field. Request: Websocket { "id": 21, "command": "tx", "transaction": "41856A742B3CAF307E7B4D0B850F302101F0F415B785454F7501E9960A2A1F6B" } Response: Websocket { "id": 21, "status": "success", "type": "response", "result": { "Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "Fee": "10", "Flags": 2147483648, "OfferSequence": 1, "Owner": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "Sequence": 2, "SigningPubKey": "03C3555B7339FFDDB43495A8371A3A87B4C66B67D49D06CB9BA1FDBFEEB57B6E43", "TransactionType": "EscrowFinish", "TxnSignature": "3045022100923B91BA4FD6450813F5335D71C64BA9EB81304A86859A631F2AD8571424A46502200CCE660D36781B84634C5F23619EB6CFCCF942709F54DCCF27CF6F499AE78C9B", "date": 557256681, "hash": "41856A742B3CAF307E7B4D0B850F302101F0F415B785454F7501E9960A2A1F6B", "inLedger": 1908257, "ledger_index": 1908257, "meta": { "AffectedNodes": [ { "ModifiedNode": { "FinalFields": { "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "Balance": "400210000", "Flags": 0, "OwnerCount": 0, "Sequence": 1 }, "LedgerEntryType": "AccountRoot", "LedgerIndex": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8", "PreviousFields": { "Balance": "400200000" }, "PreviousTxnID": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263", "PreviousTxnLgrSeq": 1828796 } }, { "DeletedNode": { "FinalFields": { "Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "Amount": "10000", "Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "FinishAfter": 557020800, "Flags": 0, "OwnerNode": "0000000000000000", "PreviousTxnID": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263", "PreviousTxnLgrSeq": 1828796 }, "LedgerEntryType": "Escrow", "LedgerIndex": "2B9845CB9DF686B9615BF04F3EC66095A334D985E03E71B893B90FCF6D4DC9E6" } }, { "ModifiedNode": { "FinalFields": { "Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "Balance": "9999989980", "Flags": 0, "OwnerCount": 0, "Sequence": 3 }, "LedgerEntryType": "AccountRoot", "LedgerIndex": "AE5AB6584A76C37C7382B6880609FC7792D90CDA36FF362AF412EB914C1715D3", "PreviousFields": { "Balance": "9999989990", "OwnerCount": 1, "Sequence": 2 }, "PreviousTxnID": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263", "PreviousTxnLgrSeq": 1828796 } }, { "ModifiedNode": { "FinalFields": { "Flags": 0, "Owner": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG", "RootIndex": "D623EBEEEE701D4323D0ADA5320AF35EA8CC6520EBBEF69343354CD593DABC88" }, "LedgerEntryType": "DirectoryNode", "LedgerIndex": "D623EBEEEE701D4323D0ADA5320AF35EA8CC6520EBBEF69343354CD593DABC88" } } ], "TransactionIndex": 2, "TransactionResult": "tesSUCCESS" }, "validated": true } } ## See Also - **Concepts:** - [What is XRP?](/docs/introduction/what-is-xrp) - [Payment Types](/docs/concepts/payment-types) - [Escrow](/docs/concepts/payment-types/escrow) - **Tutorials:** - [Send XRP](/docs/tutorials/how-tos/send-xrp) - [Look Up Transaction Results](/docs/concepts/transactions/finality-of-results/look-up-transaction-results) - [Reliable Transaction Submission](/docs/concepts/transactions/reliable-transaction-submission) - **References:** - [EscrowCancel transaction](/docs/references/protocol/transactions/types/escrowcancel) - [EscrowCreate transaction](/docs/references/protocol/transactions/types/escrowcreate) - [EscrowFinish transaction](/docs/references/protocol/transactions/types/escrowfinish) - [account_objects method](/docs/references/http-websocket-apis/public-api-methods/account-methods/account_objects) - [tx method](/docs/references/http-websocket-apis/public-api-methods/transaction-methods/tx) - [Escrow ledger object](/docs/references/protocol/ledger-data/ledger-entry-types/escrow)