diff --git a/assets/js/interactive-tutorial.js b/assets/js/interactive-tutorial.js index 3dd291c015..cd9efeca6c 100644 --- a/assets/js/interactive-tutorial.js +++ b/assets/js/interactive-tutorial.js @@ -425,6 +425,54 @@ async function activate_wait_step(step_name, prelim_result) { status_box.data("status_pending", true) } + +/** + * Get the hexadecimal ASCII representation of a string (must contain only + * 7-bit ASCII characters). + * @param {String} s The string to encode. + * @return {String} The uppercase hexadecimal representation of the string. + */ +function text_to_hex(s) { + result = "" + for (let i=0; i { "Flags": flags } - const cst_prepared = await api.prepareTransaction(cold_settings_tx, {maxLedgerVersionOffset: 20}) - const cst_signed = api.sign(cst_prepared.txJSON, cold_secret) - do_submit(block, {tx_blob: cst_signed.signedTransaction}) + generic_full_send(event, cold_settings_tx, cold_secret) complete_step("Configure Issuer") } catch(err) { @@ -207,9 +205,7 @@ $(document).ready(() => { "Flags": flags } - const hst_prepared = await api.prepareTransaction(hot_settings_tx, {maxLedgerVersionOffset: 10}) - const hst_signed = api.sign(hst_prepared.txJSON, hot_secret) - do_submit(block, {tx_blob: hst_signed.signedTransaction}) + generic_full_send(event, hot_settings_tx, hot_secret) complete_step("Configure Hot Address") } catch(err) { @@ -253,12 +249,7 @@ $(document).ready(() => { "value": limit } } - const ts_prepared = await api.prepareTransaction( - trust_set_tx, - {maxLedgerVersionOffset: 10} - ) - const ts_signed = api.sign(ts_prepared.txJSON, hot_secret) - do_submit(block, {tx_blob: ts_signed.signedTransaction}) + generic_full_send(event, trust_set_tx, hot_secret) complete_step("Make Trust Line") } catch(err) { @@ -303,12 +294,7 @@ $(document).ready(() => { if (use_dest_tag) { send_token_tx["DestinationTag"] = dest_tag } - const pay_prepared = await api.prepareTransaction( - send_token_tx, - {maxLedgerVersionOffset: 10} - ) - const pay_signed = api.sign(pay_prepared.txJSON, cold_secret) - do_submit(block, {tx_blob: pay_signed.signedTransaction}) + generic_full_send(event, send_token_tx, cold_secret) complete_step("Send Token") } catch(err) { diff --git a/content/tutorials/use-tokens/issue-a-fungible-token.md b/content/tutorials/use-tokens/issue-a-fungible-token.md index e56582ff00..8d9ac2c994 100644 --- a/content/tutorials/use-tokens/issue-a-fungible-token.md +++ b/content/tutorials/use-tokens/issue-a-fungible-token.md @@ -172,11 +172,22 @@ _JavaScript_ - +
Sending transaction...
{{ end_step() }} +### {{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. You should wait for your earlier transactions to be fully validated before proceeding to the later steps, to avoid unexpected failures from things executing out of order. For more information, see [Reliable Transaction Submission](reliable-transaction-submission.html). + +**Tip:** Technically, you can configure the hot address in parallel with configuring the issuer address. For simplicity, this tutorial waits for each transaction one at a time. + +{{ start_step("Wait (Issuer Setup)") }} +{% include '_snippets/interactive-tutorials/wait-step.md' %} +{{ end_step() }} + + ### {{n.next()}}. Configure Hot Address Settings The hot address does not strictly require any settings changes from the default, but the following are recommended as best practices: @@ -241,11 +252,19 @@ _JavaScript_ - +
Sending transaction...
{{ end_step() }} +### {{n.next()}}. Wait for Validation + +As before, wait for the previous transaction to be validated by consensus before continuing. + +{{ start_step("Wait (Hot Address Setup)") }} +{% include '_snippets/interactive-tutorials/wait-step.md' %} +{{ end_step() }} + ### {{n.next()}}. Create Trust Line from Hot to Cold Address @@ -287,7 +306,7 @@ _JavaScript_ - +
Sending transaction...
{{ end_step() }} @@ -295,6 +314,15 @@ _JavaScript_ **Note**: If you use [Authorized Trust Lines][], there is an extra step after this one: the cold address must approve the trust line from the hot address. For details of how to do this, see [Authorizing Trust Lines](authorized-trust-lines.html#authorizing-trust-lines). +### {{n.next()}}. Wait for Validation + +As before, wait for the previous transaction to be validated by consensus before continuing. + +{{ start_step("Wait (TrustSet)") }} +{% include '_snippets/interactive-tutorials/wait-step.md' %} +{{ end_step() }} + + ### {{n.next()}}. Send Token Now you can create tokens by sending a [Payment transaction][] from the cold address to the hot address. This transaction should have the following attributes (dot notation indicates nested fields): @@ -341,12 +369,21 @@ _JavaScript_ - +
Sending transaction...
{{ end_step() }} +### {{n.next()}}. Wait for Validation + +As before, wait for the previous transaction to be validated by consensus before continuing. + +{{ start_step("Wait (Payment)") }} +{% include '_snippets/interactive-tutorials/wait-step.md' %} +{{ end_step() }} + + ### {{n.next()}}. Confirm Token Balances You can check the balances of your token from the perspective of either the token issuer or the hot wallet. Tokens issued in the XRP Ledger always have balances that sum to 0: negative from the perspective of the issuer and positive from the perspective of the holder. diff --git a/tool/INTERACTIVE_TUTORIALS_README.md b/tool/INTERACTIVE_TUTORIALS_README.md index dd9862f011..4ee4fecedf 100644 --- a/tool/INTERACTIVE_TUTORIALS_README.md +++ b/tool/INTERACTIVE_TUTORIALS_README.md @@ -18,6 +18,33 @@ Interactive Tutorials are intended to demonstrate interactivity with the XRP Led - As a best practice, don't call the faucet unless the user interacts with the page by clicking a button or something. Otherwise, web crawlers and things just loading the page end up draining the faucet pretty quickly. +## Memos + +Transactions sent from interactive tutorials automatically attach a memo indicating what button of which tutorial sent the memo. Anyone who is watching Testnet/Devnet transactions can look for these memos to see when people are using the tutorials. + +The memo is identified by a `MemoType` that decodes to the URL of this document: + +``` +MemoType (hex): +68747470733A2F2F6769746875622E636F6D2F5852504C462F7872706C2D6465762D706F7274616C2F626C6F622F6D61737465722F746F6F6C2F494E5445524143544956455F5455544F5249414C535F524541444D452E6D64 + +MemoType (ASCII-decoded): +https://github.com/XRPLF/xrpl-dev-portal/blob/master/tool/INTERACTIVE_TUTORIALS_README.md +``` + +The memo has a `MemoFormat` value of `6170706C69636174696F6E2F6A736F6E` (hex), which represents the MIME type `application/json`. + +The memo has a `MemoData` field which is ASCII-encoded JSON containing the following data: + +| Field | Type | Contents | +|---|---|---| +| `path` | String | The `window.location.pathname` of the tutorial. For example, `/send-xrp.html`. | +| `button` | String | The unique html ID of the button that triggered this transaction. For example, `submit-button`. | + +For privacy reasons, the memo does not and MUST NOT include personally identifying information about the user or their browser. + +**Note:** The interactive tutorial code assumes that the path and ID are both possible to encode with plain ASCII, so please avoid using non-ASCII characters in the IDs and filenames. + ## Recommended Process An interactive tutorial is a page, so you add it to the `dactyl-config.yml` page like any other page. However, you need to add the following pieces to make the interactive stuff work: