feat(treasury): CrossmintTreasury server SDK + client read service#1845
Draft
AngelPaella wants to merge 2 commits into
Draft
feat(treasury): CrossmintTreasury server SDK + client read service#1845AngelPaella wants to merge 2 commits into
AngelPaella wants to merge 2 commits into
Conversation
Region-agnostic server-side SDK for the 2026-05-11/treasury/* API. Mirrors
the CrossmintAuth shape: from(crossmint) factory, apiClient-driven, typed
errors. Server-key only (rejects ck_* at construction).
Methods:
- createPayout(req, { idempotencyKey? }) / getPayout(id)
- createOfframp(req, { idempotencyKey? }) / getOfframp(id)
- registerHifiOfframpAccount(req) — US rail
- registerOpenPaydBeneficiary(req) — EU rail
- listAccounts() / getBalances() / listTransactions({ kind?, limit?, cursor? })
Highlights:
- Idempotency-Key built in. Auto-gen UUIDv4 per write; caller can override
for derived-key lineage.
- Public types defined locally in treasury/types.ts (no dep on the backend
monorepo's @crossmint/products-payments-types workspace package).
- CrossmintTreasuryError carries stable `code` field — match on code, not
message. Common codes documented inline.
- TREASURY_API_VERSION = "2026-05-11" pinned. Future contract bumps land
as parallel class surfaces, not mutations.
Tests: 11 new in CrossmintTreasury.test.ts (Idempotency-Key header,
URL-encoding, query-string building, error-shape decoding, raw-payload
preservation on typed errors). 47 total @crossmint/server-sdk tests
green (was 36, +11).
…ase 10.2 — SDK delta) Companion to the server-sdk Treasury surface (88b8f56). Two pieces: (1) New `createCrossmintTreasuryClient` factory in client-sdk-base. Read-only methods (getPayout, getOfframp, listTransactions, getBalances, listAccounts) for browser / RN flows that hold a `ck_*` client key and just need to poll status. Writes stay server-side where compliance + idempotency belong. Follows the existing factory-pattern of paymentMethodManagementService — consumers pass a pre-constructed CrossmintApiClient, the factory returns the typed surface. Types are loose `unknown` projections here — the client polling facade returns the server-shape directly; consumers typically already have the typed shapes from @crossmint/server-sdk/treasury or their own backend response types. Keeping types minimal avoids a dep edge from client-base to server-sdk. (2) Refresh server errors.ts with the codes added in crossbit-main Phase 9.2-apps (`1edfd638dc`) and 11.3 (`8ccee1c7f1`): - treasury.offramp.currency_unsupported (400) - treasury.account.not_provisioned (400, EU path) - treasury.account.misconfigured (400, missing env) - treasury.account.unavailable (500) - treasury.region.* / treasury.route.unsupported (400/500) - treasury.settlement_chain.unresolved (400) Documented that treasury.offramp.eu_workflow_pending was removed in 9.2-apps — the EU saga is now live and returns a real `pending` envelope. Not in scope (deferred): - EU offramp Model A two-call wrapper (createOfframpWithSignerPrompt) — backend currently kicks off the workflow on POST without a separate /authorize endpoint, per the 9.2-apps simplification. If Model A surfaces as load-bearing later, expose the wrapper then. - Treasury write methods on the client SDK — intentional; writes belong on the server boundary.
🦋 Changeset detectedLatest commit: faff008 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
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.
Summary
Public SDK surface for the B2B Treasury API (
/api/2026-05-11/treasury/*). Companion to the crossbit-main backend PR.packages/server/src/treasury/CrossmintTreasury.ts(commit88b8f56b): server-side SDK class with full write + read surface.sk_*keys only —apiKeyExpectations.usageOrigin: "server"rejects client keys at the API client level. Auto-Idempotency-Keywith caller override; typedCrossmintTreasuryErrorwith stablecodefield. Methods:createPayout/getPayout,createOfframp/getOfframp,registerHifiOfframpAccount,registerOpenPaydBeneficiary,listAccounts,getBalances,listTransactions. 11 vitest tests.packages/client/base/src/services/treasury/(commitfaff0086): factory-based read-only client surface for browser / RN flows holding ack_*key. Methods:getPayout,getOfframp,listTransactions,getBalances,listAccounts. Writes intentionally NOT exposed — compliance + idempotency stay server-side.packages/server/src/treasury/errors.ts(commitfaff0086): refreshed JSDoc with the error codes added in crossbit-main Phase 9.2-apps + 11.3 (treasury.offramp.currency_unsupported,treasury.account.not_provisioned,treasury.account.misconfigured,treasury.region.*,treasury.route.unsupported,treasury.settlement_chain.unresolved). Removedtreasury.offramp.eu_workflow_pending— no longer thrown since the EU saga went live in 9.2-apps.API version pinning
TREASURY_API_VERSIONis pinned to2026-05-11in both packages. When the backend bumps to a later dated version, add a new class (e.g.CrossmintTreasury2027) rather than mutating the existing one — consumers pin SDK versions and a wire-version bump is a breaking change.Not in scope
createOfframpWithSignerPrompt) — backend currently kicks off the workflow on POST without a separate/authorizeendpoint per the 9.2-apps simplification. If Model A becomes load-bearing in product, expose the wrapper then.Test plan
pnpm --filter @crossmint/server-sdk test:vitestgreenpnpm --filter @crossmint/client-sdk-base buildclean (no type errors)createPayoutagainst staging returns 200 with the typed response shapegetOfframppolls correctly from a browser with ack_*key