Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 4 additions & 30 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions packages/ripple-binary-codec/HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

### Changed
* Add XLS-56 Batch V1_1 support to `signingBatchData` / `encodeForSigningBatch` ([XRPLF/rippled#6446](https://github.com/XRPLF/rippled/pull/6446)). Tracks an unmerged rippled PR; the wire format may still change.

## 2.8.0 (2026-06-04)

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion packages/ripple-binary-codec/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ripple-binary-codec",
"version": "2.8.0",
"version": "2.9.0-batch.1",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding was that beta releases have a suffix of the form: 2.9.0-beta-batch-1.

Are we sure this released is not interpreted as a "General Availability" release by the community? @pdp2121

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other feature beta/experimental releases are following the same pattern, for example:
https://github.com/XRPLF/xrpl.js/releases/tag/xrpl%404.7.0-smartcontract.0

"description": "XRP Ledger binary codec",
"files": [
"dist/*",
Expand Down
46 changes: 41 additions & 5 deletions packages/ripple-binary-codec/src/binary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,41 +178,77 @@ function multiSigningData(
}

/**
* Interface describing fields required for a Batch signer
* @property flags - Flags indicating Batch transaction properties
* @property txIDs - Array of transaction IDs included in the Batch
* Fields required to serialize an XLS-56 Batch V1_1 signing payload.
*
* @property account - The outer Batch transaction's `Account`.
* @property sequence - The outer Batch's sequence value (`Sequence`, or the
* `TicketSequence` value when a ticket is used).
* @property flags - Flags indicating Batch transaction properties.
* @property txIDs - Array of inner transaction IDs included in the Batch.
* @property batchAccount - The `BatchSigner.Account` the signature binds to.
* @property signerAccount - For a multi-signed `BatchSigner`, the inner
* `Signers` entry account, appended after `batchAccount`.
*/
interface BatchObject extends JsonObject {
account: string
sequence: number
flags: number
txIDs: string[]
batchAccount?: string
signerAccount?: string
}

/**
* Serialize a signingClaim
* Serialize an XLS-56 Batch V1_1 signing payload:
* HashPrefix.batch | account | sequence | flags | txIDCount | txIDs[]
* [ | batchAccount [ | signerAccount ] ]
*
* @param batch A Batch object to serialize.
* @returns the serialized object with appropriate prefix
*/
function signingBatchData(batch: BatchObject): Uint8Array {
if (batch.account == null) {
throw Error('No field `account`')
}
if (batch.sequence == null) {
throw Error('No field `sequence`')
}
if (batch.flags == null) {
throw Error("No field `flags'")
throw Error('No field `flags`')
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
if (batch.txIDs == null) {
throw Error('No field `txIDs`')
}
const prefix = HashPrefix.batch
const account = coreTypes.AccountID.from(batch.account).toBytes()
const sequence = coreTypes.UInt32.from(batch.sequence).toBytes()
const flags = coreTypes.UInt32.from(batch.flags).toBytes()
const txIDsLength = coreTypes.UInt32.from(batch.txIDs.length).toBytes()

const bytesList = new BytesList()

bytesList.put(prefix)
bytesList.put(account)
bytesList.put(sequence)
bytesList.put(flags)
bytesList.put(txIDsLength)
batch.txIDs.forEach((txID: string) => {
bytesList.put(coreTypes.Hash256.from(txID).toBytes())
})

if (batch.batchAccount != null) {
bytesList.put(coreTypes.AccountID.from(batch.batchAccount).toBytes())
}
// The wire format is positional, so `signerAccount` must follow `batchAccount`.
// Reject `signerAccount` without `batchAccount` to avoid binding the signature
// to the wrong account.
if (batch.signerAccount != null) {
Comment thread
depthfirst-app[bot] marked this conversation as resolved.
if (batch.batchAccount == null) {
throw Error('Field `signerAccount` requires `batchAccount`')
}
bytesList.put(coreTypes.AccountID.from(batch.signerAccount).toBytes())
}

return bytesList.toBytes()
}

Expand Down
63 changes: 56 additions & 7 deletions packages/ripple-binary-codec/test/signing-data-encoding.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,25 +306,74 @@ describe('Signing data', function () {
)
})

it('can create batch blob', function () {
const flags = 1
const txIDs = [
'ABE4871E9083DF66727045D49DEEDD3A6F166EB7F8D1E92FE868F02E76B2C5CA',
'795AAC88B59E95C3497609749127E69F12958BC016C600C770AEEB1474C840B4',
]
const json = { flags, txIDs }
it('can create batch blob for a single-signed BatchSigner', function () {
const json = {
account: 'rNCFjv8Ek5oDrNiMJ3pw6eLLFtMjZLJnf2',
sequence: 5,
flags: 1,
txIDs: [
'ABE4871E9083DF66727045D49DEEDD3A6F166EB7F8D1E92FE868F02E76B2C5CA',
'795AAC88B59E95C3497609749127E69F12958BC016C600C770AEEB1474C840B4',
],
// The BatchSigner.Account the signature is bound to (XLS-56 V1_1).
batchAccount: 'rJCxK2hX9tDMzbnn3cg1GU2g19Kfmhzxkp',
}
const actual = encodeForSigningBatch(json)
expect(actual).toBe(
[
// hash prefix
'42434800',
// outer account
'95F14B0E44F78A264E41713C64B5F89242540EE2',
// outer sequence
'00000005',
// flags
'00000001',
// txIds length
'00000002',
// txIds
'ABE4871E9083DF66727045D49DEEDD3A6F166EB7F8D1E92FE868F02E76B2C5CA',
'795AAC88B59E95C3497609749127E69F12958BC016C600C770AEEB1474C840B4',
// batch signer account
'C1D81FB31C42392BA1570431F1CBCBEEBBEF50E1',
].join(''),
)
})

it('can create batch blob for a multi-signed BatchSigner', function () {
const json = {
account: 'rNCFjv8Ek5oDrNiMJ3pw6eLLFtMjZLJnf2',
sequence: 5,
flags: 1,
txIDs: [
'ABE4871E9083DF66727045D49DEEDD3A6F166EB7F8D1E92FE868F02E76B2C5CA',
'795AAC88B59E95C3497609749127E69F12958BC016C600C770AEEB1474C840B4',
],
// The BatchSigner.Account the signature is bound to.
batchAccount: 'rJCxK2hX9tDMzbnn3cg1GU2g19Kfmhzxkp',
// The inner Signers entry account for a multi-signed BatchSigner.
signerAccount: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
}
const actual = encodeForSigningBatch(json)
expect(actual).toBe(
[
// hash prefix
'42434800',
// outer account
'95F14B0E44F78A264E41713C64B5F89242540EE2',
// outer sequence
'00000005',
// flags
'00000001',
// txIds length
'00000002',
// txIds
'ABE4871E9083DF66727045D49DEEDD3A6F166EB7F8D1E92FE868F02E76B2C5CA',
'795AAC88B59E95C3497609749127E69F12958BC016C600C770AEEB1474C840B4',
// batch signer account
'C1D81FB31C42392BA1570431F1CBCBEEBBEF50E1',
// inner signer account
'B5F762798A53D543A014CAF8B297CFF8F2F937E8',
].join(''),
)
})
Expand Down
3 changes: 3 additions & 0 deletions packages/xrpl/HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr

## Unreleased

### Changed
* Add XLS-56 Batch V1_1 support to `signMultiBatch` and `combineBatchSigners` ([XRPLF/rippled#6446](https://github.com/XRPLF/rippled/pull/6446)).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: A WIP tag will be helpful to identify that this PR has not been finalized yet.


## 5.0.0 (2026-06-05)

### BREAKING CHANGES:
Expand Down
4 changes: 2 additions & 2 deletions packages/xrpl/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "xrpl",
"version": "5.0.0",
"version": "5.1.0-batch.1",
"license": "ISC",
"description": "A TypeScript/JavaScript API for interacting with the XRP Ledger in Node.js and the browser",
"files": [
Expand Down Expand Up @@ -30,7 +30,7 @@
"eventemitter3": "^5.0.1",
"fast-json-stable-stringify": "^2.1.0",
"ripple-address-codec": "^5.0.1",
"ripple-binary-codec": "^2.8.0",
"ripple-binary-codec": "^2.9.0-batch.1",
"ripple-keypairs": "^3.0.0"
},
"devDependencies": {
Expand Down
Loading
Loading