Issue token tutorial: use memos, wait steps"

This commit is contained in:
mDuo13
2021-08-18 16:58:17 -07:00
parent a7eec0b039
commit 9112945fe2
4 changed files with 130 additions and 24 deletions

View File

@@ -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<s.length; i++) {
result += s.charCodeAt(i).toString(16)
}
return result.toUpperCase()
}
/**
* Add a memo to transaction instructions (before signing) to indicate that this
* transaction was generated by an interactive tutorial. This allows anyone to
* observe transactions on Testnet/Devnet to see which ones originate from which
* interactive tutorials. For privacy reasons, the memo does not and MUST NOT
* include personally identifying information about the user or their browser.
* @param {Object} event The click event that caused this transaction to be sent
* @param {Object} tx_json The JSON transaction instructions to have the memo
* added to them (in-place).
*/
function add_memo(event, tx_json) {
const tutorial_info = {
"path": window.location.pathname,
"button": event.target.id
}
const memo = {
"Memo": {
"MemoData": text_to_hex(JSON.stringify(tutorial_info, null, 0)),
"MemoFormat": "6170706C69636174696F6E2F6A736F6E", // application/json
// The MemoType decodes to a URL that explains the format of this memo type:
// https://github.com/XRPLF/xrpl-dev-portal/blob/master/tool/INTERACTIVE_TUTORIALS_README.md
"MemoType": "68747470733A2F2F6769746875622E636F6D2F5852504C462F7872706C2D6465762D706F7274616C2F626C6F622F6D61737465722F746F6F6C2F494E5445524143544956455F5455544F5249414C535F524541444D452E6D64"
}
}
if (tx_json.Memos === undefined) {
tx_json["Memos"] = [memo]
} else {
tx_json["Memos"].push(memo)
}
}
/**
* Helper for "Send Transaction" buttons to handle the full process of
* Prepare → Sign → Submit in one step with appropriate outputs. Assumes you are
@@ -441,15 +489,23 @@ async function activate_wait_step(step_name, prelim_result) {
* @param {Event} event The (click) event that this is helping to handle.
* @param {Object} tx_json JSON object of transaction instructions to finish
* preparing and send.
* @param {String} secret (Optional) The base58 seed to use to sign the
* transaction. If omitted, look up the #use-secret field
* which was probably added by a "Get Credentials" step.
*/
async function generic_full_send(event, tx_json) {
async function generic_full_send(event, tx_json, secret) {
const block = $(event.target).closest(".interactive-block")
const blob_selector = $(event.target).data("txBlobFrom")
const wait_step_name = $(event.target).data("waitStepName")
block.find(".output-area").html("")
const secret = get_secret(event)
if (secret === undefined) {
secret = get_secret(event)
}
if (!secret) {return}
add_memo(event, tx_json)
block.find(".loader").show()
const prepared = await api.prepareTransaction(tx_json, {
maxLedgerVersionOffset: 20

View File

@@ -167,9 +167,7 @@ $(document).ready(() => {
"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) {

View File

@@ -172,11 +172,22 @@ _JavaScript_
</div>
</div>
</form>
<button id="config-issuer-button" class="btn btn-primary previous-steps-required">Configure issuer</button>
<button id="config-issuer-button" class="btn btn-primary previous-steps-required" data-wait-step-name="Wait (Issuer Setup)">Configure issuer</button>
<div class="loader collapse"><img class="throbber" src="assets/img/xrp-loader-96.png">Sending transaction...</div>
<div class="output-area"></div>
{{ 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_
</div>
</div>
</form>
<button id="config-hot-address-button" class="btn btn-primary previous-steps-required">Configure hot address</button>
<button id="config-hot-address-button" class="btn btn-primary previous-steps-required" data-wait-step-name="Wait (Hot Address Setup)">Configure hot address</button>
<div class="loader collapse"><img class="throbber" src="assets/img/xrp-loader-96.png">Sending transaction...</div>
<div class="output-area"></div>
{{ 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_
</div>
</div>
</form>
<button id="create-trust-line-button" class="btn btn-primary previous-steps-required">Create Trust Line</button>
<button id="create-trust-line-button" class="btn btn-primary previous-steps-required" data-wait-step-name="Wait (TrustSet)">Create Trust Line</button>
<div class="loader collapse"><img class="throbber" src="assets/img/xrp-loader-96.png">Sending transaction...</div>
<div class="output-area"></div>
{{ 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_
</div>
</div>
</form>
<button id="send-token-button" class="btn btn-primary previous-steps-required">Send Token</button>
<button id="send-token-button" class="btn btn-primary previous-steps-required" data-wait-step-name="Wait (Payment)">Send Token</button>
<div class="loader collapse"><img class="throbber" src="assets/img/xrp-loader-96.png">Sending transaction...</div>
<div class="output-area"></div>
{{ 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.

View File

@@ -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: