Skip to content

Commit 9a997c8

Browse files
authored
feat: add support for Batch amendment (#2801)
* improve scripts * Update settings.json * update file locations after refactor * add LedgerStateFix * add Batch * add BatchTxn autofill * add multi-account signing * add combine function * add Batch support to hashing txs * add autofill TxID support * better validation * add metadata * update definitions.json * clean up * update binary codec for signing * add Batchnet faucet * get basic tests working * add rbc tests * add autofill tests * add signMultiBatch tests * refactor * add basic tests for combineBatchSigners * handle more edge cases * better error validation * rename * update history * fix import * add more validation * remove BatchTxn, fix autofill * replace BatchTxn in some more places, fix tests * fix linter issues * update definitions * Batch integration test * remove debug statement * fix TxnSignature * fix BatchMetadata * fix tests * more updates * remove TransactionIDs * add more tests * remove LedgerStateFix * fix build issues * uncomment now-passing test * fix linter * drive-by multisign fix * add more tests * better docstrings * redo definitions.json * fix error * minor cleanup * update vscode settings * fix linter * fix history * fix tests * fix build issue * bump versions for beta * update packagelock * update package-lock * back out unrelated changes * more backing out * rename test file * update tfInnerBatchTxn handling * respond to comments * fix coderabbit issues * improve type-checking * fix errors * fix errors * fix autofill * fix ts issues * more fixes * more fixes * respond to comments * disable * update definitions * add Batch to the list of non delegatable transactions * fix definitions, update amendments in config * fix test * I tried to be too smart for my own good * more flag tests * roll back beta version changes * clean up batchSigner file * fix imports * fix test * fix 4 real * roll back some typing changes * remove faucet * respond to comments * respond to comments * fix tests * fix dependency cycle * fix imports * add address info * fix browser tests * respond to comments * improve multisig fee calculations * fix test * address comment
1 parent ac1bac7 commit 9a997c8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+2057
-374
lines changed

.ci-config/rippled.cfg

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,18 +173,23 @@ fixPreviousTxnID
173173
fixAMMv1_1
174174
# 2.3.0 Amendments
175175
AMMClawback
176-
fixAMMv1_2
177176
Credentials
178177
NFTokenMintOffer
179178
MPTokensV1
179+
fixAMMv1_2
180180
fixNFTokenPageLinks
181181
fixInnerObjTemplate2
182182
fixEnforceNFTokenTrustline
183183
fixReducedOffersV2
184+
# 2.4.0 Amendments
184185
DeepFreeze
185186
DynamicNFT
186187
PermissionedDomains
188+
fixFrozenLPTokenTransfer
189+
fixInvalidTxFlags
190+
# 2.5.0 Amendments
187191
PermissionDelegation
192+
Batch
188193

189194
# This section can be used to simulate various FeeSettings scenarios for rippled node in standalone mode
190195
[voting]

.vscode/settings.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
"editor.tabSize": 2,
33
"cSpell.words": [
44
"altnet",
5-
"Autofills",
5+
"autofills",
6+
"bignumber",
67
"Clawback",
78
"hostid",
89
"keypair",
910
"keypairs",
11+
"MPToken",
1012
"multisign",
1113
"multisigned",
1214
"multisigning",
@@ -16,7 +18,8 @@
1618
"secp256k1",
1719
"Setf",
1820
"Sidechains",
19-
"xchain"
21+
"xchain",
22+
"xrplf"
2023
],
2124
"[javascript]": {
2225
"editor.defaultFormatter": "esbenp.prettier-vscode",

packages/ripple-binary-codec/HISTORY.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
## Unreleased
44

55
### Added
6-
* Support for `Account Permissions` and `Account Permission Delegation` (XLS-74d, XLS-75d)
6+
* Support for `Account Permissions` and `Account Permission Delegation` (XLS-74d, XLS-75d).
7+
* Support for the `Batch` amendment (XLS-56).
78

89
### Fixed
910
* add `MPTCurrency` support in `Issue` (rippled internal type)
@@ -18,7 +19,7 @@
1819
## 2.2.0 (2024-12-23)
1920

2021
### Added
21-
* Support for the Multi-Purpose Token amendment (XLS-33)
22+
* Support for the Multi-Purpose Token amendment (XLS-33).
2223

2324
## 2.1.0 (2024-06-03)
2425

packages/ripple-binary-codec/src/binary.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,51 @@ function multiSigningData(
177177
})
178178
}
179179

180+
/**
181+
* Interface describing fields required for a Batch signer
182+
* @property flags - Flags indicating Batch transaction properties
183+
* @property txIDs - Array of transaction IDs included in the Batch
184+
*/
185+
interface BatchObject extends JsonObject {
186+
flags: number
187+
txIDs: string[]
188+
}
189+
190+
/**
191+
* Serialize a signingClaim
192+
*
193+
* @param batch A Batch object to serialize.
194+
* @returns the serialized object with appropriate prefix
195+
*/
196+
function signingBatchData(batch: BatchObject): Uint8Array {
197+
if (batch.flags == null) {
198+
throw Error("No field `flags'")
199+
}
200+
if (batch.txIDs == null) {
201+
throw Error('No field `txIDs`')
202+
}
203+
const prefix = HashPrefix.batch
204+
const flags = coreTypes.UInt32.from(batch.flags).toBytes()
205+
const txIDsLength = coreTypes.UInt32.from(batch.txIDs.length).toBytes()
206+
207+
const bytesList = new BytesList()
208+
209+
bytesList.put(prefix)
210+
bytesList.put(flags)
211+
bytesList.put(txIDsLength)
212+
batch.txIDs.forEach((txID: string) => {
213+
bytesList.put(coreTypes.Hash256.from(txID).toBytes())
214+
})
215+
216+
return bytesList.toBytes()
217+
}
218+
180219
export {
181220
BinaryParser,
182221
BinarySerializer,
183222
BytesList,
184223
ClaimObject,
224+
BatchObject,
185225
makeParser,
186226
serializeObject,
187227
readJSON,
@@ -191,4 +231,5 @@ export {
191231
binaryToJSON,
192232
sha512Half,
193233
transactionID,
234+
signingBatchData,
194235
}

packages/ripple-binary-codec/src/hash-prefixes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ const HashPrefix: Record<string, Uint8Array> = {
3535
proposal: bytes(0x50525000),
3636
// payment channel claim
3737
paymentChannelClaim: bytes(0x434c4d00),
38+
// batch
39+
batch: bytes(0x42434800),
3840
}
3941

4042
export { HashPrefix }

packages/ripple-binary-codec/src/index.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { quality, binary, HashPrefix } from './coretypes'
22
import { decodeLedgerData } from './ledger-hashes'
3-
import { ClaimObject } from './binary'
3+
import { ClaimObject, BatchObject } from './binary'
44
import { JsonObject } from './types/serialized-type'
55
import {
66
XrplDefinitionsBase,
@@ -15,6 +15,7 @@ const {
1515
signingData,
1616
signingClaimData,
1717
multiSigningData,
18+
signingBatchData,
1819
binaryToJSON,
1920
serializeObject,
2021
} = binary
@@ -71,12 +72,10 @@ function encodeForSigning(
7172
}
7273

7374
/**
74-
* Encode a transaction and prepare for signing with a claim
75+
* Encode a payment channel claim for signing.
7576
*
76-
* @param json JSON object representing the transaction
77-
* @param signer string representing the account to sign the transaction with
78-
* @param definitions Custom rippled types to use instead of the default. Used for sidechains and amendments.
79-
* @returns a hex string of the encoded transaction
77+
* @param json JSON object representing the claim.
78+
* @returns a hex string of the encoded claim.
8079
*/
8180
function encodeForSigningClaim(json: object): string {
8281
if (typeof json !== 'object') {
@@ -86,12 +85,12 @@ function encodeForSigningClaim(json: object): string {
8685
}
8786

8887
/**
89-
* Encode a transaction and prepare for multi-signing
88+
* Encode a transaction and prepare for multi-signing.
9089
*
91-
* @param json JSON object representing the transaction
92-
* @param signer string representing the account to sign the transaction with
90+
* @param json JSON object representing the transaction.
91+
* @param signer string representing the account to sign the transaction with.
9392
* @param definitions Custom rippled types to use instead of the default. Used for sidechains and amendments.
94-
* @returns a hex string of the encoded transaction
93+
* @returns a hex string of the encoded transaction.
9594
*/
9695
function encodeForMultisigning(
9796
json: object,
@@ -110,6 +109,19 @@ function encodeForMultisigning(
110109
)
111110
}
112111

112+
/**
113+
* Encode a Batch transaction for signing.
114+
*
115+
* @param json JSON object representing the transaction.
116+
* @returns a hex string of the encoded transaction.
117+
*/
118+
function encodeForSigningBatch(json: object): string {
119+
if (typeof json !== 'object') {
120+
throw new Error('Need an object to encode a Batch transaction')
121+
}
122+
return bytesToHex(signingBatchData(json as BatchObject))
123+
}
124+
113125
/**
114126
* Encode a quality value
115127
*
@@ -142,6 +154,7 @@ export {
142154
encodeForSigning,
143155
encodeForSigningClaim,
144156
encodeForMultisigning,
157+
encodeForSigningBatch,
145158
encodeQuality,
146159
decodeQuality,
147160
decodeLedgerData,

packages/ripple-binary-codec/src/types/hash.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Comparable } from './serialized-type'
22
import { BinaryParser } from '../serdes/binary-parser'
3-
import { hexToBytes } from '@xrplf/isomorphic/utils'
3+
import { HEX_REGEX, hexToBytes } from '@xrplf/isomorphic/utils'
44
import { compare } from '../utils'
55

66
/**
@@ -27,6 +27,9 @@ class Hash extends Comparable<Hash | string> {
2727
}
2828

2929
if (typeof value === 'string') {
30+
if (!HEX_REGEX.test(value)) {
31+
throw new Error(`Invalid hash string ${value}`)
32+
}
3033
return new this(hexToBytes(value))
3134
}
3235

packages/ripple-binary-codec/test/signing-data-encoding.test.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { XrplDefinitions } from '../src/enums/xrpl-definitions'
2-
const {
2+
import {
33
encodeForSigning,
44
encodeForSigningClaim,
55
encodeForMultisigning,
6-
} = require('../src')
6+
encodeForSigningBatch,
7+
} from '../src'
78

89
const normalDefinitions = require('../src/enums/definitions.json')
910

@@ -124,8 +125,8 @@ describe('Signing data', function () {
124125
TransactionType: 'NotAPayment',
125126
}
126127

127-
expect(() => encodeForSigning(invalidTransactionType)).toThrowError(
128-
/NotAPayment/u,
128+
expect(() => encodeForSigning(invalidTransactionType)).toThrow(
129+
new TypeError('Unable to interpret "TransactionType: NotAPayment".'),
129130
)
130131
})
131132

@@ -244,4 +245,35 @@ describe('Signing data', function () {
244245
].join(''),
245246
)
246247
})
248+
249+
it('can create batch blob', function () {
250+
const flags = 1
251+
const txIDs = [
252+
'ABE4871E9083DF66727045D49DEEDD3A6F166EB7F8D1E92FE868F02E76B2C5CA',
253+
'795AAC88B59E95C3497609749127E69F12958BC016C600C770AEEB1474C840B4',
254+
]
255+
const json = { flags, txIDs }
256+
const actual = encodeForSigningBatch(json)
257+
expect(actual).toBe(
258+
[
259+
// hash prefix
260+
'42434800',
261+
// flags
262+
'00000001',
263+
// txIds length
264+
'00000002',
265+
// txIds
266+
'ABE4871E9083DF66727045D49DEEDD3A6F166EB7F8D1E92FE868F02E76B2C5CA',
267+
'795AAC88B59E95C3497609749127E69F12958BC016C600C770AEEB1474C840B4',
268+
].join(''),
269+
)
270+
})
271+
272+
it('encodeForSigningBatch fails on non-object', function () {
273+
const flags = 1
274+
// @ts-expect-error - testing invalid input for JS users
275+
expect(() => encodeForSigningBatch(flags)).toThrow(
276+
new Error('Need an object to encode a Batch transaction'),
277+
)
278+
})
247279
})

packages/xrpl/.eslintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ module.exports = {
6666
'tsdoc/syntax': 'off',
6767
'jsdoc/require-description-complete-sentence': 'off',
6868
'import/prefer-default-export': 'off',
69+
'max-depth': ['warn', 3],
6970
},
7071
overrides: [
7172
{
@@ -155,7 +156,6 @@ module.exports = {
155156
'max-lines-per-function': ['off'],
156157
'max-statements': ['off'],
157158
complexity: ['off'],
158-
'max-depth': ['warn', 3],
159159
},
160160
},
161161
],

packages/xrpl/HISTORY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr
88
* Support for `NFTokenMintOffer` (XLS-52)
99
* Add Github Actions step to auto-generate documentation
1010
* Support for `Account Permissions` and `Account Permission Delegation` (XLS-74d, XLS-75d)
11+
* Add support for `Batch` amendment (XLS-56)
1112

1213
### Fixed
1314
* Fix `OracleSet` transaction to accept hexadecimal string values for `AssetPrice` field
1415
* `TransactionStream` model includes `hash` field in APIv2
1516
* `TransactionStream` model includes `close_time_iso` field only for APIv2
1617
* Adds `MPTCurrency` type
1718
* Better faucet support
19+
* Improve multisign fee calculations
1820

1921
## 4.2.0 (2025-2-13)
2022

0 commit comments

Comments
 (0)