Skip to content

Add contract error parsing and typed batch payload definitions - #1021

Merged
Jaydbrown merged 1 commit into
conduit-protocol:mainfrom
sunred-liu:feat/contract-error-parsing-and-batch-payload-types
Oct 20, 2026
Merged

Jaydbrown merged 1 commit into
conduit-protocol:mainfrom
sunred-liu:feat/contract-error-parsing-and-batch-payload-types

Conversation

@sunred-liu

Copy link
Copy Markdown
Contributor

closes #913
closes #915

Summary

Two related TypeScript improvements to the SDK.

1. parseContractError — contract error codes → typed errors (#913)

Soroban host errors surface as raw integers (e.g. Error(Contract, #12)), so
callers get no actionable message and cannot branch on the failure reason.

parseContractError(error, contract?, context?) extracts the numeric contract
error code from an unknown value and maps it to the matching typed error class:

Contract error Mapped to
stream #11 ClawbackDisabled ClawbackNotEnabledError
stream #1 NotAuthorized UnauthorizedStreamActionError (with operation + caller)
stream #2 StreamNotFound StreamNotFoundError (with streamId)
stream lifecycle codes InvalidStreamStateError (with operation)
factory #8 / #9 / #6 RateExceedsMaxError / DurationTooShortError / BackdatedStreamError
governor #2 InvalidParam GovernorInvalidParamError
any other known code ConduitError with the contract-scoped message

Design notes:

  • Error numbers are contract-scoped. The same numeric code means different
    things on the stream, factory and governor contracts, so the contract
    argument selects the catalogue to read. When it is omitted the code is
    auto-resolved only if exactly one contract defines it; otherwise a
    ContractError lists the candidates rather than reporting the wrong meaning.
  • No invented values. The richer stream errors carry a stream ID, an
    operation and a caller that cannot be recovered from the numeric code. They
    are only built when the caller supplies that context; otherwise a
    ConduitError with the correct message is returned.
  • Safe in a catch block. Errors without a contract error code (network
    failures, timeouts, user cancellations) are returned unchanged.

2. Typed batch payloads (#915)

Batch operations accepted loosely-shaped objects. Two dedicated payload types
now make the required fields explicit:

  • BatchStreamCreationPayload — requires recipient, token and
    depositAmount, so a missing recipient or a misformatted amount is a
    compile-time error.
  • BatchWithdrawPayload — requires streamId.

StreamsModule.createBatchStreams() and StreamsModule.batchWithdraw() use
the new types. The existing StreamConfig and BatchWithdrawItem names stay
as compatible aliases, so this is not a breaking change.

Verification

  • npx tsc --noEmit — no new type errors (the 12 pre-existing errors in
    client.ts / custom-fetch.ts / soroban.ts are unchanged from main).
  • npx vitest run — 18 new tests added (14 for parseContractError, 4 for
    the payload types), all passing. The 17 failing tests in
    custom-fetch* / relayer-stress / soroban-retry-after /
    streams.test.ts fail identically on main and are unrelated to this
    change.

closes conduit-protocol#913
closes conduit-protocol#915

Soroban host errors surface as raw integers (e.g. `Error(Contract, #12)`),
which makes them hard to diagnose.

- `parseContractError(error, contract?, context?)` extracts the numeric
  contract error code from an unknown value (host-error message, `{ code }`
  object, or `cause` chain) and maps it to the matching typed error class.
- Error numbers are contract-scoped, so the contract argument selects the
  catalogue to read. When it is omitted the code is only auto-resolved if
  exactly one contract defines it; otherwise a `ContractError` lists the
  candidates instead of guessing the wrong meaning.
- Richer stream errors (`StreamNotFoundError`, `UnauthorizedStreamActionError`,
  `InvalidStreamStateError`) are built when the caller supplies the matching
  context; otherwise a `ConduitError` with the correct contract-scoped message
  is returned.
- Errors without a contract error code are returned unchanged, so the helper
  is safe to call directly in a catch block.

Batch operations now have dedicated payload types:

- `BatchStreamCreationPayload` requires `recipient`, `token` and
  `depositAmount`, so a missing recipient or a misformatted amount is caught
  at compile time.
- `BatchWithdrawPayload` requires `streamId`.
- `StreamsModule.createBatchStreams()` and `StreamsModule.batchWithdraw()`
  use the new payload types; the existing `StreamConfig` and
  `BatchWithdrawItem` names remain as compatible aliases.
@Jaydbrown
Jaydbrown merged commit e49cb7b into conduit-protocol:main Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants