feat: add Single Asset Vault support (XLS-0065)#47
Open
Patel-Raj11 wants to merge 11 commits into
Open
Conversation
Add the Single Asset Vault amendment to xrpl.js: - VaultCreate/Set/Delete/Deposit/Withdraw/Clawback transaction models with validation, flags, and full wiring (transaction union, validate switch, exports, txToFlag map) - Vault ledger object plus optional VaultID on AccountRoot and DomainID on MPTokenIssuance, wired into the LedgerEntry union and filters - vault_info request/response, ledger_entry `vault` selector, and account_objects `vault` filter - STNumber (Number, type_code 9) serialized type in ripple-binary-codec - hashVault keylet utility, 'V' ledger space, and VaultCreate owner-reserve base-fee autofill Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…hVault Adds model validation tests for the six vault transactions, known-answer encode/decode and round-trip tests for the STNumber serialized type, and a hashVault ledger-index derivation test. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…integration tests STNumber values were being serialized with the Large arithmetic mantissa scale ([10^18, 10^19-1], log 18), but rippled serializes the STNumber wire format using the Small scale ([10^15, 10^16-1], log 15). The mismatch made rippled re-normalize the decoded Number on the receiving side, so the signature it recomputed never matched the one the SDK signed, and every VaultCreate carrying an AssetsMaximum (or any Number field) was rejected with "fails local checks: Invalid signature." Verified byte-for-byte against rippled's own serialization across a range of values. Adds the XLS-65 vault integration suite (full public-XRP-vault lifecycle and a VaultClawback-against-XRP rejection), now passing end-to-end against the standalone rippled, and updates the codec known-answer encodings accordingly. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace Jest-only `it.each` in the STNumber codec tests with the `.forEach(... it())` pattern used elsewhere in ripple-binary-codec so the cases also run under Karma/Jasmine (`test:browser`). Apply prettier formatting and add the established `eslint-disable max-statements` directive to the multi-step vault integration test. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Patel-Raj11
commented
Jun 30, 2026
Addresses PR review thread: #47 (comment)
Addresses PR review thread: #47 (comment)
Patel-Raj11
commented
Jun 30, 2026
Patel-Raj11
commented
Jun 30, 2026
Addresses PR review thread: #47 (comment)
Addresses PR review thread: #47 (comment)
Patel-Raj11
commented
Jun 30, 2026
Addresses PR review thread: #47 (comment)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reference Links
VaultDepositXRPLF/rippled#5452High Level Overview of Change
Adds client support for XLS-0065 Single Asset Vaults, so SDK users can create and manage a tokenized vault that pools one asset (XRP or IOU) from many depositors and represents ownership as MPT shares — building and signing the six vault transactions, parsing the new
Vaultledger entry, deriving a vault's ID before submission, and looking vaults up viavault_info.Categories of work in this PR:
Numbertype (STI_NUMBER = 9) live inripple-binary-codecand regenerates the codec definitions (new fields, transaction types 65–70, theVaultledger-entry type0x0084, and the newtec/terresults).VaultCreate,VaultSet,VaultDelete,VaultDeposit,VaultWithdraw, andVaultClawback, each wired into the centralvalidateswitch.tfVaultPrivate/tfVaultShareNonTransferable), and byte-length bounds (Data≤ 256 B, shareMPTokenMetadata≤ 1024 B).Vaultentry, plus an optionalVaultIDonAccountRootand an optionalDomainIDonMPTokenIssuance.vault_inforequest/response and avaultselector onledger_entry.hashVaultfor client-sideVaultIDderivation, and theVaultCreatebase-fee computation wired intoautofill.STNumbercodec,hashVault) and integration tests run against rippled.HISTORY.mdupdated in bothxrplandripple-binary-codec.Context of Change
This PR tracks the SingleAssetVault amendment (rippled #5224) and its prerequisite
STNumberserialized type (#5121). Vault shares are an MPT issued by a pseudo-account (XLS-0064), so the SDK reuses its existing MPT surface for shares and adds only the vault-specific transactions, ledger entry, andvault_infolookup. Where the XLS and the merged rippled implementation diverge, the SDK follows rippled — see Notes for reviewers.Type of Change
Did you update HISTORY.md?
Test Plan
STNumberencode/decode round-trip, andhashVaultID derivation.VaultCreate→VaultDeposit→VaultWithdraw→VaultDelete, parsing theVaultentry andvault_info), and aVaultClawbackagainst an XRP vault being rejected.account_objectstype: vaultfilter value — not implemented in the SDK (follow-up).tecPSEUDO_ACCOUNTis enforced by rippled only; no construction-time guard is added.Assetmodel still accepts MPT, and shares-as-MPT behavior remains covered).Notes for reviewers
isXRPLNumber(models/transactions/common.ts) validates withNumber.isFinite(Number(input)), so aNumberstring whose exponent exceeds JS double range (e.g."1e1000") is rejected at construction even though rippled would accept it.Dataand shareMPTokenMetadatabyte-length checks reject an empty hex string (byteLength < 1) although the spec states no minimum — an empty value is rejected rather than treated as omitted.VaultClawback.Amountis modeled as anAmount(STAmount), not aNumber.Scale(on theVaultentry /VaultCreate) andDestinationTag(onVaultWithdraw) from the XLS are intentionally not added — rippled does not implement them at these PRs.vault_listRPC (XLS §4.2) is not implemented because no Clio PR ships it; its request/response field shapes should be re-verified against the Clio implementation once it lands.