diff --git a/content/tutorials/use-simple-xrp-payments/send-xrp.md b/content/tutorials/use-simple-xrp-payments/send-xrp.md new file mode 100644 index 0000000000..2f58b45542 --- /dev/null +++ b/content/tutorials/use-simple-xrp-payments/send-xrp.md @@ -0,0 +1,160 @@ +# Send XRP + +This tutorial walks through send a simple XRP Payment using JavaScript, by first stepping through the process using the XRP Test Net, then comparing that to the additional requirements for doing the equivalent in production. + +## Prerequisites + +This page provides JavaScript examples that use the ripple-lib (RippleAPI) library. The [RippleAPI Beginners Guide](get-started-with-rippleapi-for-javascript.html) describes how to get started using RippleAPI to access XRP Ledger data from JavaScript. + +## Send a Payment on the Test Net +{% set n = cycler(* range(1,99)) %} + +### {{n.next()}}. Get an XRP Test Net Address + +To send transactions in the XRP Ledger, you first need an address and secret key, and some XRP. You can get an address in the XRP Test Net with a supply of Test Net XRP using the following interface: + + +
+ +
+ +
+
+
+
+ +Ripple operates the XRP Test Net for testing purposes only, and regularly resets the state of the test net along with all balances. + +### {{n.next()}}. Prepare Transaction + +Typically, we prepare XRP Ledger transactions as objects in [JSON](https://en.wikipedia.org/wiki/JSON) format. The following example shows a minimal Payment specification: + +```json +{ + "TransactionType": "Payment", + "Account": "rD9bZqwXu67DuZDtNCjjeDUTNLb6iQnHDn", + "Amount": "2000000", + "Destination": "rUCzEr6jrEyMpjhs4wSdQdz4g8Y382NxfM" +} +``` + +The bare minimum set of instructions for an XRP Payment is: + +- An indicator that this is a payment. (`"TransactionType": "Payment"`) +- The sending address. (`"Account"`) +- The address that should receive the XRP (`"Destination"`). This can't be the same as the sending address. +- The amount of XRP to send (`"Amount"`). Typically, this is specified as an integer in "drops" of XRP, where 1,000,000 drops equals 1 XRP. + +Technically, a viable transaction must contain some additional fields, but your client library can automatically choose sensible values for those if it's online. Some optional fields, such as `LastLedgerSequence`, are strongly recommended when sending payments with real value. For details, see [Differences for Production](#differences-for-production) below. + +**Tip:** The above example uses the standard JSON [transaction format](transaction-formats.html). You can also use RippleAPI's `preparePayment()` method to generate the transaction's JSON format. + + +### {{n.next()}}. Connect to a Test Net Server + +To provide the necessary auto-fillable fields, ripple-lib must be connected to a server where it can get the current status of your account and the shared ledger itself. (You _can_ sign transactions while being offline, but you need to provide more fields yourself.) You also, obviously, need to be connected to the network to submit transactions to it. + +The following code sample instantiates a new RippleAPI instance and connects to one of the public XRP Test Net servers that Ripple runs: + +```js +ripple = require('ripple-lib') +api = new ripple.RippleAPI({server: 'wss://s.altnet.rippletest.net:51233'}) +api.connect() +``` + +### {{n.next()}}. Sign the Transaction Instructions + +Use the [sign() method](rippleapi-reference.html#sign) to sign the transaction string with RippleAPI. If you constructed the transaction manually, as in this example, you must convert it from JSON to string first. + +```js +let payment_json = { + "TransactionType": "Payment", + "Account": "rD9bZqwXu67DuZDtNCjjeDUTNLb6iQnHDn", + "Amount": "2000000", + "Destination": "rUCzEr6jrEyMpjhs4wSdQdz4g8Y382NxfM" +} +// TODO: 'api' should be online +const response = api.sign( + JSON.stringify(payment_json), + "s████████████████████████████") +const txID = response.id +console.log("Identifying hash:", txID) +const txBlob = response.signedTransaction +console.log("Signed blob:", txBlob) +``` + +The result of the signing operation is a transaction object containing a signature. Typically, XRP Ledger APIs expect a signed transaction to be the hexadecimal representation of the transaction's canonical [binary format](serialization.html), called a "blob". For a Payment such as this one, a signed transaction blob looks like this (with line breaks added here for readability): + +```text +1200006140000000001E8480732102CD9D02581F13380BB1876313C1C2AA83267CD73 +45802BFC9BA9311774B9B18A574473045022100DBCB5FE6CEC0CE81B077A11710CB40 +E6A4F9939A45C3B4FBCFFC73C145E14CEC022044857DBE49B50DA14D7369D9BF44202 +07ACB369571EBD905CE8FA37C4154820281148541B0FE2928E372CCAD5A1CC6F47FE8 +5C15DD0B83148008F9193579C7D32FAF4AD1A9BFFDB236F148E3 +``` + +The signing API also returns the transaction's ID, or identifying hash, which you can use to look up the transaction later. This is a 64-character hexadecimal string that is unique to this transaction. The following is the identifying hash of the transaction from the same example: + +```text +D403EC6E03A68A4B7624508BAA271143A65D3AAA5D470BECD3A38EC54CEAF85E +``` + + +### {{n.next()}}. Submit the Signed Blob + +```js +// txBlob from the previous example +api.submit(txBlob).then(result => { + console.log("Tentative result code:", result.resultCode) + console.log("Tentative result message:", result.resultMessage) +}) +``` + +This method returns the **tentative** result of trying to apply the transaction locally. This result _can_ change when the transaction is included in a validated ledger: transactions that succeed initially might ultimately fail, and transactions that fail initially might ultimately succeed. Still, the tentative result often matches the final result, so it's OK to get excited if you see `tesSUCCESS` here. 😁 + +If you see any other result, you should check the following: + +- Are you using the correct addresses for the sender and destination? +- Did you forget any other fields of the transaction, skip any steps, or make any other typos? +- Do you have enough Test Net XRP to send the transaction? The amount of XRP you can send is limited by the [reserve requirement](reserves.html), which is currently 20 XRP with an additional 5 XRP for each "object" you own in the ledger. (If you generated a new address with the Test Net Faucet, you don't own any objects.) +- That you are connected to a server on the test network. + +See the full list of [transaction results](transaction-results.html) for more possibilities. + + +### {{n.next()}}. Wait for Validation + +Most transactions are accepted into the next ledger version after they're submitted, which means it may take 4-7 seconds for a transaction's outcome to be final. If the XRP Ledger is busy or poor network connectivity delays a transaction from being relayed throughout the network, a transaction may take longer to be confirmed. (For information on how to set an expiration for transactions, see ) + +You can trigger code to run using the `ledger` event type in RippleAPI. For example: + +```js +api.on('ledger', ledger => { + console.log("Ledger version", ledger.ledgerVersion, "was just validated.") +}) +``` + + +### {{n.next()}}. Check Transaction Status + +To know for sure what a transaction did, you must look up the outcome of the transaction when it appears in a validated ledger version. For example, you can use the [getTransaction() method](rippleapi-reference.html#gettransaction) to check the status of a transaction: + +```js +api.getTransaction(txID).done(tx => { + console.log("Transaction result:", tx.outcome.result) + console.log("Balance changes:", JSON.stringify(tx.outcome.balanceChanges)) +}) +``` + +The RippleAPI `getTransaction()` method only returns success if the transaction is in a validated ledger version. + +**Caution:** Other APIs may return tentative results from ledger versions that have not yet been validated. For example, if you use the `rippled` APIs' [tx method][], be sure to look for `"validated": true` in the response to confirm that the data comes from a validated ledger version. Any transaction results that are not from a validated ledger version are subject to change. + + + + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} diff --git a/dactyl-config.yml b/dactyl-config.yml index f7bc157740..ab4926f704 100644 --- a/dactyl-config.yml +++ b/dactyl-config.yml @@ -646,7 +646,14 @@ pages: targets: - local - # TODO: "Send XRP" + - md: tutorials/use-simple-xrp-payments/send-xrp.md + html: send-xrp.html + funnel: Docs + doc_type: Tutorials + category: Use Simple XRP Payments + blurb: Test out sending XRP using the XRP Test Net. + targets: + - local - md: tutorials/use-simple-xrp-payments/reliable-transaction-submission.md html: reliable-transaction-submission.html