mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-27 07:05:51 +00:00
Use Tickets: draft complete
This commit is contained in:
@@ -307,6 +307,7 @@ let waiting_for_tx = null;
|
|||||||
api.on('ledger', async (ledger) => {
|
api.on('ledger', async (ledger) => {
|
||||||
$("#current-ledger-version").text(ledger.ledgerVersion)
|
$("#current-ledger-version").text(ledger.ledgerVersion)
|
||||||
|
|
||||||
|
let tx_result;
|
||||||
if (waiting_for_tx) {
|
if (waiting_for_tx) {
|
||||||
try {
|
try {
|
||||||
tx_result = await api.request("tx", {
|
tx_result = await api.request("tx", {
|
||||||
@@ -314,7 +315,6 @@ api.on('ledger', async (ledger) => {
|
|||||||
"min_ledger": parseInt($("#earliest-ledger-version").text()),
|
"min_ledger": parseInt($("#earliest-ledger-version").text()),
|
||||||
"max_ledger": parseInt($("#lastledgersequence").text())
|
"max_ledger": parseInt($("#lastledgersequence").text())
|
||||||
})
|
})
|
||||||
console.log(tx_result)
|
|
||||||
if (tx_result.validated) {
|
if (tx_result.validated) {
|
||||||
$("#tx-validation-status").html(
|
$("#tx-validation-status").html(
|
||||||
`<th>Final Result:</th><td>${tx_result.meta.TransactionResult} (Validated)</td>`)
|
`<th>Final Result:</th><td>${tx_result.meta.TransactionResult} (Validated)</td>`)
|
||||||
@@ -359,6 +359,7 @@ let response = await api.request("account_objects", {
|
|||||||
})
|
})
|
||||||
|
|
||||||
console.log("Available Tickets:", response.account_objects)
|
console.log("Available Tickets:", response.account_objects)
|
||||||
|
let use_ticket = response.account_objects[0].TicketSequence
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -381,6 +382,13 @@ console.log("Available Tickets:", response.account_objects)
|
|||||||
})
|
})
|
||||||
$("#check-tickets-output").html(`<pre><code>${pretty_print(response)}</code></pre>`)
|
$("#check-tickets-output").html(`<pre><code>${pretty_print(response)}</code></pre>`)
|
||||||
|
|
||||||
|
// Reset the next step's form & add these tickets
|
||||||
|
$("#ticket-selector .form-area").html("")
|
||||||
|
response.account_objects.forEach((ticket, i) => {
|
||||||
|
$("#ticket-selector .form-area").append(`<div class="form-check form-check-inline"><input class="form-check-input" type="radio" id="ticket${i}" name="ticket-radio-set" value="${ticket.TicketSequence}"><label class="form-check-label" for="ticket${i}">${ticket.TicketSequence}</label></div>`)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
// Update breadcrumbs & activate next step
|
// Update breadcrumbs & activate next step
|
||||||
complete_step("Check Tickets")
|
complete_step("Check Tickets")
|
||||||
$("#prepare-ticketed-tx").prop("disabled", false)
|
$("#prepare-ticketed-tx").prop("disabled", false)
|
||||||
@@ -392,13 +400,12 @@ console.log("Available Tickets:", response.account_objects)
|
|||||||
|
|
||||||
Now that you have a Ticket available, you can prepare a transaction that uses it.
|
Now that you have a Ticket available, you can prepare a transaction that uses it.
|
||||||
|
|
||||||
This can be any [type of transaction](transaction-types.html) you like. The following example uses an [AccountSet transaction][] to set a `MessageKey` since that doesn't require any other setup in the ledger. Set the `Sequence` field to `0` and include a `TicketSequence` field with the Ticket Sequence number of one of your available Tickets.
|
This can be any [type of transaction](transaction-types.html) you like. The following example uses a no-op [AccountSet transaction][] since that doesn't require any other setup in the ledger. Set the `Sequence` field to `0` and include a `TicketSequence` field with the Ticket Sequence number of one of your available Tickets.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
let prepared_t = await api.prepareTransaction({
|
let prepared_t = await api.prepareTransaction({
|
||||||
"TransactionType": "AccountSet",
|
"TransactionType": "AccountSet",
|
||||||
"Account": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
|
"Account": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
|
||||||
"MessageKey": "DEADBEEF",
|
|
||||||
"TicketSequence": use_ticket,
|
"TicketSequence": use_ticket,
|
||||||
"Sequence": 0
|
"Sequence": 0
|
||||||
}, {
|
}, {
|
||||||
@@ -418,6 +425,10 @@ console.log("Signed transaction blob:", tx_blob_t)
|
|||||||
**Tip:** If you don't plan to submit the TicketCreate transaction right away, you should explicitly set the [instructions'](rippleapi-reference.html#transaction-instructions) `maxLedgerVersionOffset` to a larger number of ledgers. To create a transaction that could remain valid indefinitely, set the `maxLedgerVersion` to `null`.
|
**Tip:** If you don't plan to submit the TicketCreate transaction right away, you should explicitly set the [instructions'](rippleapi-reference.html#transaction-instructions) `maxLedgerVersionOffset` to a larger number of ledgers. To create a transaction that could remain valid indefinitely, set the `maxLedgerVersion` to `null`.
|
||||||
|
|
||||||
{{ start_step("Prepare Ticketed Tx") }}
|
{{ start_step("Prepare Ticketed Tx") }}
|
||||||
|
<div id="ticket-selector">
|
||||||
|
<h4>Select a Ticket:</h4>
|
||||||
|
<div class="form-area"></div>
|
||||||
|
</div>
|
||||||
<button id="prepare-ticketed-tx" class="btn btn-primary connection-required"
|
<button id="prepare-ticketed-tx" class="btn btn-primary connection-required"
|
||||||
title="Complete all previous steps first" disabled>Prepare Ticketed Transaction</button>
|
title="Complete all previous steps first" disabled>Prepare Ticketed Transaction</button>
|
||||||
<div id="prepare-ticketed-tx-output"></div>
|
<div id="prepare-ticketed-tx-output"></div>
|
||||||
@@ -425,7 +436,42 @@ console.log("Signed transaction blob:", tx_blob_t)
|
|||||||
|
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
$("#prepare-ticketed-tx").click(async function() {
|
$("#prepare-ticketed-tx").click(async function() {
|
||||||
// TODO
|
const use_ticket = parseInt($('input[name="ticket-radio-set"]:checked').val())
|
||||||
|
if (!use_ticket) {
|
||||||
|
$("#prepare-ticketed-tx-output").append('<p class="devportal-callout warning"><strong>Error</strong> You must choose a ticket first.</p>')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const address = $("#use-address").text()
|
||||||
|
const secret = $("#use-secret").text()
|
||||||
|
|
||||||
|
let prepared_t = await api.prepareTransaction({
|
||||||
|
"TransactionType": "AccountSet",
|
||||||
|
"Account": address,
|
||||||
|
"TicketSequence": use_ticket,
|
||||||
|
"Sequence": 0
|
||||||
|
}, {
|
||||||
|
maxLedgerVersionOffset: 20
|
||||||
|
})
|
||||||
|
$("#prepare-ticketed-tx-output").html("")
|
||||||
|
|
||||||
|
$("#prepare-ticketed-tx-output").append(
|
||||||
|
`<p>Prepared transaction:</p><pre><code>${pretty_print(prepared_t.txJSON)}</code></pre>`)
|
||||||
|
$("#lastledgersequence_t").html( //REMEMBER
|
||||||
|
`<code>${prepared_t.instructions.maxLedgerVersion}</code>`)
|
||||||
|
|
||||||
|
let signed_t = await api.sign(prepared_t.txJSON, secret)
|
||||||
|
$("#prepare-ticketed-tx-output").append(
|
||||||
|
`<p>Transaction hash: <code id="tx_id_t">${signed_t.id}</code></p>`)
|
||||||
|
|
||||||
|
let tx_blob_t = signed_t.signedTransaction
|
||||||
|
$("#prepare-ticketed-tx-output").append(
|
||||||
|
`<pre style="visibility: none"><code id="tx_blob_t">${tx_blob_t}</code></pre>`)
|
||||||
|
|
||||||
|
// Update breadcrumbs & activate next step
|
||||||
|
complete_step("Prepare Ticketed Tx")
|
||||||
|
$("#ticketedtx-submit").prop("disabled", false)
|
||||||
|
$("#ticketedtx-submit").prop("title", "")
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -438,12 +484,94 @@ let prelim_result_t = await api.submit(tx_blob_t)
|
|||||||
console.log("Preliminary result:", prelim_result_t)
|
console.log("Preliminary result:", prelim_result_t)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
{{ start_step("Submit Ticketed Tx") }}
|
||||||
|
<button id="ticketedtx-submit" class="btn btn-primary connection-required"
|
||||||
|
title="Complete all previous steps first" disabled>Submit</button>
|
||||||
|
<div id="ticketedtx-submit-output"></div>
|
||||||
|
{{ end_step() }}
|
||||||
|
|
||||||
|
|
||||||
|
<script type="application/javascript">
|
||||||
|
$("#ticketedtx-submit").click( async function() {
|
||||||
|
const tx_blob = $("#tx_blob_t").text()
|
||||||
|
// Wipe previous output
|
||||||
|
$("#ticketedtx-submit-output").html("")
|
||||||
|
|
||||||
|
waiting_for_tx_t = $("#tx_id_t").text() // next step uses this
|
||||||
|
let prelim_result = await api.request("submit", {"tx_blob": tx_blob})
|
||||||
|
$("#ticketedtx-submit-output").append(
|
||||||
|
`<p>Preliminary result:</p><pre><code>${pretty_print(prelim_result)}</code></pre>`)
|
||||||
|
$("#earliest-ledger-version_t").text(prelim_result.validated_ledger_index)
|
||||||
|
|
||||||
|
// TODO: remove for devnet/testnet
|
||||||
|
await api.request("ledger_accept")
|
||||||
|
|
||||||
|
// Update breadcrumbs
|
||||||
|
complete_step("Submit Ticketed Tx")
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
### {{n.next()}}. Wait for Validation
|
### {{n.next()}}. Wait for Validation
|
||||||
|
|
||||||
```js
|
Ticketed transactions go through the consensus process the same way that Sequenced transactions do.
|
||||||
TODO
|
|
||||||
```
|
|
||||||
|
|
||||||
|
{{ start_step("Wait Again") }}
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Latest Validated Ledger Version:</th>
|
||||||
|
<td id="current-ledger-version_t">(Not connected)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Ledger Version at Time of Submission:</th>
|
||||||
|
<td id="earliest-ledger-version_t">(Not submitted)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Ticketed Transaction <code>LastLedgerSequence</code>:</th>
|
||||||
|
<td id="lastledgersequence_t">(Not prepared)</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="tx-validation-status_t">
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
{{ end_step() }}
|
||||||
|
|
||||||
|
<script type="application/javascript">
|
||||||
|
let waiting_for_tx_t = null;
|
||||||
|
api.on('ledger', async (ledger) => {
|
||||||
|
$("#current-ledger-version_t").text(ledger.ledgerVersion)
|
||||||
|
|
||||||
|
let tx_result;
|
||||||
|
if (waiting_for_tx_t) {
|
||||||
|
try {
|
||||||
|
tx_result = await api.request("tx", {
|
||||||
|
"transaction": waiting_for_tx_t,
|
||||||
|
"min_ledger": parseInt($("#earliest-ledger-version_t").text()),
|
||||||
|
"max_ledger": parseInt($("#lastledgersequence_t").text())
|
||||||
|
})
|
||||||
|
console.log(tx_result)
|
||||||
|
if (tx_result.validated) {
|
||||||
|
$("#tx-validation-status_t").html(
|
||||||
|
`<th>Final Result:</th><td>${tx_result.meta.TransactionResult} (Validated)</td>`)
|
||||||
|
waiting_for_tx_t = null;
|
||||||
|
|
||||||
|
if ( $(".breadcrumb-item.bc-wait").hasClass("active") ) {
|
||||||
|
complete_step("Wait Again")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: handle the case described in https://github.com/ripple/rippled/issues/3727
|
||||||
|
} catch(e) {
|
||||||
|
if (e.data.error == "txnNotFound" && e.data.searched_all) {
|
||||||
|
$("#tx-validation-status_t").html(
|
||||||
|
`<th>Final Result:</th><td>Failed to achieve consensus (final)</td>`)
|
||||||
|
waiting_for_tx_t = null;
|
||||||
|
} else {
|
||||||
|
$("#tx-validation-status_t").html(
|
||||||
|
`<th>Final Result:</th><td>Unknown</td>`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user