Skip to content

feat: add SingleAssetVault support (XLS-65)#158

Draft
e-desouza wants to merge 7 commits intomainfrom
feat/xls-65-single-asset-vault
Draft

feat: add SingleAssetVault support (XLS-65)#158
e-desouza wants to merge 7 commits intomainfrom
feat/xls-65-single-asset-vault

Conversation

@e-desouza
Copy link
Copy Markdown
Collaborator

@e-desouza e-desouza commented Apr 3, 2026

Summary

Implements XLS-65 (SingleAssetVault) support for xrpl-rust.

New transaction types (6)

  • VaultCreate — Create a new vault with an Asset, optional AssetsMaximum, MPTokenMetadata, DomainID, WithdrawalPolicy, and Data
  • VaultSet — Update vault parameters (Data, AssetsMaximum, DomainID)
  • VaultDelete — Delete an empty vault by VaultID
  • VaultDeposit — Deposit assets into a vault
  • VaultWithdraw — Withdraw assets from a vault (with optional Destination and DestinationTag)
  • VaultClawback — Clawback assets from a vault holder

New ledger entry type

  • Vault (LedgerEntryType = 0x0084) — On-ledger vault object with Account, Asset, AssetsTotal, AssetsAvailable, AssetsMaximum, LPToken, Share, MPTokenIssuanceID, DomainID, and audit fields

Validation

  • VaultCreate derives ValidateCurrencies for Asset (Currency) field validation
  • VaultDeposit and VaultWithdraw derive ValidateCurrencies for Amount field validation

Registration

  • 6 transaction type variants added to TransactionType enum
  • LedgerEntryType::Vault (0x0084) added to enum
  • Module re-exports and integration tests included

Test plan

  • Serde roundtrip tests for all 6 transactions and Vault ledger entry
  • Builder pattern and new() constructor tests
  • get_transaction_type() variant tests
  • Optional field presence/absence tests
  • Integration tests in tests/transactions/
  • cargo fmt, cargo clippy --all-features, cargo test --release all pass
  • All 9 feature-matrix builds compile cleanly

Add six new transaction types for the XLS-65 single-asset vault
amendment: VaultCreate, VaultDelete, VaultDeposit, VaultWithdraw,
VaultClawback, and VaultSet. Each follows existing transaction
patterns with serde support, builder methods, and unit tests.
Add the Vault ledger object with LedgerEntryType::Vault (0x0084)
and the corresponding LedgerEntry::Vault variant. The Vault struct
models the on-ledger state including asset, share tokens, totals,
and metadata fields per the XLS-65 specification.
Add integration test files for all six XLS-65 vault transaction
types covering serde roundtrip, builder pattern, and validation.
These will be extended with live submission tests once XLS-65 is
available on devnet.
- vault_create: add missing Scale (UInt8) field
- vault_withdraw: add missing Destination and DestinationTag fields
- vault_clawback: change Amount from required Amount<'a> to Option<Cow<str>> (NUMBER type per spec)
- vault ledger: add missing Owner, LossUnrealized, ShareMPTID, WithdrawalPolicy, Scale, Sequence fields
Copy link
Copy Markdown
Collaborator Author

@e-desouza e-desouza left a comment

Choose a reason for hiding this comment

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

Went through the changes

Type mismatch on amount field will cause a compile error — see inline.


Review by ReviewBot 🤖

Review by Claude Opus 4.6 · Prompt: V12

VaultClawback.amount is Option<Cow<str>>, not Amount — fix test to use
string values. Add missing `scale` field to VaultCreate tests and
missing `destination`/`destination_tag` fields to VaultWithdraw tests.
Introduces a typed Flags enum for VaultCreate plus hex-blob and VaultID
validation across every vault transaction, closing the CRITICAL gaps
flagged during review.

- Add VaultCreateFlag with TfVaultPrivate (0x00010000) and
  TfVaultShareNonTransferable (0x00020000) per XLS-65. VaultCreate now
  uses CommonFields<'_, VaultCreateFlag> so flag bits serialize
  correctly instead of always emitting 0.
- Add vault_common module with validate_vault_id and validate_hex_blob
  helpers. Reused by VaultSet, VaultDelete, VaultDeposit, VaultWithdraw,
  and VaultClawback so VaultID (64 hex chars, ASCII hexdigits) is
  rejected at the client boundary instead of by rippled.
- VaultCreate.get_errors enforces XLS-65 blob caps: Data <= 256 bytes
  (512 hex chars), MPTokenMetadata <= 1024 bytes (2048 hex chars), and
  rejects non-hex characters.
- Vault ledger entry tests now assert raw PascalCase keys (Account,
  Owner, Asset, AssetsTotal, AssetsAvailable, ShareMPTID,
  WithdrawalPolicy, PreviousTxnID, PreviousTxnLgrSeq, ...) so silent
  renames that would break wire compatibility with rippled are caught.
- New unit tests: combined-flag bit serialization, oversized/non-hex
  Data and MPTokenMetadata rejection, invalid VaultID rejection
  (length and character class), and positive/negative paths for the
  shared helpers.

Gates (taskset -c 1-25 -j 25): cargo fmt check, cargo clippy
--all-features -D warnings, cargo test --release --lib all pass;
671 library tests green.
The rippleci/rippled:develop image updated after 2026-04-01 and broke
integration tests across all PRs (container exits before becoming healthy,
causing Connection refused on localhost:5005).

Pin to the last known-good digest and replace the simple until loop with
a bounded retry that checks container liveness, prints status per attempt,
and dumps container logs on failure.
pdp2121 pushed a commit that referenced this pull request Apr 21, 2026
… #3270) (#291)

## Summary

The `rippled` binary was renamed to `xrpld` upstream, and the
`rippleci/rippled` image stopped receiving updates. Our integration
tests across every open PR started failing because the published
`develop` image exited before becoming healthy (`Connection refused` on
`localhost:5005`, **0 passed / 41 failed**).

This PR mirrors the upstream fix in xrpl.js:
[XRPLF/xrpl.js#3270](XRPLF/xrpl.js#3270).
Switching to `rippleci/xrpld:develop` is the **actual root-cause fix**
rather than pinning an old digest of the deprecated image.

## Changes

`.github/workflows/integration_test.yml`:
- `RIPPLED_DOCKER_IMAGE` -> `XRPLD_DOCKER_IMAGE:
rippleci/xrpld:develop`.
- `docker run` simplified to `${IMAGE} --standalone` (the `xrpld` image
handles `mkdir` + launch internally; no more `bash -c "mkdir -p
/var/lib/rippled/db/ && rippled -a"` wrapper).
- Volume mount changed from `/etc/opt/ripple/` to `/etc/opt/xrpld/`.
- Container name: `rippled-service` -> `xrpld-service`.
- Removed the docker `--health-cmd` (which shelled out to the renamed
`rippled` CLI and always failed) in favour of a direct JSON-RPC poll
against `http://localhost:5005/`.
- Always dump container logs on the stop step for post-mortem
visibility.

`.ci-config/rippled.cfg` -> `.ci-config/xrpld.cfg`:
- `path=/var/lib/rippled/db/nudb` -> `path=/var/lib/xrpld/db/nudb`.
- `[database_path] /var/lib/rippled/db` -> `/var/lib/xrpld/db`.
- `[debug_logfile] /var/log/rippled/debug.log` ->
`/var/log/xrpld/debug.log`.

## Verification

Validated on throwaway PR #292 (now closed): **Integration Test green in
2m53s** on this exact workflow. Unit tests, Build & Lint, Quality Check
also pass.

## Related follow-up

The 7 in-flight PRs (#130, #131, #151, #153, #156, #157, #158) currently
carry a stopgap commit pinning `rippleci/rippled:develop` to a specific
digest. After this PR merges to `main`, those branches should:
1. Rebase on `main` to pick up the xrpld switch, or
2. Cherry-pick this commit and drop the stopgap digest pin.

## Test plan

- [x] Validated end-to-end on PR #292
- [x] Build & Lint, Unit Test, Integration Test, Quality Check all pass
- [ ] Merge and confirm subsequent PRs inherit the fix without manual
cherry-pick

## Credit

Approach lifted from @ckeshava's
[xrpl.js#3270](XRPLF/xrpl.js#3270).
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.

1 participant