Tx3 SDK for Python
Project description
tx3-sdk (Python)
The official Python SDK for Tx3: a DSL and protocol suite for
defining and executing UTxO-based blockchain transactions declaratively. Load a
compiled .tii protocol, bind parties and signers, and drive the full
transaction lifecycle (resolve -> sign -> submit -> wait) through TRP.
This repository is organized as a monorepo. The publishable Python package lives in sdk/.
What is Tx3
Tx3 is a domain-specific language and protocol suite for declarative, type-safe UTxO transactions. Authors write .tx3 files describing parties, environment, and transactions; the toolchain compiles them to .tii artifacts that this SDK loads at runtime to drive the resolve → sign → submit → wait lifecycle through a TRP server. See the Tx3 docs for project context.
Installation
pip install tx3-sdk
Quick start
import asyncio
from tx3_sdk import CardanoSigner, Party, PollConfig, Protocol
async def main() -> None:
# 1) Load a compiled .tii protocol
protocol = Protocol.from_file("examples/transfer.tii")
# 2) Build a client: configure TRP, profile, and parties on the builder
sender_signer = CardanoSigner.from_mnemonic(
address="addr_test1qz...",
phrase="word1 word2 ... word24",
)
client = (
protocol.client()
.trp_endpoint("https://preprod.trp.tx3.dev")
.with_profile("preprod")
.with_party("sender", Party.signer(sender_signer))
.with_party("receiver", Party.address("addr_test1qz..."))
.build()
)
# 3) Build, resolve, sign, submit
submitted = await (
await (
await client.tx("transfer").arg("quantity", 10_000_000).resolve()
).sign()
).submit()
# 4) Wait for confirmation
status = await submitted.wait_for_confirmed(PollConfig.default())
print(f"Confirmed at stage: {status.stage}")
asyncio.run(main())
All fallible validation — TRP endpoint present, profile declared, every bound
party declared — happens inside build(), which raises MissingTrpEndpointError,
UnknownProfileError, or UnknownPartyError (all under the BuilderError family,
rooted at Tx3Error). Optional setters never raise, so chains stay fluent. Profile
selection is builder-only: there is no profile-switching method on the built
client. Switching profiles requires a new builder.
Concepts
| SDK Type | Glossary Term | Description |
|---|---|---|
Protocol |
TII / Protocol | Loaded .tii with transactions, parties, and profiles. protocol.client() returns a fresh Tx3ClientBuilder |
Tx3ClientBuilder |
Client builder | Fluent builder seeded by Protocol.client() or Tx3ClientBuilder.from_parts(...); absorbs all fallible validation in build() |
Tx3Client |
Facade | Output of Tx3ClientBuilder.build() — owns the deconstructed protocol parts, TRP client, profile, and party bindings |
TxBuilder |
Invocation builder | Source-agnostic; collects args and resolves transactions |
Party |
Party | Party.address(...) or Party.signer(...) |
Profile |
Profile | { environment, parties } value baked into the client; embedded by codegen plugins, decomposed from Protocol by from_protocol |
MissingTrpEndpointError / UnknownPartyError |
Builder errors | Raised by build(); subclass of BuilderError, rooted at Tx3Error |
Signer |
Signer | Protocol producing a TxWitness for a SignRequest |
SignRequest |
SignRequest | Input passed to Signer.sign: tx_hash_hex + tx_cbor_hex |
CardanoSigner |
Cardano Signer | BIP32-Ed25519 signer at m/1852'/1815'/0'/0/0 |
Ed25519Signer |
Ed25519 Signer | Generic raw-key Ed25519 signer |
ResolvedTx |
Resolved transaction | Output of resolve(), ready for signing |
SignedTx |
Signed transaction | Output of sign(), ready for submission |
SubmittedTx |
Submitted transaction | Output of submit(), pollable for status |
PollConfig |
Poll configuration | Poll attempts and delay for wait modes |
Advanced usage
Skipping the runtime .tii (codegen flow)
If you've run trix codegen to generate typed bindings, your generated Client
embeds the per-transaction TIR envelopes and per-profile data at codegen time —
no .tii artifact at runtime. Under the hood it seeds the same builder via
Tx3ClientBuilder.from_parts(transactions, profiles, known_parties) and routes
typed per-party setters through with_party_unchecked. You can also call
from_parts directly from hand-written code:
from tx3_sdk import ClientOptions, Party, Tx3ClientBuilder
client = (
Tx3ClientBuilder.from_parts(transactions, profiles, ["sender", "receiver"])
.trp(ClientOptions(endpoint="http://localhost:8000"))
.with_party_unchecked("sender", Party.signer(signer))
.build()
)
Low-level TRP client
from tx3_sdk import TrpClient
from tx3_sdk.trp import ResolveParams
trp = TrpClient(endpoint="http://localhost:8000", headers={"Authorization": "Bearer token"})
envelope = await trp.resolve(ResolveParams(tir=..., args={"quantity": 100}))
Custom Signer
Implement the Signer protocol. sign receives a SignRequest carrying both
the tx hash and the full tx CBOR; hash-based signers read tx_hash_hex,
tx-based signers (e.g. wallet bridges) read tx_cbor_hex.
from tx3_sdk import SignRequest, Signer
from tx3_sdk.signer import TxWitness
from tx3_sdk.signer.witness import vkey_witness
class MySigner(Signer):
def address(self) -> str:
return "addr_test1..."
def sign(self, request: SignRequest) -> TxWitness:
# sign request.tx_hash_hex with your key
return vkey_witness(public_key_hex="aabb", signature_hex="ccdd")
Manual witness attachment
When a witness is produced outside any registered signer — for example by an
external wallet app or a remote signing service — resolve the transaction
first, hand the resolved hash (or full tx CBOR) to the wallet, then attach
the returned witness before sign():
from tx3_sdk.signer.witness import vkey_witness
resolved = await client.tx("transfer").arg("quantity", 10_000_000).resolve()
# Hand resolved.hash (or resolved.tx_hex) to the external wallet and get
# back a witness. The wallet needs the resolved tx to sign.
witness = vkey_witness(public_key_hex="aabb", signature_hex="ccdd") # sign resolved.hash with external wallet
signed = await resolved.add_witness(witness).sign()
submitted = await signed.submit()
add_witness may be called any number of times; manual witnesses are appended after registered-signer witnesses in attach order. Note: ResolvedTx is a frozen dataclass, so add_witness returns a new instance.
Tx3 protocol compatibility
- TRP protocol version:
v1beta0 - TII schema version:
v1beta0
Testing
- Tests follow Python's idiomatic centralized layout under
sdk/tests/. - End-to-end (e2e) tests are marked with
@pytest.mark.e2eand selected by marker.
# from python-sdk/sdk
pytest -m "not e2e"
pytest tests/e2e -m e2e
License
Apache-2.0
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tx3_sdk-0.13.0.tar.gz.
File metadata
- Download URL: tx3_sdk-0.13.0.tar.gz
- Upload date:
- Size: 36.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
491a9175b394d9d0d7b5ea9c6fbf41e42cb43c0e6f74be2210f1576b227a6689
|
|
| MD5 |
7ee86054b0a3419528ff45a530412abc
|
|
| BLAKE2b-256 |
3558a6fc80ce268ea3d982b2425657585db05f600e21acc486b79d738e56aef7
|
File details
Details for the file tx3_sdk-0.13.0-py3-none-any.whl.
File metadata
- Download URL: tx3_sdk-0.13.0-py3-none-any.whl
- Upload date:
- Size: 37.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
937d657279eeead86a4e41dae2770786b04dba987938a8f47d8783b947b55dbc
|
|
| MD5 |
e1266c9fde6bba766b5a9aec2ddd9ed3
|
|
| BLAKE2b-256 |
8edb1c04adc7248ad0653fad7b5da775a7e2a759816db56f41819f521d7c3222
|