mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-17 10:15:50 +00:00
Compare commits
1 Commits
batch-tran
...
minor-get-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2fc296573 |
@@ -1,5 +1,4 @@
|
||||
# Batch
|
||||
|
||||
Code samples showing how to create and submit a [Batch transaction](https://xrpl.org/docs/concepts/transactions/batch-transactions).
|
||||
|
||||
Both for single and multi account batch transactions.
|
||||
Code samples showing how to create and submit a [Batch transaction](../../docs/concepts/transactions/batch-transactions.md).
|
||||
Both for simple and multi account batch transactions.
|
||||
|
||||
@@ -1,301 +0,0 @@
|
||||
# Send a Batch Transaction
|
||||
|
||||
Code samples showing how to create and submit a [Batch transaction](https://xrpl.org/docs/concepts/transactions/batch-transactions) with Javascript.
|
||||
|
||||
Both for single and multi account batch transactions.
|
||||
|
||||
## Single Account Batch Transaction
|
||||
|
||||
Quick setup and usage:
|
||||
|
||||
```sh
|
||||
npm install xrpl
|
||||
node singleAccountBatch.js
|
||||
```
|
||||
|
||||
The script should output the following:
|
||||
|
||||
```sh
|
||||
=== Funding new wallets from faucet... ===
|
||||
Sender: r3y1GdzaPVcaLUaTKvq1iqNzT9EjKLvnya, Balance: 100 XRP
|
||||
Wallet1: rw744uE8PveVqU2KGyFkUNW4qGYxeK2QZM, Balance: 100 XRP
|
||||
Wallet2: rhcxDdw7VFEPEFkWrZ3G6NSEKhWUXoaQNJ, Balance: 100 XRP
|
||||
|
||||
=== Creating batch transaction ===
|
||||
{
|
||||
"TransactionType": "Batch",
|
||||
"Account": "r3y1GdzaPVcaLUaTKvq1iqNzT9EjKLvnya",
|
||||
"Flags": 65536,
|
||||
"RawTransactions": [
|
||||
{
|
||||
"RawTransaction": {
|
||||
"TransactionType": "Payment",
|
||||
"Account": "r3y1GdzaPVcaLUaTKvq1iqNzT9EjKLvnya",
|
||||
"Destination": "rw744uE8PveVqU2KGyFkUNW4qGYxeK2QZM",
|
||||
"Amount": "2000000",
|
||||
"Flags": 1073741824
|
||||
}
|
||||
},
|
||||
{
|
||||
"RawTransaction": {
|
||||
"TransactionType": "Payment",
|
||||
"Account": "r3y1GdzaPVcaLUaTKvq1iqNzT9EjKLvnya",
|
||||
"Destination": "rhcxDdw7VFEPEFkWrZ3G6NSEKhWUXoaQNJ",
|
||||
"Amount": "5000000",
|
||||
"Flags": 1073741824
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
=== Submitting batch transaction ===
|
||||
|
||||
Batch transaction submitted successfully!
|
||||
Result:
|
||||
{
|
||||
"close_time_iso": "2025-11-14T17:46:50Z",
|
||||
"ctid": "C01205F300000002",
|
||||
"hash": "723254589441AA19ACE9B07FFEA161EDCD6DD58DFDF230FAECE1477CF71117C5",
|
||||
"ledger_hash": "24B4EDFC1A0B3F951A536950BA397A8EF49212C882A9268B878885EA8A285EE5",
|
||||
"ledger_index": 1181171,
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "r3y1GdzaPVcaLUaTKvq1iqNzT9EjKLvnya",
|
||||
"Balance": "99999996",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 0,
|
||||
"Sequence": 1181168
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "C9C50B88095FBD2D78D0D2693F1C38738AD108D3EE6AB5491547A5FCFE62A236",
|
||||
"PreviousFields": {
|
||||
"Balance": "100000000",
|
||||
"Sequence": 1181167
|
||||
},
|
||||
"PreviousTxnID": "C5FFDF7016A8102250F4F8CB12F964573A95FA7CC1706C072A4F244F1A81C3B3",
|
||||
"PreviousTxnLgrSeq": 1181167
|
||||
}
|
||||
}
|
||||
],
|
||||
"TransactionIndex": 0,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"tx_json": {
|
||||
"Account": "r3y1GdzaPVcaLUaTKvq1iqNzT9EjKLvnya",
|
||||
"Fee": "4",
|
||||
"Flags": 65536,
|
||||
"LastLedgerSequence": 1181189,
|
||||
"RawTransactions": [
|
||||
{
|
||||
"RawTransaction": {
|
||||
"Account": "r3y1GdzaPVcaLUaTKvq1iqNzT9EjKLvnya",
|
||||
"Amount": "2000000",
|
||||
"Destination": "rw744uE8PveVqU2KGyFkUNW4qGYxeK2QZM",
|
||||
"Fee": "0",
|
||||
"Flags": 1073741824,
|
||||
"Sequence": 1181168,
|
||||
"SigningPubKey": "",
|
||||
"TransactionType": "Payment"
|
||||
}
|
||||
},
|
||||
{
|
||||
"RawTransaction": {
|
||||
"Account": "r3y1GdzaPVcaLUaTKvq1iqNzT9EjKLvnya",
|
||||
"Amount": "5000000",
|
||||
"Destination": "rhcxDdw7VFEPEFkWrZ3G6NSEKhWUXoaQNJ",
|
||||
"Fee": "0",
|
||||
"Flags": 1073741824,
|
||||
"Sequence": 1181169,
|
||||
"SigningPubKey": "",
|
||||
"TransactionType": "Payment"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Sequence": 1181167,
|
||||
"SigningPubKey": "EDB16F0756C88AA0E541EFBB602B7992E6BA13CFB3E1BD3D699D4DB91BAD9043D0",
|
||||
"TransactionType": "Batch",
|
||||
"TxnSignature": "C141A9C5253C940D9B85847FF1F8BF1AB9D0B63707DD8BD06204BD58AC64F8019BC52F9D8D2B1B7D889CBF081211D0A4DCAFFC87D716D795B4FCE38F23F91008",
|
||||
"ctid": "C01205F300000002",
|
||||
"date": 816457610,
|
||||
"ledger_index": 1181171
|
||||
},
|
||||
"validated": true
|
||||
}
|
||||
|
||||
=== Verifying Inner Transactions ===
|
||||
|
||||
Transaction 1 Hash: 4CFD3BB085E09C70D22F6199CAEB4281C3D1DF0824E2AACA2E4463A2799F7FE7
|
||||
- Status: tesSUCCESS (Ledger 1181171)
|
||||
- Transaction URL: https://devnet.xrpl.org/transactions/4CFD3BB085E09C70D22F6199CAEB4281C3D1DF0824E2AACA2E4463A2799F7FE7
|
||||
|
||||
Transaction 2 Hash: 9B794797A80013977FCFCF44389807E08F1B2B2957E2F8EBE9D5F0F4209F7285
|
||||
- Status: tesSUCCESS (Ledger 1181171)
|
||||
- Transaction URL: https://devnet.xrpl.org/transactions/9B794797A80013977FCFCF44389807E08F1B2B2957E2F8EBE9D5F0F4209F7285
|
||||
|
||||
=== Final Balances ===
|
||||
Sender: r3y1GdzaPVcaLUaTKvq1iqNzT9EjKLvnya, Balance: 92.999996 XRP
|
||||
Wallet1: rw744uE8PveVqU2KGyFkUNW4qGYxeK2QZM, Balance: 102 XRP
|
||||
Wallet2: rhcxDdw7VFEPEFkWrZ3G6NSEKhWUXoaQNJ, Balance: 105 XRP
|
||||
|
||||
Batch Transaction URL:
|
||||
https://devnet.xrpl.org/transactions/723254589441AA19ACE9B07FFEA161EDCD6DD58DFDF230FAECE1477CF71117C5
|
||||
```
|
||||
|
||||
## Multi-Account Batch Transaction
|
||||
|
||||
```sh
|
||||
npm install xrpl
|
||||
node multiAccountBatch.js
|
||||
```
|
||||
|
||||
The script should output the following:
|
||||
|
||||
```sh
|
||||
=== Funding new wallets from faucet... ===
|
||||
Alice: r9quQTwuBWQC1SDjPA3CzXi3V6vcKdUUkU, Balance: 100 XRP
|
||||
Bob: rLegReLGMVh3b8acEu6NJ16GFYVSrq7DFt, Balance: 100 XRP
|
||||
Charlie: rEMtU7B5e7Q347HSWwaMiqTk2mJytBTMRT, Balance: 100 XRP
|
||||
Third-party wallet: rKeZvnQ6pusBV6u1TREqJESgQR2mfpb4G2, Balance: 100 XRP
|
||||
|
||||
=== Creating batch transaction ===
|
||||
{
|
||||
"TransactionType": "Batch",
|
||||
"Account": "rKeZvnQ6pusBV6u1TREqJESgQR2mfpb4G2",
|
||||
"Flags": 65536,
|
||||
"RawTransactions": [
|
||||
{
|
||||
"RawTransaction": {
|
||||
"TransactionType": "Payment",
|
||||
"Account": "rEMtU7B5e7Q347HSWwaMiqTk2mJytBTMRT",
|
||||
"Destination": "r9quQTwuBWQC1SDjPA3CzXi3V6vcKdUUkU",
|
||||
"Amount": "50000000",
|
||||
"Flags": 1073741824
|
||||
}
|
||||
},
|
||||
{
|
||||
"RawTransaction": {
|
||||
"TransactionType": "Payment",
|
||||
"Account": "rLegReLGMVh3b8acEu6NJ16GFYVSrq7DFt",
|
||||
"Destination": "r9quQTwuBWQC1SDjPA3CzXi3V6vcKdUUkU",
|
||||
"Amount": "50000000",
|
||||
"Flags": 1073741824
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
=== Submitting batch transaction ===
|
||||
|
||||
Batch transaction submitted successfully!
|
||||
Result:
|
||||
{
|
||||
"close_time_iso": "2025-11-14T17:47:52Z",
|
||||
"ctid": "C012060900000002",
|
||||
"hash": "C6EF3F55749ED51BCF33D657BCB37B8221B317E9ED9D55CA1CF9454BD54D697E",
|
||||
"ledger_hash": "19F9DB9DF2F3978C11B5853BAAF463E370C319E3F8DEFA19A0A7EED832CC5ACE",
|
||||
"ledger_index": 1181193,
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rKeZvnQ6pusBV6u1TREqJESgQR2mfpb4G2",
|
||||
"Balance": "99999994",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 0,
|
||||
"Sequence": 1181193
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "94CD9B687558DF03CC9110EC1A7CACADAEFC76AEA6C31FA784D00F979864D5AE",
|
||||
"PreviousFields": {
|
||||
"Balance": "100000000",
|
||||
"Sequence": 1181192
|
||||
},
|
||||
"PreviousTxnID": "5331D0494C42726FDF52F8F0C34A9BBE0BCAF6ABD45AF2A76CB00CF8B2B3A761",
|
||||
"PreviousTxnLgrSeq": 1181192
|
||||
}
|
||||
}
|
||||
],
|
||||
"TransactionIndex": 0,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"tx_json": {
|
||||
"Account": "rKeZvnQ6pusBV6u1TREqJESgQR2mfpb4G2",
|
||||
"BatchSigners": [
|
||||
{
|
||||
"BatchSigner": {
|
||||
"Account": "rEMtU7B5e7Q347HSWwaMiqTk2mJytBTMRT",
|
||||
"SigningPubKey": "EDA4DB81B1ABAF32E608731E3D0A867D8DA47C6500E6F1C7AB0E51FE93F619FFE3",
|
||||
"TxnSignature": "D84E96B16D51EB2E5959F55F046167013F625C33CEC99D19FEF934D02F0F8FC1906FAAE7413652A25B5724935E94B30B9F5C114E0AC77B8D8E61DAEDA96F6405"
|
||||
}
|
||||
},
|
||||
{
|
||||
"BatchSigner": {
|
||||
"Account": "rLegReLGMVh3b8acEu6NJ16GFYVSrq7DFt",
|
||||
"SigningPubKey": "ED9D4F21B59366032AE70C8FBA9BB58852A3455326E52F2A5CAFA4F045FA9AE3AB",
|
||||
"TxnSignature": "EBA9C89F9A7F2DC7B4E0F41351C50AEA500D203075F6D7662DA1605229F30A99080409A482F96DC1851A5A3E82895395509E640B6959798DB97445FEFB959009"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Fee": "6",
|
||||
"Flags": 65536,
|
||||
"LastLedgerSequence": 1181212,
|
||||
"RawTransactions": [
|
||||
{
|
||||
"RawTransaction": {
|
||||
"Account": "rEMtU7B5e7Q347HSWwaMiqTk2mJytBTMRT",
|
||||
"Amount": "50000000",
|
||||
"Destination": "r9quQTwuBWQC1SDjPA3CzXi3V6vcKdUUkU",
|
||||
"Fee": "0",
|
||||
"Flags": 1073741824,
|
||||
"Sequence": 1181191,
|
||||
"SigningPubKey": "",
|
||||
"TransactionType": "Payment"
|
||||
}
|
||||
},
|
||||
{
|
||||
"RawTransaction": {
|
||||
"Account": "rLegReLGMVh3b8acEu6NJ16GFYVSrq7DFt",
|
||||
"Amount": "50000000",
|
||||
"Destination": "r9quQTwuBWQC1SDjPA3CzXi3V6vcKdUUkU",
|
||||
"Fee": "0",
|
||||
"Flags": 1073741824,
|
||||
"Sequence": 1181190,
|
||||
"SigningPubKey": "",
|
||||
"TransactionType": "Payment"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Sequence": 1181192,
|
||||
"SigningPubKey": "ED447F3C2BFE7653F74FC02E4B6BF5CD42FFBA139B372A59D555957C8C2DB93DCD",
|
||||
"TransactionType": "Batch",
|
||||
"TxnSignature": "5FA929144AF5092CA033ED9938F7D01D177DE7D0DB3D1440138125610ED43533E72A00FF0D826899D2DE39CE901B6C9EF7D5322DF4D5C2415D5728E60AE97D0E",
|
||||
"ctid": "C012060900000002",
|
||||
"date": 816457672,
|
||||
"ledger_index": 1181193
|
||||
},
|
||||
"validated": true
|
||||
}
|
||||
|
||||
=== Verifying Inner Transactions ===
|
||||
|
||||
Transaction 1 Hash: 3E375463F8CCA03E9C4533DC91ED9F17D30E2968DB7D46053011DBB7F79E26DD
|
||||
- Status: tesSUCCESS (Ledger 1181193)
|
||||
- Transaction URL: https://devnet.xrpl.org/transactions/3E375463F8CCA03E9C4533DC91ED9F17D30E2968DB7D46053011DBB7F79E26DD
|
||||
|
||||
Transaction 2 Hash: BCBBC9B3A5912B496AB2BFF25DD45C634946832307BA284A53D6EBA81E68B8B4
|
||||
- Status: tesSUCCESS (Ledger 1181193)
|
||||
- Transaction URL: https://devnet.xrpl.org/transactions/BCBBC9B3A5912B496AB2BFF25DD45C634946832307BA284A53D6EBA81E68B8B4
|
||||
|
||||
=== Final Balances ===
|
||||
Alice: r9quQTwuBWQC1SDjPA3CzXi3V6vcKdUUkU, Balance: 200 XRP
|
||||
Bob: rLegReLGMVh3b8acEu6NJ16GFYVSrq7DFt, Balance: 50 XRP
|
||||
Charlie: rEMtU7B5e7Q347HSWwaMiqTk2mJytBTMRT, Balance: 50 XRP
|
||||
Third-party wallet: rKeZvnQ6pusBV6u1TREqJESgQR2mfpb4G2, Balance: 99.999994 XRP
|
||||
|
||||
Batch Transaction URL:
|
||||
https://devnet.xrpl.org/transactions/C6EF3F55749ED51BCF33D657BCB37B8221B317E9ED9D55CA1CF9454BD54D697E
|
||||
```
|
||||
@@ -1,132 +0,0 @@
|
||||
/**
|
||||
* XRP Ledger Batch Transactions Tutorial
|
||||
*
|
||||
* This tutorial demonstrates how to use the Batch transaction feature (XLS-56)
|
||||
* to perform a multi-account batch transaction.
|
||||
*/
|
||||
|
||||
import xrpl from "xrpl"
|
||||
import { BatchFlags } from 'xrpl/dist/npm/models/transactions/batch.js'
|
||||
import { GlobalFlags } from 'xrpl/dist/npm/models/transactions/common.js'
|
||||
import { signMultiBatch, combineBatchSigners } from 'xrpl/dist/npm/Wallet/batchSigner.js'
|
||||
|
||||
const client = new xrpl.Client("wss://s.devnet.rippletest.net:51233/")
|
||||
await client.connect()
|
||||
|
||||
// Create and fund wallets
|
||||
console.log("=== Funding new wallets from faucet... ===")
|
||||
const { wallet: alice } = await client.fundWallet()
|
||||
const { wallet: bob } = await client.fundWallet()
|
||||
const { wallet: charlie } = await client.fundWallet()
|
||||
const { wallet: thirdPartyWallet } = await client.fundWallet()
|
||||
|
||||
console.log(`Alice: ${alice.address}, Balance: ${await client.getXrpBalance(alice.address)} XRP`)
|
||||
console.log(`Bob: ${bob.address}, Balance: ${await client.getXrpBalance(bob.address)} XRP`)
|
||||
console.log(`Charlie: ${charlie.address}, Balance: ${await client.getXrpBalance(charlie.address)} XRP`)
|
||||
console.log(`Third-party wallet: ${thirdPartyWallet.address}, Balance: ${await client.getXrpBalance(thirdPartyWallet.address)} XRP`)
|
||||
|
||||
// Create inner transactions --------------------------------------------
|
||||
// REQUIRED: Inner transactions MUST have the tfInnerBatchTxn flag (0x40000000).
|
||||
// This marks them as part of a batch (allows Fee: 0 and empty SigningPubKey).
|
||||
|
||||
// Transaction 1: Charlie pays Alice
|
||||
const charliePayment = {
|
||||
TransactionType: "Payment",
|
||||
Account: charlie.address,
|
||||
Destination: alice.address,
|
||||
Amount: xrpl.xrpToDrops(50),
|
||||
Flags: GlobalFlags.tfInnerBatchTxn // THIS IS REQUIRED
|
||||
}
|
||||
|
||||
// Transaction 2: Bob pays Alice
|
||||
const bobPayment = {
|
||||
TransactionType: "Payment",
|
||||
Account: bob.address,
|
||||
Destination: alice.address,
|
||||
Amount: xrpl.xrpToDrops(50),
|
||||
Flags: GlobalFlags.tfInnerBatchTxn // THIS IS REQUIRED
|
||||
}
|
||||
|
||||
// Send Batch transaction --------------------------------------------
|
||||
console.log("\n=== Creating batch transaction ===")
|
||||
const batchTx = {
|
||||
TransactionType: "Batch",
|
||||
Account: thirdPartyWallet.address,
|
||||
Flags: BatchFlags.tfAllOrNothing, // tfAllOrNothing: All inner transactions must succeed
|
||||
// Must include a minimum of 2 transactions and a maximum of 8 transactions.
|
||||
RawTransactions: [
|
||||
{ RawTransaction: charliePayment },
|
||||
{ RawTransaction: bobPayment },
|
||||
]
|
||||
}
|
||||
console.log(JSON.stringify(batchTx, null, 2))
|
||||
|
||||
// Validate the transaction structure
|
||||
xrpl.validate(batchTx)
|
||||
|
||||
// Set the expected number of signers for this transaction.
|
||||
// "autofill" will automatically add Fee: "0" and SigningPubKey: "".
|
||||
const autofilledBatchTx = await client.autofill(batchTx, 2)
|
||||
|
||||
// Gather batch signatures --------------------------------
|
||||
// Each signer needs their own tx copy because signMultiBatch modifies the object.
|
||||
// Charlie signs the Batch transaction
|
||||
const charlieBatch = { ...autofilledBatchTx }
|
||||
signMultiBatch(charlie, charlieBatch)
|
||||
|
||||
// Bob signs the Batch transaction
|
||||
const bobBatch = { ...autofilledBatchTx }
|
||||
signMultiBatch(bob, bobBatch)
|
||||
|
||||
// Combine inner transaction signatures.
|
||||
// This returns a signed transaction blob (hex string) ready for submission.
|
||||
const combinedSignedTx = combineBatchSigners([charlieBatch, bobBatch])
|
||||
|
||||
// Submit the signed blob with the third-party's wallet
|
||||
console.log("\n=== Submitting batch transaction ===")
|
||||
const submitResponse = await client.submitAndWait(combinedSignedTx,
|
||||
{ wallet: thirdPartyWallet }
|
||||
)
|
||||
|
||||
// Check Batch transaction result --------------------------------
|
||||
if (submitResponse.result.meta.TransactionResult !== "tesSUCCESS") {
|
||||
const resultCode = submitResponse.result.meta.TransactionResult
|
||||
console.warn(`\nTransaction failed with result code ${resultCode}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log("\nBatch transaction submitted successfully!")
|
||||
console.log("Result:\n", JSON.stringify(submitResponse.result, null, 2))
|
||||
|
||||
// Calculate and verify inner transaction hashes --------------------------------------------
|
||||
console.log("\n=== Verifying Inner Transactions ===")
|
||||
|
||||
// Get the actual inner transactions from the batch response
|
||||
const rawTransactions = submitResponse.result.tx_json.RawTransactions
|
||||
|
||||
for (let i = 0; i < rawTransactions.length; i++) {
|
||||
const innerTx = rawTransactions[i].RawTransaction
|
||||
const hash = xrpl.hashes.hashSignedTx(xrpl.encode(innerTx))
|
||||
|
||||
console.log(`\nTransaction ${i + 1} Hash: ${hash}`)
|
||||
|
||||
try {
|
||||
const tx = await client.request({ command: 'tx', transaction: hash })
|
||||
console.log(` - Status: ${tx.result.meta?.TransactionResult} (Ledger ${tx.result.ledger_index})`)
|
||||
console.log(` - Transaction URL: https://devnet.xrpl.org/transactions/${hash}`)
|
||||
} catch (error) {
|
||||
console.log(`✗ Not found: ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify balances after transaction
|
||||
console.log("\n=== Final Balances ===")
|
||||
console.log(`Alice: ${alice.address}, Balance: ${await client.getXrpBalance(alice.address)} XRP`)
|
||||
console.log(`Bob: ${bob.address}, Balance: ${await client.getXrpBalance(bob.address)} XRP`)
|
||||
console.log(`Charlie: ${charlie.address}, Balance: ${await client.getXrpBalance(charlie.address)} XRP`)
|
||||
console.log(`Third-party wallet: ${thirdPartyWallet.address}, Balance: ${await client.getXrpBalance(thirdPartyWallet.address)} XRP`)
|
||||
|
||||
// View the transaction on the XRPL Explorer
|
||||
console.log(`\nBatch Transaction URL:\nhttps://devnet.xrpl.org/transactions/${submitResponse.result.hash}`)
|
||||
|
||||
await client.disconnect()
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"xrpl": "^4.4.2"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
/**
|
||||
* Single Account Batch Transaction Example
|
||||
*
|
||||
* This example demonstrates how to use the Batch transactions feature (XLS-56)
|
||||
* to create a single-account batch transaction that sends payments
|
||||
* to multiple destinations in one atomic operation.
|
||||
*/
|
||||
|
||||
import xrpl from "xrpl"
|
||||
import { BatchFlags } from 'xrpl/dist/npm/models/transactions/batch.js'
|
||||
import { GlobalFlags } from 'xrpl/dist/npm/models/transactions/common.js'
|
||||
|
||||
const client = new xrpl.Client("wss://s.devnet.rippletest.net:51233/")
|
||||
await client.connect()
|
||||
|
||||
// Create and fund wallets
|
||||
console.log("=== Funding new wallets from faucet... ===")
|
||||
const { wallet: sender } = await client.fundWallet()
|
||||
const { wallet: wallet1 } = await client.fundWallet()
|
||||
const { wallet: wallet2 } = await client.fundWallet()
|
||||
|
||||
console.log(`Sender: ${sender.address}, Balance: ${await client.getXrpBalance(sender.address)} XRP`)
|
||||
console.log(`Wallet1: ${wallet1.address}, Balance: ${await client.getXrpBalance(wallet1.address)} XRP`)
|
||||
console.log(`Wallet2: ${wallet2.address}, Balance: ${await client.getXrpBalance(wallet2.address)} XRP`)
|
||||
|
||||
// Create inner transactions --------------------------------------------
|
||||
// REQUIRED: Inner transactions MUST have the tfInnerBatchTxn flag (0x40000000).
|
||||
// This marks them as part of a batch (allows Fee: 0 and empty SigningPubKey).
|
||||
|
||||
// Transaction 1
|
||||
const payment1 = {
|
||||
TransactionType: "Payment",
|
||||
Account: sender.address,
|
||||
Destination: wallet1.address,
|
||||
Amount: xrpl.xrpToDrops(2),
|
||||
Flags: GlobalFlags.tfInnerBatchTxn // THIS IS REQUIRED
|
||||
}
|
||||
|
||||
// Transaction 2
|
||||
const payment2 = {
|
||||
TransactionType: "Payment",
|
||||
Account: sender.address,
|
||||
Destination: wallet2.address,
|
||||
Amount: xrpl.xrpToDrops(5),
|
||||
Flags: GlobalFlags.tfInnerBatchTxn // THIS IS REQUIRED
|
||||
}
|
||||
|
||||
// Send Batch transaction --------------------------------------------
|
||||
console.log("\n=== Creating batch transaction ===")
|
||||
const batchTx = {
|
||||
TransactionType: "Batch",
|
||||
Account: sender.address,
|
||||
Flags: BatchFlags.tfAllOrNothing, // tfAllOrNothing: All inner transactions must succeed
|
||||
// Must include a minimum of 2 transactions and a maximum of 8 transactions.
|
||||
RawTransactions: [
|
||||
{ RawTransaction: payment1 },
|
||||
{ RawTransaction: payment2 }
|
||||
]
|
||||
}
|
||||
console.log(JSON.stringify(batchTx, null, 2))
|
||||
|
||||
// Validate the transaction structure before submitting
|
||||
xrpl.validate(batchTx)
|
||||
|
||||
// Submit and wait for validation
|
||||
console.log("\n=== Submitting batch transaction ===")
|
||||
const submitResponse = await client.submitAndWait(batchTx, {
|
||||
wallet: sender,
|
||||
// "autofill" will automatically add Fee: "0" and SigningPubKey: "".
|
||||
autofill: true
|
||||
})
|
||||
|
||||
// Check Batch transaction result --------------------------------
|
||||
if (submitResponse.result.meta.TransactionResult !== "tesSUCCESS") {
|
||||
const resultCode = submitResponse.result.meta.TransactionResult
|
||||
console.warn(`\nTransaction failed with result code ${resultCode}`)
|
||||
process.exit(1)
|
||||
}
|
||||
console.log("\nBatch transaction submitted successfully!")
|
||||
console.log("Result:\n", JSON.stringify(submitResponse.result, null, 2))
|
||||
|
||||
// Calculate and verify inner transaction hashes --------------------------------------------
|
||||
console.log("\n=== Verifying Inner Transactions ===")
|
||||
|
||||
// Get the actual inner transactions from the batch response
|
||||
const rawTransactions = submitResponse.result.tx_json.RawTransactions
|
||||
|
||||
for (let i = 0; i < rawTransactions.length; i++) {
|
||||
const innerTx = rawTransactions[i].RawTransaction
|
||||
const hash = xrpl.hashes.hashSignedTx(xrpl.encode(innerTx))
|
||||
|
||||
console.log(`\nTransaction ${i + 1} Hash: ${hash}`)
|
||||
|
||||
try {
|
||||
const tx = await client.request({ command: 'tx', transaction: hash })
|
||||
console.log(` - Status: ${tx.result.meta?.TransactionResult} (Ledger ${tx.result.ledger_index})`)
|
||||
console.log(` - Transaction URL: https://devnet.xrpl.org/transactions/${hash}`)
|
||||
} catch (error) {
|
||||
console.log(`✗ Not found: ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify balances after transaction
|
||||
console.log("\n=== Final Balances ===")
|
||||
console.log(`Sender: ${sender.address}, Balance: ${await client.getXrpBalance(sender.address)} XRP`)
|
||||
console.log(`Wallet1: ${wallet1.address}, Balance: ${await client.getXrpBalance(wallet1.address)} XRP`)
|
||||
console.log(`Wallet2: ${wallet2.address}, Balance: ${await client.getXrpBalance(wallet2.address)} XRP`)
|
||||
|
||||
// View the batch transaction on the XRPL Explorer
|
||||
console.log(`\nBatch Transaction URL:\nhttps://devnet.xrpl.org/transactions/${submitResponse.result.hash}`)
|
||||
|
||||
await client.disconnect()
|
||||
@@ -1,7 +1,9 @@
|
||||
// @chunk {"steps": ["import-node-tag"]}
|
||||
// Import the library
|
||||
// @chunk {"steps": ["connect-tag"]}
|
||||
import xrpl from "xrpl"
|
||||
// @chunk-end
|
||||
|
||||
// @chunk {"steps": ["connect-tag"]}
|
||||
// Define the network client
|
||||
const SERVER_URL = "wss://s.altnet.rippletest.net:51233/"
|
||||
const client = new xrpl.Client(SERVER_URL)
|
||||
|
||||
@@ -121,12 +121,12 @@ In this example, two users are atomically swapping their tokens: XRP for GKO.
|
||||
| Field | JSON Type | [Internal Type][] | Required? | Description |
|
||||
|:------------------|:----------|:------------------|:----------|:------------|
|
||||
| `Flags` | Number | UInt32 | Yes | A bit-flag for this transaction. Exactly one must be specified to represent the batch mode of the transaction. See: [Batch Flags](#batch-flags). |
|
||||
| `RawTransactions` | Array | Array | Yes | The list of transactions to apply. See [RawTransactions](#rawtransactions). |
|
||||
| `RawTransactions` | Array | Array | Yes | The list of transactions to apply. |
|
||||
| `BatchSigners` | Array | Array | No | The signatures authorizing a multi-account `Batch` transaction. |
|
||||
|
||||
### RawTransactions
|
||||
|
||||
`RawTransactions` contains the list of inner transactions to be applied. There must be a minimum of **2** transactions and a maximum of **8** transactions. These transactions can come from one account or multiple accounts.
|
||||
`RawTransactions` contains the list of inner transactions to be applied. There can be up to 8 transactions included. These transactions can come from one account or multiple accounts.
|
||||
|
||||
Each inner transaction:
|
||||
|
||||
@@ -169,7 +169,6 @@ A transaction is considered successful if it receives a `tesSUCCESS` result.
|
||||
|
||||
| Error Code | Description |
|
||||
|:--------------------------|:--------------------------------------------------|
|
||||
| `temARRAY_EMPTY` | The batch transaction contains zero or one inner transaction. You must submit at least two inner transactions. |
|
||||
| `temINVALID_INNER_BATCH` | An inner transaction is malformed. |
|
||||
| `temSEQ_AND_TICKET` | The transaction contains both a `TicketSequence` field and a non-zero `Sequence` value. A transaction can't include both fields, but must have at least one. |
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
seo:
|
||||
description: Batch multiple transactions together and execute them as a single unit.
|
||||
metadata:
|
||||
indexPage: true
|
||||
labels:
|
||||
- Batch
|
||||
- Transactions
|
||||
---
|
||||
# Use Batch Transactions
|
||||
|
||||
Batch multiple transactions together and execute them as a single unit.
|
||||
|
||||
{% child-pages /%}
|
||||
@@ -1,172 +0,0 @@
|
||||
---
|
||||
seo:
|
||||
description: Send a Batch transaction containing transactions from multiple accounts.
|
||||
metadata:
|
||||
indexPage: true
|
||||
labels:
|
||||
- Batch
|
||||
- Transactions
|
||||
---
|
||||
# Send a Multi-Account Batch Transaction
|
||||
|
||||
This tutorial shows you how to create a [Batch transaction][] containing transactions from multiple accounts, where each account must sign the Batch transaction. Any account, even one not involved in the inner transactions, can submit the batch.
|
||||
|
||||
## Goals
|
||||
|
||||
By the end of this tutorial, you will be able to:
|
||||
|
||||
- Create a Batch transaction with multiple inner transactions, signed by multiple accounts, and submitted by a third party account.
|
||||
- Configure the Batch transaction to ensure atomicity, so that either all inner transactions succeed or they all fail.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To complete this tutorial, you should:
|
||||
|
||||
- Have a basic understanding of the XRP Ledger.
|
||||
- Have an XRP Ledger client library set up in your development environment. This page provides examples for the following:
|
||||
- **JavaScript** with the [xrpl.js library](https://github.com/XRPLF/xrpl.js). See [Get Started Using JavaScript](../../javascript/build-apps/get-started.md) for setup steps.
|
||||
|
||||
## Source Code
|
||||
|
||||
You can find the complete source code for this tutorial's examples in the [code samples section of this website's repository](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/batch/).
|
||||
|
||||
## Steps
|
||||
|
||||
The example in this tutorial demonstrates a scenario where Bob and Charlie both owe Alice 50 XRP each, and a third-party (such as a payment processor) submits the Batch transaction atomically to ensure Alice is paid by both parties.
|
||||
|
||||
### 1. Install dependencies
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
From the code sample folder, use npm to install dependencies:
|
||||
|
||||
```bash
|
||||
npm install xrpl
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 2. Set up client and accounts
|
||||
|
||||
To get started, import the client library and instantiate a client to connect to the XRPL. Then, create the accounts for Alice, Bob, Charlie, and the third-party.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/batch/js/multiAccountBatch.js" language="js" from="import xrpl" before="// Create inner transactions" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 3. Prepare inner transactions
|
||||
|
||||
Next, prepare the inner transactions that will be included in the batch.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/batch/js/multiAccountBatch.js" language="js" from="// Create inner transactions" to="// Send Batch transaction" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The first transaction sends a payment of 50 XRP from Charlie to Alice, and the second sends a payment of 50 XRP from Bob to Alice. Both transactions must include the `tfInnerBatchTxn` (0x40000000) flag to indicate that they are inner transactions of a batch.
|
||||
|
||||
Inner transactions must have a Fee of **0** and an empty string for the `SigningPubKey`. The outer Batch transaction handles the overall fee and signing for all inner transactions.
|
||||
|
||||
{% admonition type="info" name="Note" %}
|
||||
The `Fee` and `SigningPubKey` fields are omitted as the client library's _autofill_ functionality automatically populates these when submitting the Batch transaction.
|
||||
|
||||
You typically don't need to set these manually, but if you do, ensure `Fee` is set to 0 and `SigningPubKey` is an empty string.
|
||||
{% /admonition %}
|
||||
|
||||
### 4. Prepare Batch transaction
|
||||
|
||||
Create the Batch transaction and provide the inner transactions. The key fields to note are:
|
||||
|
||||
| Field | Value |
|
||||
|:---------------- |:---------- |
|
||||
| TransactionType | The type of transaction, in this case `Batch`.|
|
||||
| Account | The wallet address of the account that is sending the Batch transaction. |
|
||||
| Flags | The flags for the Batch transaction. For this example the transaction is configured with the `tfAllOrNothing` (0x00010000) flag to ensure that either all inner transactions succeed or they all fail atomically. See [Batch Flags](../../../references/protocol/transactions/types/batch.md#batch-flags) for other options. |
|
||||
| RawTransactions | Contains the list of inner transactions to be applied. Must include a minimum of **2** transactions and a maximum of **8** transactions. These transactions can come from one account or multiple accounts. |
|
||||
| BatchSigners | The list of signatures required for the Batch transaction. This is required because there are multiple accounts' transactions included in the batch. |
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/batch/js/multiAccountBatch.js" language="js" from="// Send Batch transaction" before="// Gather batch signatures" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Because we used `autofill`, the client library automatically fills in any missing fields, like `Fee` and `SigningPubKey`. Additionally, we specify the expected number of signers (2 in this case).
|
||||
|
||||
### 5. Gather batch signatures
|
||||
|
||||
To add the `BatchSigners` field, you need to collect signatures from each account that's sending a transaction within the batch. In this case we need two signatures, one from Charlie and one from Bob. Each sender must sign the Batch transaction to authorize their payment.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
The **xrpl.js** library provides a helper function, `signMultiBatch()`, to sign the Batch transaction for each account.
|
||||
|
||||
Then, to combine the signatures into a single signed Batch transaction, use the `combineBatchSigners()` utility function.
|
||||
{% code-snippet file="/_code-samples/batch/js/multiAccountBatch.js" language="js" from="// Gather batch signatures" to="// Submit" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 6. Submit Batch transaction
|
||||
|
||||
With all the required signatures gathered, the third-party wallet can now submit the Batch transaction.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/batch/js/multiAccountBatch.js" language="js" from="// Submit" before="// Check Batch transaction" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 7. Check Batch transaction result
|
||||
|
||||
To check the result of the Batch transaction submission:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/batch/js/multiAccountBatch.js" language="js" from="// Check Batch transaction" before="// Calculate and verify" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The code checks for a `tesSUCCESS` result and displays the response details.
|
||||
|
||||
{% admonition type="warning" name="Warning" %}
|
||||
A `tesSUCCESS` result indicates that the Batch transaction was processed successfully, but does not guarantee the inner transactions succeeded. For example, see the [following transaction on the XRPL Explorer](https://devnet.xrpl.org/transactions/20CFCE5CF75E93E6D1E9C1E42F8E8C8C4CB1786A65BE23D2EA77EAAB65A455C5/simple).
|
||||
{% /admonition %}
|
||||
|
||||
Because the Batch transaction is configured with a `tfAllOrNothing` flag, if any inner transaction fails, **all** inner transactions wil fail, and only the Batch transaction fee is deducted from the **third-party wallet**.
|
||||
|
||||
### 8. Verify inner transactions
|
||||
|
||||
Since there is no way to check the status of inner transactions, you can verify them by calculating their hashes and looking them up on the ledger:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/batch/js/multiAccountBatch.js" language="js" from="// Calculate and verify" before="// Verify balances after transaction" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The code extracts the actual inner transactions from the batch response, calculates the hash of each inner transaction and looks up each transaction on the ledger using its hash.
|
||||
|
||||
### 9. Verify balances
|
||||
|
||||
You can also verify that the inner transactions executed successfully by checking the account balances to confirm the expected changes.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/batch/js/multiAccountBatch.js" language="js" from="// Verify balances after transaction" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
## See Also
|
||||
|
||||
- **Concepts**:
|
||||
- [Batch Transactions](../../../concepts/transactions/batch-transactions.md)
|
||||
- **Tutorials**:
|
||||
- [Send a Single Account Batch Transaction](send-a-single-account-batch-transaction.md)
|
||||
- **References**:
|
||||
- [Batch Transaction][]
|
||||
|
||||
{% raw-partial file="/docs/_snippets/common-links.md" /%}
|
||||
@@ -1,162 +0,0 @@
|
||||
---
|
||||
seo:
|
||||
description: Send a Batch transaction from a single account.
|
||||
metadata:
|
||||
indexPage: true
|
||||
labels:
|
||||
- Batch
|
||||
- Transactions
|
||||
---
|
||||
# Send a Single Account Batch Transaction
|
||||
|
||||
A [Batch transaction][] allows you to group multiple transactions together and execute them as a single atomic operation.
|
||||
|
||||
This tutorial shows you how to create a Batch transaction where a single account submits multiple transactions that either all succeed together or all fail together.
|
||||
|
||||
## Goals
|
||||
|
||||
By the end of this tutorial, you will be able to:
|
||||
|
||||
- Create a Batch transaction with multiple inner transactions, signed and submitted by a single account.
|
||||
- Configure the Batch transaction to ensure atomicity, so that either all inner transactions succeed or they all fail.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To complete this tutorial, you should:
|
||||
|
||||
- Have a basic understanding of the XRP Ledger.
|
||||
- Have an XRP Ledger client library set up in your development environment. This page provides examples for the following:
|
||||
- **JavaScript** with the [xrpl.js library](https://github.com/XRPLF/xrpl.js). See [Get Started Using JavaScript](../../javascript/build-apps/get-started.md) for setup steps.
|
||||
|
||||
## Source Code
|
||||
|
||||
You can find the complete source code for this tutorial's examples in the [code samples section of this website's repository](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/batch/).
|
||||
|
||||
## Steps
|
||||
|
||||
The example in this tutorial demonstrates a scenario where an account sends multiple payments that must be processed atomically in one Batch transaction.
|
||||
|
||||
### 1. Install dependencies
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
From the code sample folder, use npm to install dependencies:
|
||||
|
||||
```bash
|
||||
npm install xrpl
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 2. Set up client and accounts
|
||||
|
||||
To get started, import the client library and instantiate a client to connect to the XRPL. For this tutorial you need a funded account for the Batch transaction **sender**, and two other accounts to **receive** the payments.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/batch/js/singleAccountBatch.js" language="js" from="import xrpl" before="// Create inner transactions" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 3. Prepare inner transactions
|
||||
|
||||
Next, prepare the inner transactions that will be included in the batch.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/batch/js/singleAccountBatch.js" language="js" from="// Create inner transactions" to="// Send Batch transaction" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The first transaction sends a payment of 2 XRP from the sender to `wallet1`, and the second transaction sends 5 XRP from the sender to `wallet2`. Both transactions must include the `tfInnerBatchTxn` (0x40000000) flag to indicate that they are inner transactions of a batch.
|
||||
|
||||
Inner transactions must have a Fee of **0** and an empty string for the `SigningPubKey`. The outer Batch transaction handles the overall fee and signing for all inner transactions.
|
||||
|
||||
{% admonition type="info" name="Note" %}
|
||||
The `Fee` and `SigningPubKey` fields are omitted as the client library's _autofill_ functionality automatically populates these when submitting the Batch transaction.
|
||||
|
||||
You typically don't need to set these manually, but if you do, ensure `Fee` is set to 0 and `SigningPubKey` is an empty string.
|
||||
{% /admonition %}
|
||||
|
||||
### 4. Prepare Batch transaction
|
||||
|
||||
Create the Batch transaction and provide the inner transactions. The key fields to note are:
|
||||
|
||||
| Field | Value |
|
||||
|:---------------- |:---------- |
|
||||
| TransactionType | The type of transaction, in this case `Batch`.|
|
||||
| Account | The wallet address of the account that is sending the Batch transaction. |
|
||||
| Flags | The flags for the Batch transaction. For this example the transaction is configured with the `tfAllOrNothing` (0x00010000) flag to ensure that either all inner transactions succeed or they all fail atomically. See [Batch Flags](../../../references/protocol/transactions/types/batch.md#batch-flags) for other options. |
|
||||
| RawTransactions | Contains the list of inner transactions to be applied. Must include a minimum of **2** transactions and a maximum of **8** transactions. These transactions can come from one account or multiple accounts. |
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/batch/js/singleAccountBatch.js" language="js" from="// Send Batch transaction" before="// Submit" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 5. Submit Batch transaction
|
||||
|
||||
Now the sender can submit the Batch transaction:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/batch/js/singleAccountBatch.js" language="js" from="// Submit" before="// Check Batch transaction" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Because `autofill` is set to `true`, the client library automatically fills in any missing fields, like the `Fee` and `SigningPubKey`, before submitting the batch.
|
||||
|
||||
### 6. Check Batch transaction result
|
||||
|
||||
To check the result of the Batch transaction submission:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/batch/js/singleAccountBatch.js" language="js" from="// Check Batch transaction" before="// Calculate and verify" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The code checks for a `tesSUCCESS` result and displays the response details.
|
||||
|
||||
{% admonition type="warning" name="Warning" %}
|
||||
A `tesSUCCESS` result indicates that the Batch transaction was processed successfully, but does not guarantee the inner transactions succeeded.
|
||||
|
||||
For example, see the [following transaction on the XRPL Explorer](https://devnet.xrpl.org/transactions/20CFCE5CF75E93E6D1E9C1E42F8E8C8C4CB1786A65BE23D2EA77EAAB65A455C5/simple).
|
||||
{% /admonition %}
|
||||
|
||||
Because the Batch transaction is configured with a `tfAllOrNothing` flag, if any inner transaction fails, **all** inner transactions wil fail, and only the Batch transaction fee is deducted from the **third-party wallet**.
|
||||
|
||||
### 7. Verify inner transactions
|
||||
|
||||
Since there is no way to check the status of inner transactions, you can verify them by calculating their hashes and looking them up on the ledger:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/batch/js/singleAccountBatch.js" language="js" from="// Calculate and verify" before="// Verify balances after transaction" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The code extracts the actual inner transactions from the batch response, calculates the hash of each inner transaction and looks up each transaction on the ledger using its hash.
|
||||
|
||||
### 8. Verify balances
|
||||
|
||||
You can also verify that the inner transactions executed successfully by checking the account balances to confirm the expected changes.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/batch/js/singleAccountBatch.js" language="js" from="// Verify balances after transaction" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
## See Also
|
||||
|
||||
- **Concepts**:
|
||||
- [Batch Transactions](../../../concepts/transactions/batch-transactions.md)
|
||||
- **Tutorials**:
|
||||
- [Send a Multi-Account Batch Transaction](send-a-multi-account-batch-transaction.md)
|
||||
- **References**:
|
||||
- [Batch Transaction][]
|
||||
|
||||
{% raw-partial file="/docs/_snippets/common-links.md" /%}
|
||||
@@ -62,10 +62,10 @@ Click **Download** on the top right of the code preview panel to download the so
|
||||
|
||||
Follow the steps to create a simple application with `xrpl.js`.
|
||||
|
||||
### 1. Install Dependencies
|
||||
|
||||
<!-- Web steps -->
|
||||
{% step id="import-web-tag" when={ "environment": "Web" } %}
|
||||
### 1. Install Dependencies
|
||||
|
||||
To load `xrpl.js` into your project, add a `<script>` tag to your HTML.
|
||||
|
||||
You can load the library from a CDN as in the example, or download a release and host it on your own website.
|
||||
@@ -74,7 +74,8 @@ This loads the module into the top level as `xrpl`.
|
||||
{% /step %}
|
||||
|
||||
<!-- Node.js steps -->
|
||||
{% step id="install-node-tag" when={ "environment": "Node" } %}
|
||||
{% step id="import-node-tag" when={ "environment": "Node" } %}
|
||||
### 1. Install Dependencies
|
||||
|
||||
Start a new project by creating an empty folder, then move into that folder and use [NPM](https://www.npmjs.com/) to install the latest version of xrpl.js:
|
||||
|
||||
@@ -145,31 +146,32 @@ If you want to generate a wallet without funding it, you can create a new `Walle
|
||||
To use an existing wallet seed encoded in [base58][], you can create a `Wallet` instance from it.
|
||||
{% /step %}
|
||||
|
||||
{% step id="query-xrpl-tag" %}
|
||||
### 4. Query the XRP Ledger
|
||||
|
||||
{% step id="query-xrpl-tag" %}
|
||||
Use the Client's `request()` method to access the XRP Ledger's [WebSocket API](../../../references/http-websocket-apis/api-conventions/request-formatting.md).
|
||||
{% /step %}
|
||||
|
||||
{% step id="listen-for-events-tag" %}
|
||||
### 5. Listen for Events
|
||||
|
||||
{% step id="listen-for-events-tag" %}
|
||||
You can set up handlers for various types of events in `xrpl.js`, such as whenever the XRP Ledger's [consensus process](../../../concepts/consensus-protocol/index.md) produces a new [ledger version](../../../concepts/ledgers/index.md). To do that, first call the [subscribe method][] to get the type of events you want, then attach an event handler using the `on(eventType, callback)` method of the client.
|
||||
{% /step %}
|
||||
|
||||
{% step id="disconnect-node-tag" when={ "environment": "Node" } %}
|
||||
### 6. Disconnect
|
||||
|
||||
{% step id="disconnect-node-tag" when={ "environment": "Node" } %}
|
||||
Disconnect when done so Node.js can end the process. The example code waits 10 seconds before disconnecting to allow time for the ledger event listener to receive and display events.
|
||||
{% /step %}
|
||||
|
||||
{% step id="disconnect-web-tag" when={ "environment": "Web" } %}
|
||||
### 6. Disconnect
|
||||
Disconnect from the ledger when done. The example code waits 10 seconds before disconnecting to allow time for the ledger event listener to receive and display events.
|
||||
{% /step %}
|
||||
|
||||
{% step id="run-app-node-tag" when={ "environment": "Node" } %}
|
||||
### 7. Run the Application
|
||||
|
||||
{% step id="run-app-node-tag" when={ "environment": "Node" } %}
|
||||
Finally, in your terminal, run the application like so:
|
||||
|
||||
```sh
|
||||
|
||||
@@ -295,11 +295,6 @@
|
||||
- page: docs/tutorials/how-tos/manage-account-settings/require-destination-tags.md
|
||||
- page: docs/tutorials/how-tos/manage-account-settings/offline-account-setup.md
|
||||
- page: docs/tutorials/how-tos/manage-account-settings/use-tickets.md
|
||||
- page: docs/tutorials/how-tos/use-batch-transactions/index.md
|
||||
expanded: false
|
||||
items:
|
||||
- page: docs/tutorials/how-tos/use-batch-transactions/send-a-single-account-batch-transaction.md
|
||||
- page: docs/tutorials/how-tos/use-batch-transactions/send-a-multi-account-batch-transaction.md
|
||||
- page: docs/tutorials/how-tos/use-specialized-payment-types/index.md
|
||||
expanded: false
|
||||
items:
|
||||
|
||||
Reference in New Issue
Block a user