Skip to content

feat(client): support Perps internal transfers - #330

Draft
kartojal wants to merge 1 commit into
mainfrom
feature/dev-628-support-owner-signed-perps-internal-transfers-and-history-in
Draft

feat(client): support Perps internal transfers#330
kartojal wants to merge 1 commit into
mainfrom
feature/dev-628-support-owner-signed-perps-internal-transfers-and-history-in

Conversation

@kartojal

Copy link
Copy Markdown
Contributor

Summary

  • add owner-signed SecureClient.transferPerpsCollateral with one-attempt unknown-outcome semantics
  • add normalized PerpsSession.listInternalTransfers pagination and forward-compatible transfer types
  • preserve machine-readable non-400 rejection identifiers and add release changesets

Contract notes

  • internal-transfer amounts are decimalized token units; "100.00" is signed and sent without base-unit conversion
  • repeated signatures are replay-rejected, not idempotently replayed, so the action exposes no retry control
  • history pagination deduplicates inclusive timestamp boundaries; the upstream timestamp-only 500-row limit remains documented in DEV-628

Verification

  • pnpm build
  • pnpm test (528 tests passed; client type tests clean)
  • pnpm lint
  • pnpm typecheck

Linear: DEV-628
Upstream: perpetuals#1270

@osr21

osr21 commented Aug 31, 2026

Copy link
Copy Markdown

One recovery detail worth making explicit for callers: the one-attempt/unknown-outcome contract is safe, but after a timeout the action cannot return the new transferId, so consumers need a documented correlation strategy before they can decide whether manual intervention is required.

A practical recipe using the surface in this PR would be:

  1. Generate a unique caller correlation value (32 hex chars works well) and put it in the signed label before calling transferPerpsCollateral.
  2. Record the local send window, amount, direction/counterparty and label.
  3. On an unknown outcome, do not resubmit. Poll listInternalTransfers({ start, end }) over a bounded window and match the full tuple, primarily the unique label.
  4. If one match appears, treat its transferId as the recovered acknowledgement; if zero/multiple matches remain after the window, surface an explicit uncertain state for operator review.

This matters because amount + counterparty alone are not unique for treasury/rebalancing workloads, while the timestamp-only pagination ceiling noted here makes an unbounded history scan unreliable. If labels are not guaranteed unique server-side, the docs should say that clearly and present the tuple match as reconciliation rather than idempotency. A short example/TSDoc block would make the otherwise good “never retry unknown outcomes” guidance actionable.

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