Skip to content

feat(facade): unified Tx3ClientBuilder for §3.3/§3.6 parity#13

Merged
scarmuega merged 3 commits into
mainfrom
feat/unified-builder
May 24, 2026
Merged

feat(facade): unified Tx3ClientBuilder for §3.3/§3.6 parity#13
scarmuega merged 3 commits into
mainfrom
feat/unified-builder

Conversation

@scarmuega
Copy link
Copy Markdown
Contributor

Summary

Ports the unified-builder pattern from rust-sdk into python-sdk so the §3.3/§3.6 facade rows of sdks/parity-matrix.md flip ❌→✅.

  • New Tx3ClientBuilder (with Protocol.client() + from_parts(...) seeders, trp / trp_endpoint / with_header / with_profile / with_party / with_parties / with_party_unchecked / with_env_value setters, single build() terminal).
  • Tx3Client now owns the deconstructed protocol parts; with_profile is builder-only (removed from the built client per §3.6); tx(name) raises UnknownTxError at call site.
  • TxBuilder is source-agnostic — both dynamic and codegen flows drive the same resolve() path.
  • New BuilderError family + MissingTrpEndpointError; UnknownPartyError re-parented from ResolutionErrorBuilderError (both still extend Tx3Error).
  • Codegen template (.trix/client-lib/__init__.py.hbs) wraps Tx3ClientBuilder.from_parts(...); per-party setters route through with_party_unchecked; profiles emitted as individual SdkProfile consts with a typed Profile str-Enum.
  • Top-level re-exports add Tx3ClientBuilder, Profile, BuilderError, MissingTrpEndpointError, ClientOptions.

Spec references: sdks/sdk-spec/api-surface/facade.md §3.3, §3.4, §3.6; sdks/sdk-spec/codegen/generated-surface.md §C.3a–d.

Breaking changes

  • Tx3Client(protocol, trp, ...) direct construction is gone — use protocol.client()...build() instead.
  • Tx3Client.with_profile(name) removed — call with_profile on the builder.
  • tx(name) raises UnknownTxError at call site instead of deferring to resolve().
  • UnknownPartyError's parent class changed (ResolutionErrorBuilderError).

Notes

  • Tx3ClientBuilder._trp_client(client) is an internal test escape hatch (not part of the public API) — lets unit tests inject a mock TRP client without going through ClientOptions. Documented inline.
  • Migrated pre-existing test_add_witness.py and test_errors.py to the new builder API. test_facade.py rewritten with 17 builder-focused tests.

Test plan

  • All modified files py_compile clean
  • pytest tests/ --ignore=tests/e2e46/46 pass
  • tx3c codegen against sdk/tests/fixtures/transfer.tii renders cleanly and the rendered __init__.py syntax-compiles
  • codegen-check.sh will fail in CI until this lands on PyPI — the script installs tx3-sdk from PyPI, which is still v0.11.0 without Tx3ClientBuilder. Expected for a template flip.

🤖 Generated with Claude Code

scarmuega and others added 3 commits May 24, 2026 12:46
….6 parity

Adds Tx3ClientBuilder with the two seeding entry points (Protocol.client()
for the dynamic flow and Tx3ClientBuilder.from_parts(...) for the codegen
flow), the mandatory trp/trp_endpoint setters, optional with_profile /
with_party / with_parties / with_party_unchecked / with_header /
with_env_value, and a single build() terminal that raises
MissingTrpEndpointError, UnknownProfileError, or UnknownPartyError.

New BuilderError class family under Tx3Error makes the builder errors
discriminable. Removes with_profile from the built Tx3Client (profile
selection is builder-only per §3.6); Tx3Client.tx(name) raises UnknownTxError
at the call site instead of deferring to resolve().

TxBuilder is now source-agnostic: holds the TIR envelope, env, parties, and
args directly so the dynamic and codegen flows drive an identical resolve()
path.

Codegen template wraps Tx3ClientBuilder.from_parts(...) instead of
re-implementing client state. Generated Client adds only the typed per-tx
Params dataclasses, per-tx methods, per-party setters (routing through
with_party_unchecked), embedded TIR / SdkProfile constants, and (when
profiles are declared) a typed Profile str-Enum.

Builder exposes an internal _trp_client(client) escape hatch for tests to
inject mock TRP clients without going through ClientOptions — not part of
the public API.

Top-level re-exports add Tx3ClientBuilder, Profile, BuilderError,
MissingTrpEndpointError, ClientOptions.

Existing tests (test_add_witness, test_errors) migrated to the builder API;
test_facade rewritten with 17 new tests covering the builder contract.
46/46 unit tests pass.

Spec: sdks/sdk-spec/api-surface/facade.md §3.3, §3.4, §3.6;
      sdks/sdk-spec/codegen/generated-surface.md §C.3a–d.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Updates the quick-start example to use protocol.client()...build() instead
of Tx3Client(protocol, trp). Expands the concepts table with
Tx3ClientBuilder, Profile, and BuilderError. Adds a from_parts walkthrough
under "Skipping the runtime .tii (codegen flow)".

sdk/README.md is a symlink to the root README, so both stay in sync.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The e2e harness still constructed Tx3Client directly via the removed
`Tx3Client(protocol, trp).with_profile(...)` shape. Routes through
`protocol.client().trp_endpoint(...).with_profile(...).with_header(...).build()`
instead; `dmtr-api-key` is now attached via the builder's `with_header` setter
rather than a separately-constructed TrpClient (the builder now owns TRP
client construction and lifetime).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@scarmuega scarmuega merged commit 556729b into main May 24, 2026
2 of 3 checks passed
@scarmuega scarmuega deleted the feat/unified-builder branch May 24, 2026 16:16
scarmuega added a commit that referenced this pull request May 24, 2026
Aligns the python-sdk package version with the fleet's 0.12 release train
(rust-sdk workspace is already at 0.12.0). The unified Tx3ClientBuilder
landed in #13 and is a breaking change — per
sdks/sdk-spec/release-policy.md any change to MAJOR or MINOR must be
coordinated across all SDKs.

Bumps both pyproject.toml `version` and the runtime `__version__` constant
in tx3_sdk/__init__.py.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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