Skip to content

feat: add Ripple Custody full api support - #38

Open
pdp2121 wants to merge 1 commit into
mainfrom
add-ripple-custody-full-api
Open

feat: add Ripple Custody full api support#38
pdp2121 wants to merge 1 commit into
mainfrom
add-ripple-custody-full-api

Conversation

@pdp2121

@pdp2121 pdp2121 commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

High Level Overview of Change

  • Add custody.api.call — a typed, unsigned HTTP passthrough to any Ripple Custody v1 endpoint the SDK doesn't model as a first-class vertical.
  • Add custody.api.propose — the signed governed-intent counterpart; wraps any intent payload in a Core_Propose envelope, signs it, and submits it (e.g. releasing quarantined transfers) without a dedicated method.

Context of Change

  • Previously the Ripple Custody adapter exposed only verticals and kept its HTTP client private, so unmodeled endpoints (reading intents/domains/transfers, quarantine release) were unreachable.
  • api.call mirrors the existing Palisade passthrough (generated route map + operations types).
  • api.propose reuses the existing IntentSigner; the envelope build/sign logic is extracted into a shared buildProposeEnvelope that the native transaction path now also uses (no duplication, behavior unchanged).

Type of Change

  • New feature (non-breaking change which adds functionality)
  • 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)

Test Plan

  • Unit: new custody-api suite covering call routing/path-interpolation and propose envelope/signing/overrides; full unit tier green.
  • Contract (live sandbox): api.call reads (getMe, getAccounts), api.propose signed-envelope acceptance, and a non-mutating v0_ReleaseQuarantinedTransfers dry-run that validates the payload shape.
  • typecheck, lint, format, and the dual ESM+CJS build all pass.

for (const [key, value] of Object.entries(query)) {
if (value !== undefined) {
// Custody query params are scalars; skip null/undefined and non-scalars.
if (value !== undefined && value !== null && typeof value !== 'object') {

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.

Are arrays meant to be included or not? In line 24, Query = Record<string, unknown> so an array is allowed but this line (if (value !== undefined && value !== null && typeof value !== 'object') {) would drop any array.

targetDomainId: options.domainId,
id: intentId,

return buildProposeEnvelope(intentSigner, {

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.

If someone passes their own id but no matching options.id would a random id be generated for the envelope id? In that case the 2 values would diverge which goes against the added comment here. Is this divergence ok?

Comment on lines +22 to +37
const entries = []
let skipped = 0
for (const [path, item] of Object.entries(spec.paths ?? {})) {
for (const method of METHODS) {
const op = item[method]
if (op === undefined) continue
// openapi-typescript keys the generated `operations` off operationId, so an
// operation without one is neither typed nor routable — skip it and report
// the count rather than emitting an unusable entry.
if (op.operationId === undefined) {
skipped += 1
continue
}
entries.push([op.operationId, method.toUpperCase(), path])
}
}

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.

Is there a risk of a repeated operationIds? Looks like the generator tracks missing operationIds but has no check for duplicates. A duplicate operationId would produce duplicate CUSTODY_ROUTES object key

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.

2 participants