Skip to content

feat(xrpl): custom definitions support#3229

Open
tequdev wants to merge 32 commits intoXRPLF:mainfrom
tequdev:xrpl_binary_codec_custom_definition_support
Open

feat(xrpl): custom definitions support#3229
tequdev wants to merge 32 commits intoXRPLF:mainfrom
tequdev:xrpl_binary_codec_custom_definition_support

Conversation

@tequdev
Copy link
Copy Markdown
Member

@tequdev tequdev commented Mar 23, 2026

Handover for #2683

High Level Overview of Change

In previous versions, custom definition support was added to the ripple-binary-codec methods but not the proxy ones in the xrpl package.

This PR adds support for Custom Definitions to the following xrpl methods:

  • utils.encode
  • utils.decode
  • utils.encodeForSigning
  • Wallet.sign
  • client.submit()
  • client.submitAndWait

Context of Change

When using custom definitions, you had to directly use the encode, decode, and encodeForSigning methods from ripple-binary-codec. Those features can now be used via the proxy methods in the xrpl package.

Custom definition support has also been added to the Wallet.sign method which wasn't the case before.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (non-breaking change that only restructures code)
  • Tests (You added tests for code that already exists, or your new feature included in this PR)
  • Documentation Updates
  • Release

Did you update HISTORY.md?

  • Yes
  • No, this change does not impact library users

Test Plan

Added 3 unit tests for:

  • Wallet.sign (single signature)
  • Wallet.sign (multisignature)
  • Wallet.sign (unknown transaction type)

elmurci and others added 21 commits April 21, 2024 15:38
Co-authored-by: Mayukha Vadari <mvadari@gmail.com>
…n_support

Support custom definitions for `client.submit()`, `client.submitAndWait()`
Co-authored-by: tequ <git@tequ.dev>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 23, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Threads an optional XrplDefinitionsBase parameter through encoding, decoding, signing, validation, submission, and hashing APIs so custom ripple-binary-codec definitions can be provided and used during transaction processing and tests.

Changes

Cohort / File(s) Summary
Public API docs
packages/ripple-binary-codec/README.md
Documented optional definitions?: XrplDefinitionsBase for decode, encode, encodeForSigning, and encodeForMultisigning.
Release notes
packages/xrpl/HISTORY.md
Added entry noting Custom Definitions support for client submit paths and util encode/decode/signing.
Wallet & signing utilities
packages/xrpl/src/Wallet/index.ts, packages/xrpl/src/Wallet/utils.ts
Wallet.sign, getDecodedTransaction, and computeSignature accept and forward definitions into validation, encoding, signing, and hash computation.
Client plumbing
packages/xrpl/src/client/index.ts
Added public Client.definitions?: XrplDefinitionsBase and merge/pass it into getSignedTx for submit()/submitAndWait().
Validation changes
packages/xrpl/src/models/transactions/common.ts, packages/xrpl/src/models/transactions/transaction.ts
Validation functions accept definitions/customDefinitions and consult provided definitions (transactionNames) instead of only defaults when checking TransactionType.
Encoding/decoding utilities
packages/xrpl/src/utils/index.ts, packages/xrpl/src/utils/hashes/hashLedger.ts
encode, encodeForSigning, encodeForMultiSigning, decode, and hashSignedTx accept and forward optional definitions.
Submit sugar
packages/xrpl/src/sugar/submit.ts
submitRequest and getSignedTx accept definitions and use them for signed checks and encoding/decoding of string/object transactions.
Test fixtures
packages/xrpl/test/fixtures/...
packages/xrpl/test/fixtures/requests/index.ts, packages/xrpl/test/fixtures/requests/signAsCustomDefinition.json, packages/xrpl/test/fixtures/responses/index.ts, packages/xrpl/test/fixtures/responses/signCustomDefinition.json, packages/xrpl/test/fixtures/responses/signAsCustomDefinition.json, packages/xrpl/test/fixtures/rippled/index.ts, packages/xrpl/test/fixtures/rippled/customDefinition.json
Added fixtures for custom-definition signing scenarios and exposed definitions fixture in rippled fixtures.
Tests
packages/xrpl/test/wallet/index.test.ts
Added tests for Wallet.sign() with valid custom definitions, invalid transaction-type error, and multisign path using custom definitions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • mvadari
  • ckeshava
  • kuan121
  • pdp2121
  • Patel-Raj11

Poem

🐇 I hopped through bytes and learned each new field,
Carried custom rules so transactions yield,
I signed and encoded with nimble delight,
Multisign and hashes snug in moonlight,
A rabbit cheers tests passing into the night.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(xrpl): custom definitions support' clearly and concisely summarizes the main change in the pull request—adding custom definitions support to xrpl methods.
Description check ✅ Passed The description comprehensively covers the overview, context, type of change, and confirms HISTORY.md was updated with test plan details, meeting all major template requirements.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@tequdev tequdev changed the title Xrpl binary codec custom definition support feat(xrpl): custom definitions support Mar 23, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
packages/xrpl/src/utils/index.ts (1)

17-25: ⚠️ Potential issue | 🟡 Minor

Use a type-only import for XrplDefinitionsBase.

XrplDefinitionsBase is only used in type positions (function parameter annotations), not at runtime. Although this doesn't currently cause issues, using import type follows TypeScript best practices and ensures compatibility with stricter compiler settings like verbatimModuleSyntax.

♻️ Proposed fix
 import {
   encode as rbcEncode,
   decode as rbcDecode,
   encodeForMultisigning as rbcEncodeForMultisigning,
   encodeForSigning as rbcEncodeForSigning,
   encodeForSigningClaim as rbcEncodeForSigningClaim,
-  XrplDefinitionsBase,
   encodeForSigningBatch as rbcEncodeForSigningBatch,
 } from 'ripple-binary-codec'
+import type { XrplDefinitionsBase } from 'ripple-binary-codec'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/xrpl/src/utils/index.ts` around lines 17 - 25, The import currently
brings in XrplDefinitionsBase at runtime; change it to a type-only import so the
symbol is not emitted at runtime. Replace the existing import that includes
XrplDefinitionsBase with an import type for XrplDefinitionsBase (keeping the
other runtime imports as-is) so functions using XrplDefinitionsBase in parameter
annotations still compile under strict TS settings (e.g., verbatimModuleSyntax)
without importing the type at runtime.
packages/xrpl/src/client/index.ts (1)

863-890: ⚠️ Potential issue | 🟠 Major

Missing definitions parameter in hashSignedTx call.

At line 883, hashSignedTx(signedTx) is called without passing this.definitions. Since the transaction was signed using custom definitions via getSignedTx, the hash computation should also use the same definitions to correctly decode/encode the transaction.

Proposed fix
-    const txHash = hashes.hashSignedTx(signedTx)
+    const txHash = hashes.hashSignedTx(signedTx, this.definitions)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/xrpl/src/client/index.ts` around lines 863 - 890, The call to
hashSignedTx(signedTx) omits the custom transaction definitions used when
signing, so update the hash calculation to pass the same definitions object
(this.definitions) — i.e., call hashes.hashSignedTx(signedTx, this.definitions)
— so the computed txHash matches the encoding used in getSignedTx; adjust the
reference in the function that returns waitForFinalTransactionOutcome(...) to
use the corrected txHash.
packages/xrpl/src/sugar/submit.ts (1)

238-274: ⚠️ Potential issue | 🟠 Major

Missing definitions parameter in wallet.sign() call.

At line 273, wallet.sign(tx).tx_blob is called without passing definitions. Since getSignedTx receives definitions in its options and uses it for decoding unsigned string transactions (line 266), the signing step should also use the same definitions to properly encode custom transaction types.

Proposed fix
-  return wallet.sign(tx).tx_blob
+  return wallet.sign(tx, false, definitions).tx_blob
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/xrpl/src/sugar/submit.ts` around lines 238 - 274, The getSignedTx
function calls wallet.sign(tx).tx_blob without passing the definitions option,
so custom transaction types decoded earlier (via decode(..., definitions)) may
be mis-encoded; update the signing call in getSignedTx to pass the same
definitions object to wallet.sign (i.e., call wallet.sign(tx, definitions) and
return its tx_blob) and ensure the function imports/uses the definitions
parameter consistently alongside decode and client.autofill.
packages/xrpl/src/models/transactions/transaction.ts (1)

262-270: ⚠️ Potential issue | 🟠 Major

validateBaseTransaction blocks custom transaction types before validateTxAgainstCustomDefinitions can be invoked.

The customDefinitions parameter is intended to support custom transaction types, but validateBaseTransaction (line 269) runs unconditionally before the switch statement and rejects any TransactionType not in the built-in TRANSACTION_TYPES array. This prevents the default case (line 586) from ever handling custom types with validateTxAgainstCustomDefinitions. Either skip validateBaseTransaction for custom types, or move the TransactionType check to occur only after attempting custom definition validation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/xrpl/src/models/transactions/transaction.ts` around lines 262 - 270,
The unconditional call to validateBaseTransaction in validate prevents custom
transaction types from reaching validateTxAgainstCustomDefinitions; update
validate so it first checks if customDefinitions is provided and the
transaction.TransactionType is not in TRANSACTION_TYPES, and in that case skip
validateBaseTransaction and attempt validateTxAgainstCustomDefinitions (or
alternatively move the built-in TRANSACTION_TYPES check to after the
switch/default branch), ensuring validateTxAgainstCustomDefinitions is invoked
for custom types before rejecting unknown TransactionType values; look for the
validate function, validateBaseTransaction, validateTxAgainstCustomDefinitions,
and TRANSACTION_TYPES symbols to implement this control flow change.
🧹 Nitpick comments (1)
packages/xrpl/src/sugar/submit.ts (1)

66-70: Consider: isAccountDelete decodes without definitions.

At line 69, isAccountDelete(signedTransaction) is called, and this function (lines 305-307) decodes string transactions without definitions. While AccountDelete is a standard transaction type so this won't cause functional issues, it's inconsistent with the pattern established elsewhere in this file.

Proposed fix for consistency

Update isAccountDelete to accept and use definitions:

-function isAccountDelete(transaction: Transaction | string): boolean {
-  const tx = typeof transaction === 'string' ? decode(transaction) : transaction
+function isAccountDelete(
+  transaction: Transaction | string,
+  definitions?: XrplDefinitionsBase,
+): boolean {
+  const tx =
+    typeof transaction === 'string'
+      ? decode(transaction, definitions)
+      : transaction
   return tx.TransactionType === 'AccountDelete'
 }

And update the call site at line 69:

-    fail_hard: isAccountDelete(signedTransaction) || failHard,
+    fail_hard: isAccountDelete(signedTransaction, definitions) || failHard,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/xrpl/src/sugar/submit.ts` around lines 66 - 70, The call to
isAccountDelete(signedTransaction) omits the consistent use of ripple
definitions; update the isAccountDelete function signature to accept a
definitions parameter and use it when decoding the signed transaction (modify
isAccountDelete to decode with the provided definitions), then update the
SubmitRequest creation (the code that builds request with command:'submit',
tx_blob:signedTxEncoded, fail_hard:...) to call
isAccountDelete(signedTransaction, definitions) so the decode is consistent with
other decoders in this file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/xrpl/HISTORY.md`:
- Around line 140-142: Remove the duplicate "### Added" heading in the 3.1.0
section of HISTORY.md: locate the repeated "### Added" header and merge its list
item(s) into the existing "### Added" block (keeping the entry "Custom
definitions support for `util.encode`, `util.decode`, `util.encodeForSigning`
and `Wallet.sign`" under that single header), then delete the redundant header
so there is only one "### Added" section for that version.

---

Outside diff comments:
In `@packages/xrpl/src/client/index.ts`:
- Around line 863-890: The call to hashSignedTx(signedTx) omits the custom
transaction definitions used when signing, so update the hash calculation to
pass the same definitions object (this.definitions) — i.e., call
hashes.hashSignedTx(signedTx, this.definitions) — so the computed txHash matches
the encoding used in getSignedTx; adjust the reference in the function that
returns waitForFinalTransactionOutcome(...) to use the corrected txHash.

In `@packages/xrpl/src/models/transactions/transaction.ts`:
- Around line 262-270: The unconditional call to validateBaseTransaction in
validate prevents custom transaction types from reaching
validateTxAgainstCustomDefinitions; update validate so it first checks if
customDefinitions is provided and the transaction.TransactionType is not in
TRANSACTION_TYPES, and in that case skip validateBaseTransaction and attempt
validateTxAgainstCustomDefinitions (or alternatively move the built-in
TRANSACTION_TYPES check to after the switch/default branch), ensuring
validateTxAgainstCustomDefinitions is invoked for custom types before rejecting
unknown TransactionType values; look for the validate function,
validateBaseTransaction, validateTxAgainstCustomDefinitions, and
TRANSACTION_TYPES symbols to implement this control flow change.

In `@packages/xrpl/src/sugar/submit.ts`:
- Around line 238-274: The getSignedTx function calls wallet.sign(tx).tx_blob
without passing the definitions option, so custom transaction types decoded
earlier (via decode(..., definitions)) may be mis-encoded; update the signing
call in getSignedTx to pass the same definitions object to wallet.sign (i.e.,
call wallet.sign(tx, definitions) and return its tx_blob) and ensure the
function imports/uses the definitions parameter consistently alongside decode
and client.autofill.

In `@packages/xrpl/src/utils/index.ts`:
- Around line 17-25: The import currently brings in XrplDefinitionsBase at
runtime; change it to a type-only import so the symbol is not emitted at
runtime. Replace the existing import that includes XrplDefinitionsBase with an
import type for XrplDefinitionsBase (keeping the other runtime imports as-is) so
functions using XrplDefinitionsBase in parameter annotations still compile under
strict TS settings (e.g., verbatimModuleSyntax) without importing the type at
runtime.

---

Nitpick comments:
In `@packages/xrpl/src/sugar/submit.ts`:
- Around line 66-70: The call to isAccountDelete(signedTransaction) omits the
consistent use of ripple definitions; update the isAccountDelete function
signature to accept a definitions parameter and use it when decoding the signed
transaction (modify isAccountDelete to decode with the provided definitions),
then update the SubmitRequest creation (the code that builds request with
command:'submit', tx_blob:signedTxEncoded, fail_hard:...) to call
isAccountDelete(signedTransaction, definitions) so the decode is consistent with
other decoders in this file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 354528f1-7d81-4bcf-95f8-3a5e29abab72

📥 Commits

Reviewing files that changed from the base of the PR and between 54f55fa and 006a3cb.

📒 Files selected for processing (17)
  • packages/ripple-binary-codec/README.md
  • packages/xrpl/HISTORY.md
  • packages/xrpl/src/Wallet/index.ts
  • packages/xrpl/src/client/index.ts
  • packages/xrpl/src/models/transactions/common.ts
  • packages/xrpl/src/models/transactions/transaction.ts
  • packages/xrpl/src/sugar/submit.ts
  • packages/xrpl/src/utils/hashes/hashLedger.ts
  • packages/xrpl/src/utils/index.ts
  • packages/xrpl/test/fixtures/requests/index.ts
  • packages/xrpl/test/fixtures/requests/signAsCustomDefinition.json
  • packages/xrpl/test/fixtures/responses/index.ts
  • packages/xrpl/test/fixtures/responses/signAsCustomDefinition.json
  • packages/xrpl/test/fixtures/responses/signCustomDefinition.json
  • packages/xrpl/test/fixtures/rippled/customDefinition.json
  • packages/xrpl/test/fixtures/rippled/index.ts
  • packages/xrpl/test/wallet/index.test.ts

Comment thread packages/xrpl/HISTORY.md Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
packages/xrpl/src/Wallet/utils.ts (1)

93-93: Minor JSDoc formatting inconsistency.

The @param definitions is missing the hyphen separator that other parameters in this function use (e.g., @param tx -, @param privateKey -).

📝 Proposed fix
-   * `@param` definitions Custom rippled types to use instead of the default. Used for sidechains and amendments.
+   * `@param` definitions - Custom rippled types to use instead of the default. Used for sidechains and amendments.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/xrpl/src/Wallet/utils.ts` at line 93, Update the JSDoc for the
function in packages/xrpl/src/Wallet/utils.ts so the `@param` entry for
definitions matches the other param lines (include the " - " hyphen separator);
locate the JSDoc block that contains `@param` tx -, `@param` privateKey - and change
the `@param` definitions line to "@param definitions - Custom rippled types to use
instead of the default. Used for sidechains and amendments." to keep formatting
consistent.
packages/xrpl/src/Wallet/index.ts (1)

361-361: Minor JSDoc formatting inconsistency.

The @param definitions is missing the hyphen separator that other parameters in this method use (e.g., @param transaction -, @param multisign -).

📝 Proposed fix
-   * `@param` definitions Custom rippled types to use instead of the default. Used for sidechains and amendments.
+   * `@param` definitions - Custom rippled types to use instead of the default. Used for sidechains and amendments.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/xrpl/src/Wallet/index.ts` at line 361, Update the JSDoc for the
Wallet constructor/factory in Wallet/index.ts so the `@param` entry for
definitions uses the same hyphen-separated format as the other params (e.g.,
match style used by `@param` transaction - and `@param` multisign -); locate the
JSDoc block above the Wallet constructor or related function and add the missing
" - " after "definitions" and include the brief description text to keep
formatting consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/xrpl/src/Wallet/index.ts`:
- Line 361: Update the JSDoc for the Wallet constructor/factory in
Wallet/index.ts so the `@param` entry for definitions uses the same
hyphen-separated format as the other params (e.g., match style used by `@param`
transaction - and `@param` multisign -); locate the JSDoc block above the Wallet
constructor or related function and add the missing " - " after "definitions"
and include the brief description text to keep formatting consistent.

In `@packages/xrpl/src/Wallet/utils.ts`:
- Line 93: Update the JSDoc for the function in
packages/xrpl/src/Wallet/utils.ts so the `@param` entry for definitions matches
the other param lines (include the " - " hyphen separator); locate the JSDoc
block that contains `@param` tx -, `@param` privateKey - and change the `@param`
definitions line to "@param definitions - Custom rippled types to use instead of
the default. Used for sidechains and amendments." to keep formatting consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7af2c47a-8234-44d6-850e-4c02915d364d

📥 Commits

Reviewing files that changed from the base of the PR and between 0373902 and 137f82e.

📒 Files selected for processing (2)
  • packages/xrpl/src/Wallet/index.ts
  • packages/xrpl/src/Wallet/utils.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/xrpl/src/models/transactions/transaction.ts`:
- Around line 261-264: The Batch branch in the export function
validate(transaction: Record<string, unknown>, customDefinitions?:
XrplDefinitionsBase) calls validate(...) recursively for inner transactions but
does not pass along the customDefinitions parameter; update the recursive
validate calls inside the Batch handling (and the similar call at the second
occurrence around the other Batch branch) to forward the customDefinitions
argument so inner/custom transaction types are validated against the provided
XrplDefinitionsBase rather than defaults.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e00dcb52-4e2a-4b13-bc6e-8d8eea092347

📥 Commits

Reviewing files that changed from the base of the PR and between 137f82e and 6ae5337.

📒 Files selected for processing (3)
  • packages/xrpl/src/models/transactions/common.ts
  • packages/xrpl/src/models/transactions/transaction.ts
  • packages/xrpl/test/wallet/index.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/xrpl/test/wallet/index.test.ts

Comment thread packages/xrpl/src/models/transactions/transaction.ts
Comment thread packages/xrpl/HISTORY.md Outdated
@kuan121
Copy link
Copy Markdown
Collaborator

kuan121 commented Apr 3, 2026

/ai-review

Copy link
Copy Markdown

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Choose a reason for hiding this comment

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

Two bugs flagged inline: definitions not forwarded to submitRequest (line 790 in client/index.ts) causing silent failures for custom types, and a design gap where custom transaction types bypass all field-level validation in transaction.ts.

Review by Claude Opus 4.6 · Prompt: V13

Comment thread packages/xrpl/src/client/index.ts Outdated
} = {},
): Promise<SubmittableTransaction | string> {
if (isSigned(transaction)) {
if (isSigned(transaction, definitions)) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

If definitions is undefined, isSigned decodes via standard codec which can't handle custom types — may silently return true for an unsigned custom transaction. This is the downstream consequence of the missing definitions arg in client/index.ts line 790; fixing that call site resolves this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

fixed via b5aff79

throw new ValidationError(
`Invalid field TransactionType: ${tx.TransactionType}`,
)
if (!customDefinitions?.transactionNames.includes(tx.TransactionType)) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Custom transaction types skip all field-level validation — only validateBaseTransaction runs. Document this limitation and consider a hook for registering field validators for custom types.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/xrpl/src/client/index.ts (1)

878-898: ⚠️ Potential issue | 🟠 Major

submitAndWait still drops this.definitions in submitRequest and hashSignedTx.

getSignedTx is passed definitions, but the subsequent submitRequest(this, signedTx, opts?.failHard) (line 890) and hashes.hashSignedTx(signedTx) (line 898) do not receive this.definitions. For custom transaction types this can cause decode/hash failures or a hash mismatch vs. what Wallet.sign produced — so waitForFinalTransactionOutcome may never find the tx. The same applies to submit at line 805. (This was raised in a prior review for submitRequest.)

Suggested change
-    const response = await submitRequest(this, signedTx, opts?.failHard)
+    const response = await submitRequest(
+      this,
+      signedTx,
+      opts?.failHard,
+      this.definitions,
+    )
     ...
-    const txHash = hashes.hashSignedTx(signedTx)
+    const txHash = hashes.hashSignedTx(signedTx, this.definitions)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/xrpl/src/client/index.ts` around lines 878 - 898, The submitAndWait
(and submit) flow currently passes this.definitions into getSignedTx but fails
to pass definitions into submitRequest and hashes.hashSignedTx, which breaks
custom types/hashes; update calls to submitRequest(this, signedTx,
opts?.failHard) and hashes.hashSignedTx(signedTx) to include this.definitions
(or pass a merged opts.definitions) so both submitRequest and hashSignedTx
receive the same definitions used to build the signedTx, and apply the same fix
in the submit function to ensure consistent decoding/hashing for custom
transaction types.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/xrpl/src/client/index.ts`:
- Around line 229-234: Client.definitions is declared but not exposed via
ClientOptions; add an optional definitions?: XrplDefinitionsBase to the
ClientOptions type/interface and assign this.options.definitions (or
options.definitions) to this.definitions in the Client constructor, following
the pattern used for feeCushion/maxFeeXRP, and ensure any internal uses (e.g.,
submit and submitAndWait) read from this.definitions rather than only from
mutated instances so the value is available immediately after new Client(...).

---

Duplicate comments:
In `@packages/xrpl/src/client/index.ts`:
- Around line 878-898: The submitAndWait (and submit) flow currently passes
this.definitions into getSignedTx but fails to pass definitions into
submitRequest and hashes.hashSignedTx, which breaks custom types/hashes; update
calls to submitRequest(this, signedTx, opts?.failHard) and
hashes.hashSignedTx(signedTx) to include this.definitions (or pass a merged
opts.definitions) so both submitRequest and hashSignedTx receive the same
definitions used to build the signedTx, and apply the same fix in the submit
function to ensure consistent decoding/hashing for custom transaction types.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8484c7aa-15d0-4b2f-85a6-b59f20ba1164

📥 Commits

Reviewing files that changed from the base of the PR and between 6ae5337 and 0360c4e.

📒 Files selected for processing (8)
  • packages/xrpl/HISTORY.md
  • packages/xrpl/src/Wallet/index.ts
  • packages/xrpl/src/client/index.ts
  • packages/xrpl/src/models/transactions/transaction.ts
  • packages/xrpl/test/fixtures/responses/signAsCustomDefinition.json
  • packages/xrpl/test/fixtures/responses/signCustomDefinition.json
  • packages/xrpl/test/fixtures/rippled/customDefinition.json
  • packages/xrpl/test/wallet/index.test.ts
✅ Files skipped from review due to trivial changes (3)
  • packages/xrpl/test/fixtures/responses/signCustomDefinition.json
  • packages/xrpl/test/fixtures/responses/signAsCustomDefinition.json
  • packages/xrpl/HISTORY.md

Comment on lines +229 to +234
/**
* Custom rippled types to use instead of the default. Used for sidechains and amendments.
*
*/
public definitions: XrplDefinitionsBase | undefined

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Client.definitions is never wired into ClientOptions.

The new public field is declared but there is no way to set it at construction — users must mutate client.definitions = ... after new Client(...). Consider exposing it through ClientOptions (e.g., options.definitions) and assigning it in the constructor, mirroring feeCushion/maxFeeXRP. This also makes the behavior documentable and consistent with how the property is threaded into submit/submitAndWait.

Suggested change
 export interface ClientOptions extends ConnectionUserOptions {
   ...
   timeout?: number
+  /**
+   * Custom rippled transaction type definitions for sidechains/amendments.
+   */
+  definitions?: XrplDefinitionsBase
 }
   public definitions: XrplDefinitionsBase | undefined
   ...
   public constructor(server: string, options: ClientOptions = {}) {
     ...
     this.feeCushion = options.feeCushion ?? DEFAULT_FEE_CUSHION
     this.maxFeeXRP = options.maxFeeXRP ?? DEFAULT_MAX_FEE_XRP
+    this.definitions = options.definitions
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/xrpl/src/client/index.ts` around lines 229 - 234, Client.definitions
is declared but not exposed via ClientOptions; add an optional definitions?:
XrplDefinitionsBase to the ClientOptions type/interface and assign
this.options.definitions (or options.definitions) to this.definitions in the
Client constructor, following the pattern used for feeCushion/maxFeeXRP, and
ensure any internal uses (e.g., submit and submitAndWait) read from
this.definitions rather than only from mutated instances so the value is
available immediately after new Client(...).

tequdev and others added 2 commits April 23, 2026 11:26
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
typeof transaction === 'string'
? // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- converts JsonObject to correct Transaction type
(decode(transaction) as unknown as SubmittableTransaction)
(decode(transaction, definitions) as unknown as SubmittableTransaction)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Severity: MEDIUM

getSignedTx passes definitions to decode() here and to isSigned() above, but the subsequent wallet.sign(tx) call (line 273) does not receive definitions. For custom transaction types, this means the transaction is decoded with custom definitions but signed/encoded with default definitions, producing incorrect signatures or encoding failures.
Helpful? Add 👍 / 👎

💡 Fix Suggestion

Suggestion: On line 273, pass definitions as the third argument to wallet.sign(). The Wallet.sign() method accepts definitions as its third parameter (after multisign). Change:

return wallet.sign(tx).tx_blob

to:

return wallet.sign(tx, undefined, definitions).tx_blob

This ensures that custom transaction types are signed and encoded using the same custom definitions that were used for decoding and isSigned() checks earlier in the function.

const signedTx = await getSignedTx(this, transaction, opts)
const signedTx = await getSignedTx(this, transaction, {
...opts,
definitions: this.definitions,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Severity: MEDIUM

submitAndWait passes this.definitions to getSignedTx here, but omits it from the subsequent submitRequest() and hashSignedTx() calls below. Compare with submit() which correctly passes this.definitions to submitRequest (line 824). This causes isSigned check, encoding, and hash computation to use wrong (default) definitions for custom types.
Helpful? Add 👍 / 👎

💡 Fix Suggestion

Suggestion: Pass this.definitions to both submitRequest and hashes.hashSignedTx in the submitAndWait method, matching the pattern used in submit():

  1. On line 909, change:
    const response = await submitRequest(this, signedTx, opts?.failHard)
    to:
    const response = await submitRequest(this, signedTx, opts?.failHard, this.definitions)

  2. On line 917, change:
    const txHash = hashes.hashSignedTx(signedTx)
    to:
    const txHash = hashes.hashSignedTx(signedTx, this.definitions)

This ensures that custom definitions are used for the isSigned check, encode call in submitRequest, and the decode/encode calls in hashSignedTx, consistent with how submit() already passes this.definitions on line 824.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants