Skip to content
Last updated

Use Tickets

Tickets let you reserve Sequence numbers in advance so you can send transactions out of order. This is useful when collecting signatures on multi-signed transactions while normal account activity continues, or queuing transactions for later submission.

This tutorial walks through creating a batch of Tickets, using one in a transaction, and applying the same pattern to multi-signed workflows.

Requires the TicketBatch amendment. Loading...

Goals

By the end of this tutorial, you will be able to:

  • Create Tickets to reserve Sequence numbers for future use.
  • Use a Ticket to send a transaction outside the normal Sequence order.

Prerequisites

To complete this tutorial, you need:

  • A basic understanding of the XRP Ledger.
  • A basic understanding of how Sequence numbers work in transactions.
  • An XRP Ledger client library set up.
  • (Optional) A basic understanding of multi-signing, if you plan to combine it with Tickets.

Source Code

You can find the complete source code for this tutorial's examples in the code samples section of this website's repository.

Steps

1. Install dependencies

Install dependencies for your language from the code sample folder.

npm install

2. Set up client and account

Import the XRPL client library, connect to the network, and generate a test account funded by the Testnet faucet. Using a live test network lets you submit transactions without risking real XRP.

import xrpl from 'xrpl'

// Set up client and account
const client = new xrpl.Client('wss://s.altnet.rippletest.net:51233')
await client.connect()

// Fund wallet --------------------------------------------------------------
console.log('Getting a wallet from the faucet...')
const { wallet } = await client.fundWallet()
console.log("Wallet address:", wallet.address)
Note

When you're building production-ready software, use an existing account and manage your keys using a secure signing configuration.

3. Create Tickets

Send a TicketCreate transaction and set the TicketCount field to the number of Tickets you want to create (up to 250 per account). Each new Ticket reserves a future Sequence Number you can use later. Each Ticket also counts toward your account's owner reserve, which is released when the Ticket is used. Tickets stay reserved on the ledger until you consume them, regardless of any other transactions your account sends.

Submit the transaction and wait for validation. For example, to create 10 Tickets:

// Create Tickets -----------------------------------------------------------
console.log('\nSubmitting TicketCreate transaction...')
const ticketCreateResult = await client.submitAndWait({
  TransactionType: 'TicketCreate',
  Account: wallet.address,
  TicketCount: 10
}, { wallet, autofill: true })
console.log(`TicketCreate hash: ${ticketCreateResult.result.hash}, validated: ${ticketCreateResult.result.validated}`)
Note

A transaction is not final until it is validated by consensus, which typically occurs 4-7 seconds after submission. The submit-and-wait call above blocks until validation completes, so the validated result is already available.

For production code that needs to handle longer waits or transaction expiration, see Reliable Transaction Submission.

4. Check available Tickets

To send a Ticketed transaction, you need a Ticket Sequence number. Use the account_objects method to list your Tickets. See the method's Response Format for the response shape.

// Check Available Tickets --------------------------------------------------
console.log('\nChecking available tickets...')
const ticketsResponse = await client.request({
  command: 'account_objects',
  account: wallet.address,
  type: 'ticket'
})
const tickets = ticketsResponse.result.account_objects
console.log(`Found ${tickets.length} Tickets`)

// Choose an arbitrary Ticket to use
const useTicket = tickets[0].TicketSequence
console.log(`Using Ticket Sequence: ${useTicket}`)

You can repeat the next step as long as you have unused Tickets.

5. Use a Ticket

Now that you have a Ticket available, you can use it in a transaction. This can be any type of transaction. You can use Tickets in any order, but each can only be used once. For the multi-signing variant, see With Multi-Signing below.

The Ticket pattern

For any transaction that uses a Ticket, set the Sequence field to 0 and include a TicketSequence field with one of your available Ticket Sequence numbers.

The following example uses an AccountSet transaction with no fields set, making it a no-op that requires no setup. Ticketed transactions go through the same consensus process as Sequenced transactions.

// Use a Ticket -------------------------------------------------------------
console.log('\nSubmitting ticketed AccountSet transaction...')
const ticketedResult = await client.submitAndWait({
  TransactionType: 'AccountSet',
  Account: wallet.address,
  TicketSequence: useTicket,
  Sequence: 0
}, { wallet, autofill: true })
console.log(`Ticketed AccountSet hash: ${ticketedResult.result.hash}, validated: ${ticketedResult.result.validated}`)

// Recheck Available Tickets ------------------------------------------------
console.log('\nRechecking available tickets...')
const ticketsAfterResponse = await client.request({
  command: 'account_objects',
  account: wallet.address,
  type: 'ticket'
})
console.log(`Found ${ticketsAfterResponse.result.account_objects.length} Tickets`)

// Disconnect when done (If you omit this, Node.js won't end the process)
await client.disconnect()

After the transaction is validated, the Ticket is consumed and removed from the ledger. The available Ticket count drops by one.

Tip

You can use this same pattern to cancel an unused Ticket — just send a no-op AccountSet using the Ticket you no longer need.

With Multi-Signing

Reserve a Ticket for each multi-signed transaction to hold its slot while you collect signatures. Then submit each transaction as soon as its signatures are complete, in any order.

In this scenario, step 5: Use a Ticket becomes a multi-step process: prepare the transaction, circulate it among signers, and combine their signatures. See Send a Multi-Signed Transaction for more details.

For complete working examples that combine Tickets and multi-signing, see use-tickets-multisig.js (JavaScript) or use-tickets-to-multisign.py (Python) in the code samples directory. A Go variant isn't currently available.

You can prepare multiple multi-signed transactions simultaneously, each using a different Ticket.

Tip

For this scenario, omit the LastLedgerSequence field so that the transaction does not expire while you collect signatures. How you do this varies by library:

  • xrpl.js: Specify "LastLedgerSequence": null when auto-filling the transaction.
  • xrpl-py: Set last_ledger_sequence=None on the transaction.
  • xrpl-go: Leave the field unset before signing.
  • rippled directly: Omit the field from the prepared instructions. The server doesn't provide a default.

See Also