From 8c25a5ea3397acb985226ad32b45a51511aeb79b Mon Sep 17 00:00:00 2001 From: mDuo13 Date: Wed, 17 Sep 2025 18:19:53 -0700 Subject: [PATCH] Start implementing tutorial for updated timed escrow sample --- .../escrow/js/send-timed-escrow-linear.js | 92 ------------------- ...crow-functions.js => send-timed-escrow.js} | 30 +++--- ...-held-escrow.md => send-a-timed-escrow.md} | 56 +++++++++-- 3 files changed, 68 insertions(+), 110 deletions(-) delete mode 100644 _code-samples/escrow/js/send-timed-escrow-linear.js rename _code-samples/escrow/js/{send-timed-escrow-functions.js => send-timed-escrow.js} (93%) rename docs/tutorials/how-tos/use-specialized-payment-types/use-escrows/{send-a-time-held-escrow.md => send-a-timed-escrow.md} (81%) diff --git a/_code-samples/escrow/js/send-timed-escrow-linear.js b/_code-samples/escrow/js/send-timed-escrow-linear.js deleted file mode 100644 index c8079fd37c..0000000000 --- a/_code-samples/escrow/js/send-timed-escrow-linear.js +++ /dev/null @@ -1,92 +0,0 @@ -import xrpl from 'xrpl' - -/* Sleep function that can be used with await */ -function sleep (delayInSeconds) { - const delayInMs = delayInSeconds * 1000 - return new Promise((resolve) => setTimeout(resolve, delayInMs)) -} - -const client = new xrpl.Client('wss://s.altnet.rippletest.net:51233') -await client.connect() - -console.log('Funding new wallet from faucet...') -const { wallet } = await client.fundWallet() -const dest_address = 'rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe' // Testnet faucet -const delay = 30 - -// Set the escrow finish time ----------------------------------------------- -const finishAfter = new Date() -finishAfter.setSeconds(finishAfter.getSeconds() + delay) -console.log('This escrow will finish after:', finishAfter) -// Convert finishAfter to seconds since the Ripple Epoch: -const finishAfterRippleTime = xrpl.isoTimeToRippleTime(finishAfter.toISOString()) - -// Send EscrowCreate transaction -------------------------------------------- -const escrowCreate = { - TransactionType: 'EscrowCreate', - Account: wallet.address, - Destination: dest_address, - Amount: '12345', // drops of XRP - FinishAfter: finishAfterRippleTime -} -xrpl.validate(escrowCreate) - -console.log('Signing and submitting the transaction:', - JSON.stringify(escrowCreate, null, 2)) -const response = await client.submitAndWait(escrowCreate, { - wallet, - autofill: true -}) -console.log(JSON.stringify(response.result, null, 2)) -const escrowSeq = response.result.tx_json.Sequence -console.log(`Escrow sequence is ${escrowSeq}.`) - -// Wait for the escrow to be finishable ------------------------------------- -console.log(`Waiting ${delay} seconds for the escrow to mature...`) -await sleep(delay) - -// Check if escrow can be finished ------------------------------------------- -let escrowReady = false -while (!escrowReady) { - // Check the close time of the latest validated ledger. - // Close times are rounded by about 10 seconds, so the exact time the escrow - // is ready to finish may vary by +/- 10 seconds. - const validatedLedger = await client.request({ - command: 'ledger', - ledger_index: 'validated' - }) - const ledgerCloseTime = validatedLedger.result.ledger.close_time - console.log('Latest validated ledger closed at', - xrpl.rippleTimeToISOTime(ledgerCloseTime)) - if (ledgerCloseTime > finishAfterRippleTime) { - escrowReady = true - console.log('Escrow is ready to be finished.') - } else { - let timeDifference = finishAfterRippleTime - ledgerCloseTime - if (timeDifference === 0) { timeDifference = 1 } - console.log(`Waiting another ${timeDifference} second(s).`) - await sleep(timeDifference) - } -} - -// Send EscrowFinish transaction -------------------------------------------- -const escrowFinish = { - TransactionType: 'EscrowFinish', - Account: wallet.address, - Owner: wallet.address, - OfferSequence: escrowSeq -} -xrpl.validate(escrowFinish) - -console.log('Signing and submitting the transaction:', - JSON.stringify(escrowFinish, null, 2)) -const response2 = await client.submitAndWait(escrowFinish, { - wallet, - autofill: true -}) -console.log(JSON.stringify(response2.result, null, 2)) -if (response2.result.meta.TransactionResult === 'tesSUCCESS') { - console.log('Escrow finished successfully.') -} - -client.disconnect() diff --git a/_code-samples/escrow/js/send-timed-escrow-functions.js b/_code-samples/escrow/js/send-timed-escrow.js similarity index 93% rename from _code-samples/escrow/js/send-timed-escrow-functions.js rename to _code-samples/escrow/js/send-timed-escrow.js index 980c53f200..dc302d9d00 100644 --- a/_code-samples/escrow/js/send-timed-escrow-functions.js +++ b/_code-samples/escrow/js/send-timed-escrow.js @@ -1,11 +1,5 @@ import xrpl from 'xrpl' -/* Sleep function that can be used with await */ -function sleep (delayInSeconds) { - const delayInMs = delayInSeconds * 1000 - return new Promise((resolve) => setTimeout(resolve, delayInMs)) -} - /* Main function when called as a commandline script */ async function main () { const client = new xrpl.Client('wss://s.altnet.rippletest.net:51233') @@ -13,13 +7,17 @@ async function main () { console.log('Funding new wallet from faucet...') const { wallet } = await client.fundWallet() + + // Define properties of the escrow const dest_address = 'rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe' // Testnet faucet - const delay = 30 + const delay = 30 // how long to escrow the funds, in seconds + const amount = '12345' // drops of XRP to send in the escrow const { escrowSeq, finishAfterRippleTime } = await send_timed_escrow( client, wallet, dest_address, + amount, delay ) @@ -30,12 +28,13 @@ async function main () { client.disconnect() } -/* +/* send_timed_escrow * Create a time-based escrow. * Parameters: * client (xrpl.Client): network-connected client * wallet (xrpl.Wallet): sender wallet * dest_address (string): receiver address in base58 + * amount (string): how many drops of XRP to send in escrow * delay (int): number of seconds until the escrow is mature * Returns: object with the following keys * response (xrpl.TxResponse): transaction result from submitAndWait @@ -43,7 +42,7 @@ async function main () { * finishAfterRippleTime (int): the FinishAfter time of the created escrow, * in seconds since the Ripple Epoch */ -async function send_timed_escrow (client, wallet, dest_address, delay) { +async function send_timed_escrow (client, wallet, dest_address, amount, delay) { // Set the escrow finish time ----------------------------------------------- const finishAfter = new Date() finishAfter.setSeconds(finishAfter.getSeconds() + delay) @@ -56,7 +55,7 @@ async function send_timed_escrow (client, wallet, dest_address, delay) { TransactionType: 'EscrowCreate', Account: wallet.address, Destination: dest_address, - Amount: '12345', // drops of XRP + Amount: amount, FinishAfter: finishAfterRippleTime } xrpl.validate(escrowCreate) @@ -77,7 +76,7 @@ async function send_timed_escrow (client, wallet, dest_address, delay) { } } -/* +/* wait_for_escrow * Check the ledger close time to see if an escrow can be finished. * If it's not ready yet, wait a number of seconds equal to the difference * from the latest ledger close time to the escrow's FinishAfter time. @@ -113,7 +112,13 @@ async function wait_for_escrow (client, finishAfterRippleTime) { } } -/* +/* Sleep function that can be used with await */ +function sleep (delayInSeconds) { + const delayInMs = delayInSeconds * 1000 + return new Promise((resolve) => setTimeout(resolve, delayInMs)) +} + +/* finish_escrow * Finish an escrow that your account owns. * Parameters: * client (xrpl.Client): network-connected client @@ -143,4 +148,5 @@ async function finish_escrow (client, wallet, escrowSeq) { } } +// Call main function so it runs as a script main() diff --git a/docs/tutorials/how-tos/use-specialized-payment-types/use-escrows/send-a-time-held-escrow.md b/docs/tutorials/how-tos/use-specialized-payment-types/use-escrows/send-a-timed-escrow.md similarity index 81% rename from docs/tutorials/how-tos/use-specialized-payment-types/use-escrows/send-a-time-held-escrow.md rename to docs/tutorials/how-tos/use-specialized-payment-types/use-escrows/send-a-timed-escrow.md index 3f82e9c66e..f72d7bf456 100644 --- a/docs/tutorials/how-tos/use-specialized-payment-types/use-escrows/send-a-time-held-escrow.md +++ b/docs/tutorials/how-tos/use-specialized-payment-types/use-escrows/send-a-timed-escrow.md @@ -1,15 +1,59 @@ --- -html: send-a-time-held-escrow.html -parent: use-escrows.html seo: - description: Create an escrow whose only condition for release is that a specific time has passed. + description: Send an escrow whose only condition for release is that a specific time has passed. labels: - Escrow - - Smart Contracts --- -# Send a Time-Held Escrow +# Send a Timed Escrow + +This tutorial demonstrates how to send an [escrow](../../../../concepts/payment-types/escrow.md) whose only condition for release is that a specific time has passed. You can use this to set aside money for yourself or others so that it absolutely cannot be used until the specified time. + +This tutorial shows how to escrow XRP. If the [TokenEscrow amendment][] is enabled, you can also escrow tokens. + +## Goals + +By following this tutorial, you should learn how to: + +- Convert a timestamp into the XRP Ledger's native format. +- Create and finish an escrow. + +## Prerequisites + +To complete this tutorial, you should: + +- Have a basic understanding of the XRP Ledger +- Have an XRP Ledger client library, such as **xrpl.js**, installed. + +## Source Code + +You can find the complete source code for this tutorial's examples in the {% repo-link path="_code-samples/escrow/send-timed-escrow.js" %}code samples section of this website's repository{% /repo-link %}. + +## Steps + +### 1. Install dependencies + +{% tabs %} +{% tab label="JavaScript" %} +From the code sample folder, use npm to install dependencies: + +```sh +npm i +``` +{% /tab %} +{% /tabs %} + +### 2. Import dependencies and get accounts + +After importing the XRPL client library, the tutorial code gets a new wallet from the testnet faucet and defines the properties of the escrow as hard-coded constants. You can use an existing wallet or modify the constants as desired. + + +{% tabs %} +{% tab label="JavaScript" %} +{% code-snippet file="/_code-samples/escrow/js/send-timed-escrow.js" language="js" before="/* send_timed_escrow" /%} +{% /tab %} +{% /tabs %} + -The [EscrowCreate transaction][] 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