mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-22 12:45:50 +00:00
Calculate inner transaction hash to verify success
This commit is contained in:
@@ -16,22 +16,22 @@ node singleAccountBatch.js
|
||||
The script should output the following:
|
||||
|
||||
```sh
|
||||
Funding new wallets from faucet...
|
||||
Sender: raNwujquxJ7QTLhfbkKN6sZa7RBPHV671e, Balance: 100 XRP
|
||||
Wallet1: r4JMmKToZRMVT3mGWPnKHFEHsSMQEWigLC, Balance: 100 XRP
|
||||
Wallet2: rKfPgHASYuttoF1HfU56V31WbJvZn3w8xn, Balance: 100 XRP
|
||||
=== Funding new wallets from faucet... ===
|
||||
Sender: rP9EsVosrmx2HyrmLgWJpJacX5ZrVVQsim, Balance: 100 XRP
|
||||
Wallet1: rGx6SACvYEvX8SRrvTPD91UhBmJ16pxL94, Balance: 100 XRP
|
||||
Wallet2: r3qetgSfAtyCpGc4rvKNz4LX3F3urMSJJy, Balance: 100 XRP
|
||||
|
||||
Creating batch transaction:
|
||||
=== Creating Batch transaction... ===
|
||||
{
|
||||
"TransactionType": "Batch",
|
||||
"Account": "raNwujquxJ7QTLhfbkKN6sZa7RBPHV671e",
|
||||
"Account": "rP9EsVosrmx2HyrmLgWJpJacX5ZrVVQsim",
|
||||
"Flags": 65536,
|
||||
"RawTransactions": [
|
||||
{
|
||||
"RawTransaction": {
|
||||
"TransactionType": "Payment",
|
||||
"Account": "raNwujquxJ7QTLhfbkKN6sZa7RBPHV671e",
|
||||
"Destination": "r4JMmKToZRMVT3mGWPnKHFEHsSMQEWigLC",
|
||||
"Account": "rP9EsVosrmx2HyrmLgWJpJacX5ZrVVQsim",
|
||||
"Destination": "rGx6SACvYEvX8SRrvTPD91UhBmJ16pxL94",
|
||||
"Amount": "2000000",
|
||||
"Flags": 1073741824
|
||||
}
|
||||
@@ -39,8 +39,8 @@ Creating batch transaction:
|
||||
{
|
||||
"RawTransaction": {
|
||||
"TransactionType": "Payment",
|
||||
"Account": "raNwujquxJ7QTLhfbkKN6sZa7RBPHV671e",
|
||||
"Destination": "rKfPgHASYuttoF1HfU56V31WbJvZn3w8xn",
|
||||
"Account": "rP9EsVosrmx2HyrmLgWJpJacX5ZrVVQsim",
|
||||
"Destination": "r3qetgSfAtyCpGc4rvKNz4LX3F3urMSJJy",
|
||||
"Amount": "5000000",
|
||||
"Flags": 1073741824
|
||||
}
|
||||
@@ -48,90 +48,100 @@ Creating batch transaction:
|
||||
]
|
||||
}
|
||||
|
||||
Submitting batch transaction...
|
||||
=== Submitting Batch transaction... ===
|
||||
|
||||
Batch transaction submitted successfully!
|
||||
Result:
|
||||
{
|
||||
"close_time_iso": "2025-11-03T14:16:21Z",
|
||||
"ctid": "C00D458B00020002",
|
||||
"hash": "A93D3C2BDB5D600E592B64B84E66D789237D029267129EBC659EE483E532DD95",
|
||||
"ledger_hash": "BE6B7C12E551305F09E942D6FA3FC8546F024AE5C53FC495DA6ABF78461E7019",
|
||||
"ledger_index": 869771,
|
||||
"close_time_iso": "2025-11-17T12:04:50Z",
|
||||
"ctid": "C013313800030002",
|
||||
"hash": "AE118213B0A183528418ABC5F14E3BFD6524020C5DB1C060157A0D3FDE15B900",
|
||||
"ledger_hash": "621183809B68A794371C5EC6522105FF04E502C48EBDC8171B80224991E33394",
|
||||
"ledger_index": 1257784,
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "raNwujquxJ7QTLhfbkKN6sZa7RBPHV671e",
|
||||
"Account": "rP9EsVosrmx2HyrmLgWJpJacX5ZrVVQsim",
|
||||
"Balance": "99999996",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 0,
|
||||
"Sequence": 869767
|
||||
"Sequence": 1257779
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "6238B6901FEBD1492C03546C7965A01F184C4E37B696304B86F78F4ADB7831B1",
|
||||
"LedgerIndex": "42CC98AF0A28EDDDC7E359B5622CC5748BDE2A93E124AF5C32647ECA8F68D480",
|
||||
"PreviousFields": {
|
||||
"Balance": "100000000",
|
||||
"Sequence": 869766
|
||||
"Sequence": 1257778
|
||||
},
|
||||
"PreviousTxnID": "559F102041D84FF9DA17483355C3C96A0F8923D9C9C7971BBB15C972DD1F37D6",
|
||||
"PreviousTxnLgrSeq": 869766
|
||||
"PreviousTxnID": "081C42DAE12001735AC4E9A7F027636DF612DB17B4BFA2333F4DB8EA0C9D1E9F",
|
||||
"PreviousTxnLgrSeq": 1257778
|
||||
}
|
||||
}
|
||||
],
|
||||
"TransactionIndex": 2,
|
||||
"TransactionIndex": 3,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"tx_json": {
|
||||
"Account": "raNwujquxJ7QTLhfbkKN6sZa7RBPHV671e",
|
||||
"Account": "rP9EsVosrmx2HyrmLgWJpJacX5ZrVVQsim",
|
||||
"Fee": "4",
|
||||
"Flags": 65536,
|
||||
"LastLedgerSequence": 869789,
|
||||
"LastLedgerSequence": 1257802,
|
||||
"RawTransactions": [
|
||||
{
|
||||
"RawTransaction": {
|
||||
"Account": "raNwujquxJ7QTLhfbkKN6sZa7RBPHV671e",
|
||||
"Account": "rP9EsVosrmx2HyrmLgWJpJacX5ZrVVQsim",
|
||||
"Amount": "2000000",
|
||||
"Destination": "r4JMmKToZRMVT3mGWPnKHFEHsSMQEWigLC",
|
||||
"Destination": "rGx6SACvYEvX8SRrvTPD91UhBmJ16pxL94",
|
||||
"Fee": "0",
|
||||
"Flags": 1073741824,
|
||||
"Sequence": 869767,
|
||||
"Sequence": 1257779,
|
||||
"SigningPubKey": "",
|
||||
"TransactionType": "Payment"
|
||||
}
|
||||
},
|
||||
{
|
||||
"RawTransaction": {
|
||||
"Account": "raNwujquxJ7QTLhfbkKN6sZa7RBPHV671e",
|
||||
"Account": "rP9EsVosrmx2HyrmLgWJpJacX5ZrVVQsim",
|
||||
"Amount": "5000000",
|
||||
"Destination": "rKfPgHASYuttoF1HfU56V31WbJvZn3w8xn",
|
||||
"Destination": "r3qetgSfAtyCpGc4rvKNz4LX3F3urMSJJy",
|
||||
"Fee": "0",
|
||||
"Flags": 1073741824,
|
||||
"Sequence": 869768,
|
||||
"Sequence": 1257780,
|
||||
"SigningPubKey": "",
|
||||
"TransactionType": "Payment"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Sequence": 869766,
|
||||
"SigningPubKey": "EDFECFB87A29F93E52BBA0BA5A14A59B520BB0E39F33943A2FDC1101D34349270D",
|
||||
"Sequence": 1257778,
|
||||
"SigningPubKey": "ED7031CA5BA4EC745610AB495F5053F318C119E87567BE485A494773AD8ED4FBCE",
|
||||
"TransactionType": "Batch",
|
||||
"TxnSignature": "E08E300BDE1700C7CC27F3DA9B784907F637518E1C7E0978E57BFE5D1511A3B6A4269235FC2D9EAA550182A5F2B59415A442CE59555B9B9A0A79AB4030C9F701",
|
||||
"ctid": "C00D458B00020002",
|
||||
"date": 815494581,
|
||||
"ledger_index": 869771
|
||||
"TxnSignature": "0610A277086943BC462C1A5F85BEB667B62B4BDA59525138B6014101C08297897A73D3D2D247CB37A06E1EA36267C53A51C0FDF32F3D8E974029BEDC41105B07",
|
||||
"ctid": "C013313800030002",
|
||||
"date": 816696290,
|
||||
"ledger_index": 1257784
|
||||
},
|
||||
"validated": true
|
||||
}
|
||||
|
||||
Final balances after batch transaction:
|
||||
Sender: raNwujquxJ7QTLhfbkKN6sZa7RBPHV671e, Balance: 92.999996 XRP
|
||||
Wallet1: r4JMmKToZRMVT3mGWPnKHFEHsSMQEWigLC, Balance: 102 XRP
|
||||
Wallet2: rKfPgHASYuttoF1HfU56V31WbJvZn3w8xn, Balance: 105 XRP
|
||||
Batch transaction URL:
|
||||
https://devnet.xrpl.org/transactions/AE118213B0A183528418ABC5F14E3BFD6524020C5DB1C060157A0D3FDE15B900
|
||||
|
||||
Transaction URL:
|
||||
https://devnet.xrpl.org/transactions/A93D3C2BDB5D600E592B64B84E66D789237D029267129EBC659EE483E532DD95
|
||||
=== Verifying inner transactions... ===
|
||||
|
||||
Transaction 1 hash: D18EA54D5653BBB5C87F116978822EAB7A26EDFB1D6C41910F36D7484D4890E3
|
||||
- Status: tesSUCCESS (Ledger 1257784)
|
||||
- Transaction URL: https://devnet.xrpl.org/transactions/D18EA54D5653BBB5C87F116978822EAB7A26EDFB1D6C41910F36D7484D4890E3
|
||||
|
||||
Transaction 2 hash: 5660DB400F08EE5543C54D4D65824A2142F9D5AC17294A4ABF654260F129B44E
|
||||
- Status: tesSUCCESS (Ledger 1257784)
|
||||
- Transaction URL: https://devnet.xrpl.org/transactions/5660DB400F08EE5543C54D4D65824A2142F9D5AC17294A4ABF654260F129B44E
|
||||
|
||||
=== Final balances ===
|
||||
Sender: rP9EsVosrmx2HyrmLgWJpJacX5ZrVVQsim, Balance: 92.999996 XRP
|
||||
Wallet1: rGx6SACvYEvX8SRrvTPD91UhBmJ16pxL94, Balance: 102 XRP
|
||||
Wallet2: r3qetgSfAtyCpGc4rvKNz4LX3F3urMSJJy, Balance: 105 XRP
|
||||
```
|
||||
|
||||
## Multi-Account Batch Transaction
|
||||
@@ -144,23 +154,23 @@ node multiAccountBatch.js
|
||||
The script should output the following:
|
||||
|
||||
```sh
|
||||
Funding new wallets from faucet...
|
||||
Alice: rfCBfRGpcGJLwdbfz1M6HYoAL8nZyHRHHa, Balance: 100 XRP
|
||||
Bob: rKPUDuS2jQNpAMhkNncqC9rKJDpL2gXDN7, Balance: 100 XRP
|
||||
Charlie: rnz3Da7phfR6tgTZoPYF5psYTiHTshTB8K, Balance: 100 XRP
|
||||
Third-party wallet: rU8LsCmVjSdf7hSmiGBtBDtt2WhHxp7Zpc, Balance: 100 XRP
|
||||
=== Funding new wallets from faucet... ===
|
||||
Alice: rHpve1GL2ZXUs3NB5iU91BrXBSwb5PbBrG, Balance: 100 XRP
|
||||
Bob: r3ruQ92bqXwWxcR2w4cC1tW35og9h3UbBq, Balance: 100 XRP
|
||||
Charlie: rsi5D9bkczpbGykPxoGNBVVmFFFXGwm3QA, Balance: 100 XRP
|
||||
Third-party wallet: rfUpGXTzU3siTr4UovV6Wt86Vw3gQU4ttA, Balance: 100 XRP
|
||||
|
||||
Creating batch transaction:
|
||||
=== Creating Batch transaction... ===
|
||||
{
|
||||
"TransactionType": "Batch",
|
||||
"Account": "rU8LsCmVjSdf7hSmiGBtBDtt2WhHxp7Zpc",
|
||||
"Account": "rfUpGXTzU3siTr4UovV6Wt86Vw3gQU4ttA",
|
||||
"Flags": 65536,
|
||||
"RawTransactions": [
|
||||
{
|
||||
"RawTransaction": {
|
||||
"TransactionType": "Payment",
|
||||
"Account": "rnz3Da7phfR6tgTZoPYF5psYTiHTshTB8K",
|
||||
"Destination": "rfCBfRGpcGJLwdbfz1M6HYoAL8nZyHRHHa",
|
||||
"Account": "rsi5D9bkczpbGykPxoGNBVVmFFFXGwm3QA",
|
||||
"Destination": "rHpve1GL2ZXUs3NB5iU91BrXBSwb5PbBrG",
|
||||
"Amount": "50000000",
|
||||
"Flags": 1073741824
|
||||
}
|
||||
@@ -168,8 +178,8 @@ Creating batch transaction:
|
||||
{
|
||||
"RawTransaction": {
|
||||
"TransactionType": "Payment",
|
||||
"Account": "rKPUDuS2jQNpAMhkNncqC9rKJDpL2gXDN7",
|
||||
"Destination": "rfCBfRGpcGJLwdbfz1M6HYoAL8nZyHRHHa",
|
||||
"Account": "r3ruQ92bqXwWxcR2w4cC1tW35og9h3UbBq",
|
||||
"Destination": "rHpve1GL2ZXUs3NB5iU91BrXBSwb5PbBrG",
|
||||
"Amount": "50000000",
|
||||
"Flags": 1073741824
|
||||
}
|
||||
@@ -177,35 +187,35 @@ Creating batch transaction:
|
||||
]
|
||||
}
|
||||
|
||||
Submitting batch transaction...
|
||||
=== Submitting Batch transaction... ===
|
||||
|
||||
Batch transaction submitted successfully!
|
||||
Result:
|
||||
{
|
||||
"close_time_iso": "2025-11-03T14:15:00Z",
|
||||
"ctid": "C00D457000000002",
|
||||
"hash": "8CBCCD88B8ABC248797B84ABB92066961C1CB5FE75ACE2115ADCA6B74C85993A",
|
||||
"ledger_hash": "2217A0DBB38B870187B412533B939724095359A050B21E071A2A114BF57CFB60",
|
||||
"ledger_index": 869744,
|
||||
"close_time_iso": "2025-11-17T12:08:31Z",
|
||||
"ctid": "C013317600000002",
|
||||
"hash": "1299D20C6B489DA5C632AE4DBE49475DBF42D9444C7E9C109CC9B8DD0FD55FEC",
|
||||
"ledger_hash": "E45ECF69057084CD02BA49A17E4D0C9154D33A98BB3C95A11B2EB9BE18F32C9B",
|
||||
"ledger_index": 1257846,
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rU8LsCmVjSdf7hSmiGBtBDtt2WhHxp7Zpc",
|
||||
"Account": "rfUpGXTzU3siTr4UovV6Wt86Vw3gQU4ttA",
|
||||
"Balance": "99999994",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 0,
|
||||
"Sequence": 869743
|
||||
"Sequence": 1257845
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "1E9BA043B9C6518582D0FF73A08DCD8B6958195735086CF7295E5EB6433FB453",
|
||||
"LedgerIndex": "2D9E0A02007241C38A8DF679E7E62AA0B273E8B12A5430B7B9D99300424F0E1F",
|
||||
"PreviousFields": {
|
||||
"Balance": "100000000",
|
||||
"Sequence": 869742
|
||||
"Sequence": 1257844
|
||||
},
|
||||
"PreviousTxnID": "F7019BC55D80438FDDB01C2549CCC3F7DAF9791F8645E0269D63979EAEC5BBA6",
|
||||
"PreviousTxnLgrSeq": 869742
|
||||
"PreviousTxnID": "3153DE8DE922538A6BE54AA8F783CAD4B848A321AFF028D3E6DD0E80C4B9C237",
|
||||
"PreviousTxnLgrSeq": 1257844
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -213,69 +223,79 @@ Result:
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"tx_json": {
|
||||
"Account": "rU8LsCmVjSdf7hSmiGBtBDtt2WhHxp7Zpc",
|
||||
"Account": "rfUpGXTzU3siTr4UovV6Wt86Vw3gQU4ttA",
|
||||
"BatchSigners": [
|
||||
{
|
||||
"BatchSigner": {
|
||||
"Account": "rnz3Da7phfR6tgTZoPYF5psYTiHTshTB8K",
|
||||
"SigningPubKey": "EDC566D7DA8186BBD30DDAE1FB770FCE7F248949194E1A2E70B18CFA060B140B59",
|
||||
"TxnSignature": "31639BFA1359DD24345776EAEEACCF61C1CDC792988679263D113E80A22D837E20ACD2B25E482FCA769990C004D747836370C6BAD14524559639BBEBA5813002"
|
||||
"Account": "rsi5D9bkczpbGykPxoGNBVVmFFFXGwm3QA",
|
||||
"SigningPubKey": "EDEB88C2868BD25BF03DB26050E16579FA6F8F9E3FF3172E0DC3DCBDA5408572EB",
|
||||
"TxnSignature": "9508568084596147CFDCFC18A62DC298A78AD1148BA4B0EB99BEE1CD37E5555FE3930810790D5708F9739B0E3F79772012C154CA33C2280BDD5B72473C17A607"
|
||||
}
|
||||
},
|
||||
{
|
||||
"BatchSigner": {
|
||||
"Account": "rKPUDuS2jQNpAMhkNncqC9rKJDpL2gXDN7",
|
||||
"SigningPubKey": "EDEF1966B325000407940E4C0792E3CCC3E27F51D132BDC53DCC2B1998E7C32A34",
|
||||
"TxnSignature": "6BF9860B0E2E134FB302329D711BAA7B6314395D39523982DBBC037E84FB17AB5E8E736DB3DB0019B4477686AF2D91E5D2B49409698A95219376B2E318D3E501"
|
||||
"Account": "r3ruQ92bqXwWxcR2w4cC1tW35og9h3UbBq",
|
||||
"SigningPubKey": "ED82F98DA6A3FC3E88D2EE3A5469D92C7070513BEF4DEE75CAB0BDAA81E8AE378D",
|
||||
"TxnSignature": "A482C8747F79857530474F1677599766C0BE283CB7E2A05AACF76E61BECCA16DCE3802D2D8244FBF4546A1C0E5EB70691255E3EFD2F8AC80B55357BDAB9ACD05"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Fee": "6",
|
||||
"Flags": 65536,
|
||||
"LastLedgerSequence": 869762,
|
||||
"LastLedgerSequence": 1257864,
|
||||
"RawTransactions": [
|
||||
{
|
||||
"RawTransaction": {
|
||||
"Account": "rnz3Da7phfR6tgTZoPYF5psYTiHTshTB8K",
|
||||
"Account": "rsi5D9bkczpbGykPxoGNBVVmFFFXGwm3QA",
|
||||
"Amount": "50000000",
|
||||
"Destination": "rfCBfRGpcGJLwdbfz1M6HYoAL8nZyHRHHa",
|
||||
"Destination": "rHpve1GL2ZXUs3NB5iU91BrXBSwb5PbBrG",
|
||||
"Fee": "0",
|
||||
"Flags": 1073741824,
|
||||
"Sequence": 869740,
|
||||
"Sequence": 1257842,
|
||||
"SigningPubKey": "",
|
||||
"TransactionType": "Payment"
|
||||
}
|
||||
},
|
||||
{
|
||||
"RawTransaction": {
|
||||
"Account": "rKPUDuS2jQNpAMhkNncqC9rKJDpL2gXDN7",
|
||||
"Account": "r3ruQ92bqXwWxcR2w4cC1tW35og9h3UbBq",
|
||||
"Amount": "50000000",
|
||||
"Destination": "rfCBfRGpcGJLwdbfz1M6HYoAL8nZyHRHHa",
|
||||
"Destination": "rHpve1GL2ZXUs3NB5iU91BrXBSwb5PbBrG",
|
||||
"Fee": "0",
|
||||
"Flags": 1073741824,
|
||||
"Sequence": 869738,
|
||||
"Sequence": 1257841,
|
||||
"SigningPubKey": "",
|
||||
"TransactionType": "Payment"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Sequence": 869742,
|
||||
"SigningPubKey": "ED2B56D6FB4E8C236A6B07E8D8AD9A4938606144E31779918F99525CA6B3C56664",
|
||||
"Sequence": 1257844,
|
||||
"SigningPubKey": "ED22A32B61EDF083315515831723BC18F8311F03886BBA375DFF46335BB7A75F0B",
|
||||
"TransactionType": "Batch",
|
||||
"TxnSignature": "9C51C1F2CB0E8BCEA1FADD3992249DE72AC46FC86AB2FB023A597FBD5C4CCB3337967E9AAFFB5F1C0CBC91128F3FD194F78F207E461BE1FF906C496B94EC410E",
|
||||
"ctid": "C00D457000000002",
|
||||
"date": 815494500,
|
||||
"ledger_index": 869744
|
||||
"TxnSignature": "156791D2DBFAEFC9B0AC29F2D8D0CDB25E13F92E70E6D5414FE31BD8573CA23D3F62F8B34FC1F117BD556B25E4F748095A24C4342108AB32F1B2BAFBF1443501",
|
||||
"ctid": "C013317600000002",
|
||||
"date": 816696511,
|
||||
"ledger_index": 1257846
|
||||
},
|
||||
"validated": true
|
||||
}
|
||||
|
||||
Final balances after batch transaction:
|
||||
Alice: rfCBfRGpcGJLwdbfz1M6HYoAL8nZyHRHHa, Balance: 200 XRP
|
||||
Bob: rKPUDuS2jQNpAMhkNncqC9rKJDpL2gXDN7, Balance: 50 XRP
|
||||
Charlie: rnz3Da7phfR6tgTZoPYF5psYTiHTshTB8K, Balance: 50 XRP
|
||||
Third-party wallet: rU8LsCmVjSdf7hSmiGBtBDtt2WhHxp7Zpc, Balance: 99.999994 XRP
|
||||
Batch transaction URL:
|
||||
https://devnet.xrpl.org/transactions/1299D20C6B489DA5C632AE4DBE49475DBF42D9444C7E9C109CC9B8DD0FD55FEC
|
||||
|
||||
Transaction URL:
|
||||
https://devnet.xrpl.org/transactions/8CBCCD88B8ABC248797B84ABB92066961C1CB5FE75ACE2115ADCA6B74C85993A
|
||||
=== Verifying inner transactions ===
|
||||
|
||||
Transaction 1 hash: 0F71979E3F641C980929F926640DCA886C30236ED0CD7C94B6CB36F0D42948AC
|
||||
- Status: tesSUCCESS (Ledger 1257846)
|
||||
- Transaction URL: https://devnet.xrpl.org/transactions/0F71979E3F641C980929F926640DCA886C30236ED0CD7C94B6CB36F0D42948AC
|
||||
|
||||
Transaction 2 hash: BC124CB29334AA1079139A9BE186B69A0AC467797F147754E2406714854D2A50
|
||||
- Status: tesSUCCESS (Ledger 1257846)
|
||||
- Transaction URL: https://devnet.xrpl.org/transactions/BC124CB29334AA1079139A9BE186B69A0AC467797F147754E2406714854D2A50
|
||||
|
||||
=== Final balances ===
|
||||
Alice: rHpve1GL2ZXUs3NB5iU91BrXBSwb5PbBrG, Balance: 200 XRP
|
||||
Bob: r3ruQ92bqXwWxcR2w4cC1tW35og9h3UbBq, Balance: 50 XRP
|
||||
Charlie: rsi5D9bkczpbGykPxoGNBVVmFFFXGwm3QA, Balance: 50 XRP
|
||||
Third-party wallet: rfUpGXTzU3siTr4UovV6Wt86Vw3gQU4ttA, Balance: 99.999994 XRP
|
||||
```
|
||||
|
||||
@@ -3,18 +3,17 @@
|
||||
*
|
||||
* This tutorial demonstrates how to use the Batch transaction feature (XLS-56)
|
||||
* to perform a multi-account batch transaction.
|
||||
* Concept doc: https://xrpl.org/docs/concepts/transactions/batch-transactions
|
||||
* Reference doc: https://xrpl.org/docs/references/protocol/transactions/types/batch
|
||||
*/
|
||||
|
||||
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...")
|
||||
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()
|
||||
@@ -35,7 +34,7 @@ const charliePayment = {
|
||||
Account: charlie.address,
|
||||
Destination: alice.address,
|
||||
Amount: xrpl.xrpToDrops(50),
|
||||
Flags: GlobalFlags.tfInnerBatchTxn // THIS IS REQUIRED
|
||||
Flags: xrpl.GlobalFlags.tfInnerBatchTxn // THIS IS REQUIRED
|
||||
}
|
||||
|
||||
// Transaction 2: Bob pays Alice
|
||||
@@ -44,15 +43,15 @@ const bobPayment = {
|
||||
Account: bob.address,
|
||||
Destination: alice.address,
|
||||
Amount: xrpl.xrpToDrops(50),
|
||||
Flags: GlobalFlags.tfInnerBatchTxn // THIS IS REQUIRED
|
||||
Flags: xrpl.GlobalFlags.tfInnerBatchTxn // THIS IS REQUIRED
|
||||
}
|
||||
|
||||
// Send Batch transaction --------------------------------------------
|
||||
console.log("\nCreating batch transaction:")
|
||||
console.log("\n=== Creating Batch transaction... ===")
|
||||
const batchTx = {
|
||||
TransactionType: "Batch",
|
||||
Account: thirdPartyWallet.address,
|
||||
Flags: BatchFlags.tfAllOrNothing, // tfAllOrNothing: All inner transactions must succeed
|
||||
Flags: xrpl.BatchFlags.tfAllOrNothing, // tfAllOrNothing: All inner transactions must succeed
|
||||
// Must include a minimum of 2 transactions and a maximum of 8 transactions.
|
||||
RawTransactions: [
|
||||
{ RawTransaction: charliePayment },
|
||||
@@ -72,18 +71,18 @@ const autofilledBatchTx = await client.autofill(batchTx, 2)
|
||||
// Each signer needs their own tx copy because signMultiBatch modifies the object.
|
||||
// Charlie signs the Batch transaction
|
||||
const charlieBatch = { ...autofilledBatchTx }
|
||||
signMultiBatch(charlie, charlieBatch)
|
||||
xrpl.signMultiBatch(charlie, charlieBatch)
|
||||
|
||||
// Bob signs the Batch transaction
|
||||
const bobBatch = { ...autofilledBatchTx }
|
||||
signMultiBatch(bob, bobBatch)
|
||||
xrpl.signMultiBatch(bob, bobBatch)
|
||||
|
||||
// Combine inner transaction signatures.
|
||||
// This returns a signed transaction blob (hex string) ready for submission.
|
||||
const combinedSignedTx = combineBatchSigners([charlieBatch, bobBatch])
|
||||
const combinedSignedTx = xrpl.combineBatchSigners([charlieBatch, bobBatch])
|
||||
|
||||
// Submit the signed blob with the third-party's wallet
|
||||
console.log("\nSubmitting batch transaction...")
|
||||
console.log("\n=== Submitting Batch transaction... ===")
|
||||
const submitResponse = await client.submitAndWait(combinedSignedTx,
|
||||
{ wallet: thirdPartyWallet }
|
||||
)
|
||||
@@ -97,15 +96,39 @@ if (submitResponse.result.meta.TransactionResult !== "tesSUCCESS") {
|
||||
|
||||
console.log("\nBatch transaction submitted successfully!")
|
||||
console.log("Result:\n", JSON.stringify(submitResponse.result, null, 2))
|
||||
// View the transaction on the XRPL Explorer
|
||||
console.log(`\nBatch transaction URL:\nhttps://devnet.xrpl.org/transactions/${submitResponse.result.hash}`)
|
||||
|
||||
// Calculate and verify inner transaction hashes --------------------------------------------
|
||||
console.log("\n=== Verifying inner transactions ===")
|
||||
const rawTransactions = submitResponse.result.tx_json.RawTransactions
|
||||
let hasFailure = false
|
||||
|
||||
for (let i = 0; i < rawTransactions.length; i++) {
|
||||
const innerTx = rawTransactions[i].RawTransaction
|
||||
const hash = xrpl.hashes.hashSignedTx(innerTx)
|
||||
console.log(`\nTransaction ${i + 1} hash: ${hash}`)
|
||||
|
||||
try {
|
||||
const tx = await client.request({ command: 'tx', transaction: hash })
|
||||
const status = tx.result.meta?.TransactionResult
|
||||
console.log(` - Status: ${status} (Ledger ${tx.result.ledger_index})`)
|
||||
console.log(` - Transaction URL: https://devnet.xrpl.org/transactions/${hash}`)
|
||||
} catch (error) {
|
||||
hasFailure = true
|
||||
console.log(` - Transaction not found: ${error}`)
|
||||
}
|
||||
}
|
||||
if (hasFailure) {
|
||||
console.error("\n--- Error: One or more inner transactions failed. ---")
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Verify balances after transaction
|
||||
console.log("\nFinal balances after batch 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(`\nTransaction URL:\nhttps://devnet.xrpl.org/transactions/${submitResponse.result.hash}`)
|
||||
|
||||
await client.disconnect()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"xrpl": "^4.4.2"
|
||||
"xrpl": "^4.4.3"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
* 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.
|
||||
* Concept doc: https://xrpl.org/docs/concepts/transactions/batch-transactions
|
||||
* Reference doc: https://xrpl.org/docs/references/protocol/transactions/types/batch
|
||||
*/
|
||||
|
||||
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...")
|
||||
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()
|
||||
@@ -33,7 +33,7 @@ const payment1 = {
|
||||
Account: sender.address,
|
||||
Destination: wallet1.address,
|
||||
Amount: xrpl.xrpToDrops(2),
|
||||
Flags: GlobalFlags.tfInnerBatchTxn // THIS IS REQUIRED
|
||||
Flags: xrpl.GlobalFlags.tfInnerBatchTxn // THIS IS REQUIRED
|
||||
}
|
||||
|
||||
// Transaction 2
|
||||
@@ -42,15 +42,15 @@ const payment2 = {
|
||||
Account: sender.address,
|
||||
Destination: wallet2.address,
|
||||
Amount: xrpl.xrpToDrops(5),
|
||||
Flags: GlobalFlags.tfInnerBatchTxn // THIS IS REQUIRED
|
||||
Flags: xrpl.GlobalFlags.tfInnerBatchTxn // THIS IS REQUIRED
|
||||
}
|
||||
|
||||
// Send Batch transaction --------------------------------------------
|
||||
console.log("\nCreating batch transaction:")
|
||||
console.log("\n=== Creating Batch transaction... ===")
|
||||
const batchTx = {
|
||||
TransactionType: "Batch",
|
||||
Account: sender.address,
|
||||
Flags: BatchFlags.tfAllOrNothing, // tfAllOrNothing: All inner transactions must succeed
|
||||
Flags: xrpl.BatchFlags.tfAllOrNothing, // tfAllOrNothing: All inner transactions must succeed
|
||||
// Must include a minimum of 2 transactions and a maximum of 8 transactions.
|
||||
RawTransactions: [
|
||||
{ RawTransaction: payment1 },
|
||||
@@ -63,7 +63,7 @@ console.log(JSON.stringify(batchTx, null, 2))
|
||||
xrpl.validate(batchTx)
|
||||
|
||||
// Submit and wait for validation
|
||||
console.log("\nSubmitting batch transaction...")
|
||||
console.log("\n=== Submitting Batch transaction... ===")
|
||||
const submitResponse = await client.submitAndWait(batchTx, {
|
||||
wallet: sender,
|
||||
// "autofill" will automatically add Fee: "0" and SigningPubKey: "".
|
||||
@@ -78,14 +78,38 @@ if (submitResponse.result.meta.TransactionResult !== "tesSUCCESS") {
|
||||
}
|
||||
console.log("\nBatch transaction submitted successfully!")
|
||||
console.log("Result:\n", JSON.stringify(submitResponse.result, null, 2))
|
||||
// View the batch transaction on the XRPL Explorer
|
||||
console.log(`\nBatch transaction URL:\nhttps://devnet.xrpl.org/transactions/${submitResponse.result.hash}`)
|
||||
|
||||
// Calculate and verify inner transaction hashes --------------------------------------------
|
||||
console.log("\n=== Verifying inner transactions... ===")
|
||||
const rawTransactions = submitResponse.result.tx_json.RawTransactions
|
||||
let hasFailure = false
|
||||
|
||||
for (let i = 0; i < rawTransactions.length; i++) {
|
||||
const innerTx = rawTransactions[i].RawTransaction
|
||||
const hash = xrpl.hashes.hashSignedTx(innerTx)
|
||||
console.log(`\nTransaction ${i + 1} hash: ${hash}`)
|
||||
|
||||
try {
|
||||
const tx = await client.request({ command: 'tx', transaction: hash })
|
||||
const status = tx.result.meta?.TransactionResult
|
||||
console.log(` - Status: ${status} (Ledger ${tx.result.ledger_index})`)
|
||||
console.log(` - Transaction URL: https://devnet.xrpl.org/transactions/${hash}`)
|
||||
} catch (error) {
|
||||
hasFailure = true
|
||||
console.log(` - Transaction not found: ${error}`)
|
||||
}
|
||||
}
|
||||
if (hasFailure) {
|
||||
console.error("\n--- Error: One or more inner transactions failed. ---")
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Verify balances after transaction
|
||||
console.log("\nFinal balances after batch 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 transaction on the XRPL Explorer
|
||||
console.log(`\nTransaction URL:\nhttps://devnet.xrpl.org/transactions/${submitResponse.result.hash}`)
|
||||
|
||||
await client.disconnect()
|
||||
|
||||
@@ -120,13 +120,13 @@ With all the required signatures gathered, the third-party wallet can now submit
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 6. Check Batch transaction result
|
||||
### 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="// Verify balances after transaction" /%}
|
||||
{% code-snippet file="/_code-samples/batch/js/multiAccountBatch.js" language="js" from="// Check Batch transaction" before="// Calculate and verify" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
@@ -136,7 +136,23 @@ The code checks for a `tesSUCCESS` result and displays the response details.
|
||||
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 %}
|
||||
|
||||
To verify that the inner transactions have been successful, check the account balances to confirm the expected changes.
|
||||
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 in the Batch transaction result, you need to calculate the inner transaction hashes and look 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" %}
|
||||
@@ -144,8 +160,6 @@ To verify that the inner transactions have been successful, check the account ba
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
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**.
|
||||
|
||||
## See Also
|
||||
|
||||
- **Concepts**:
|
||||
|
||||
@@ -114,7 +114,7 @@ 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="// Verify balances after transaction" /%}
|
||||
{% code-snippet file="/_code-samples/batch/js/singleAccountBatch.js" language="js" from="// Check Batch transaction" before="// Calculate and verify" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
@@ -126,7 +126,23 @@ A `tesSUCCESS` result indicates that the Batch transaction was processed success
|
||||
For example, see the [following transaction on the XRPL Explorer](https://devnet.xrpl.org/transactions/20CFCE5CF75E93E6D1E9C1E42F8E8C8C4CB1786A65BE23D2EA77EAAB65A455C5/simple).
|
||||
{% /admonition %}
|
||||
|
||||
To verify that the inner transactions have been successful, check the account balances to confirm the expected changes.
|
||||
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 in the Batch transaction result, you need to calculate the inner transaction hashes and look 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" %}
|
||||
@@ -134,8 +150,6 @@ To verify that the inner transactions have been successful, check the account ba
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
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 **sender**.
|
||||
|
||||
## See Also
|
||||
|
||||
- **Concepts**:
|
||||
|
||||
Reference in New Issue
Block a user