# Cardano Client Bindings — full documentation > Generated from the docsite. One file, all pages, for AI ingestion. --- # Using Cardano Client Bindings with AI Agents Source: https://pages.bloxbean.com/cardano-client-bindings/ai/ Cardano Client Bindings is designed to be **AI-friendly**: the API surface is small and identical across all four languages, transactions are plain YAML, and everything an agent needs fits in one document. Point your AI tool at the artifacts below and it can write correct code against the bindings without any training data about them. ## TL;DR Point your AI agent at the **[AI Starter Pack](../starter-pack/)** or the full docs dump: | File | When to use it | |---|---| | **[`/ai/starter-pack.md`](../starter-pack/)** | The single highest-leverage artifact. Distills the offline contract, the API groups, TxPlan YAML with the intent catalog, error codes, signing roles, and the known limitations agents trip over. | | **[`/llms.txt`](https://pages.bloxbean.com/cardano-client-bindings/llms.txt)** | Curated index of this docsite, following [llmstxt.org](https://llmstxt.org/). Small, agent-friendly. | | **[`/llms-full.txt`](https://pages.bloxbean.com/cardano-client-bindings/llms-full.txt)** | The full docsite concatenated as a single markdown file, for full-coverage ingestion. | ## Per-tool setup ### Claude Code (CLI) Drop the starter pack into your project as `CLAUDE.md` (or append it to an existing one): ```bash curl -o CLAUDE.md https://pages.bloxbean.com/cardano-client-bindings/ai/starter-pack.md ``` Claude Code reads `CLAUDE.md` at the start of every session, so the agent always has the bindings' contract in context. For multi-project setups, reference the hosted version from your global `~/.claude/CLAUDE.md`: ```markdown When working with cardano-client-lib bindings (Python/Go/Rust/JS `ccl` packages), follow https://pages.bloxbean.com/cardano-client-bindings/ai/starter-pack/ ``` ### Cursor Add a project rule: ```bash mkdir -p .cursor/rules curl -o .cursor/rules/ccl-bindings.mdc https://pages.bloxbean.com/cardano-client-bindings/ai/starter-pack.md ``` ### Continue (VS Code / JetBrains) Add a URL context provider in `.continue/config.json`: ```json { "contextProviders": [ { "name": "url", "params": { "url": "https://pages.bloxbean.com/cardano-client-bindings/llms-full.txt" } } ] } ``` ### ChatGPT / Claude.ai / other chat UIs Paste the starter pack (or attach it as a file) at the start of the conversation, then ask for what you need — e.g. *"Using cardano-client-lib for Python as described above, build and sign a stake-delegation transaction."* ## What agents get wrong without context These are the failure modes the starter pack exists to prevent: 1. **Inventing an online API** — the library never fetches or submits; chain data is an input, submission is your job. 2. **Calling the broken functions** — `tx.from_json`, `tx.sign_with_secret_key`, and `plutus.data_to_json`/`data_from_json` fail in the current release (GraalVM reflection gaps). 3. **Signing with the wrong keys** — certificates need `sign_tx_with_keys` with explicit roles, or the node rejects the transaction. 4. **Confusing `Network` values with on-chain network ids** — they're inverted for mainnet. 5. **Guessing TxPlan field names** — the intent catalog in the starter pack has the verified YAML shapes. 6. **Using Node.js for the JS wrapper** — it's Bun-only. --- # Cardano Client Bindings — AI Starter Pack Source: https://pages.bloxbean.com/cardano-client-bindings/ai/starter-pack/ > **Read this entire document before generating code that uses these bindings.** It distills the offline contract, the API surface, the TxPlan YAML transaction format, error codes, signing rules, and the known limitations that AI agents most commonly get wrong. This pack is optimized for AI ingestion; the human-friendly guides are on the docsite. ## 1. What this is Cardano Client Bindings compiles the Java [Cardano Client Lib (CCL)](https://github.com/bloxbean/cardano-client-lib) into a native shared library (`libccl`) via GraalVM native-image, with four wrappers exposing the same functionality: | Language | Package | Entry object | Naming | |---|---|---|---| | Python ≥ 3.8 | `pip install cardano-client-lib`, `from ccl import CclLib` | `CclLib()` | `snake_case` | | Go ≥ 1.21 | `go get github.com/bloxbean/cardano-client-bindings/wrappers/go` | `ccl.New()` → `Bridge` | `PascalCase` | | Rust ≥ 1.70 | crate `cardano-client-lib` (import as `ccl`) | `ccl::Bridge::new()` | `snake_case`, methods return `Result` | | JavaScript | `bun add @bloxbean/cardano-client-lib` — **Bun only, never Node.js** | `new CclBridge()` | `camelCase` | All four have the same nine API groups — `account`, `address`, `crypto`, `tx`, `plutus`, `script`, `gov`, `wallet`, `quicktx` — the same error codes, and the same TxPlan YAML format. Semantics are identical; only naming idiom differs. ## 2. The offline contract (never violate this) - The library makes **no network calls** and **never submits transactions**. Do not invent fetch/submit methods on it. - Chain data (UTXOs, protocol parameters) is an **input** you pass to `quicktx.build`. Optional wrapper-side `Provider` objects (YaciProvider, BlockfrostProvider) fetch it for `quicktx.build_with` — those are plain HTTP helpers in the wrapper, not the native library. - Submission: POST the signed CBOR hex (as bytes) to any Blockfrost-compatible `/tx/submit` with `Content-Type: application/cbor`, using the language's own HTTP client. - Keys/mnemonics are inputs to each call; the library holds no state between calls beyond the loaded isolate. ## 3. Core workflow (build → sign → submit) ```python from ccl import CclLib, Network, YaciProvider with CclLib() as lib: # context manager; or lib.close() account = lib.account.create(Network.TESTNET) # {"mnemonic","base_address","enterprise_address","stake_address"} provider = YaciProvider() # or BlockfrostProvider(project_id, network="preprod") yaml = f""" version: 1.0 transaction: - tx: from: {account["base_address"]} intents: - type: payment address: addr_test1qz... amounts: - unit: lovelace quantity: "5000000" """ result = lib.quicktx.build_with(yaml, provider, account["base_address"]) # or fully offline: lib.quicktx.build(yaml, utxos, protocol_params, exec_units=None, additional_signers=0) # result = {"tx_cbor": str, "tx_hash": str, "fee": str} signed = lib.account.sign_tx(account["mnemonic"], result["tx_cbor"], Network.TESTNET) # submit `signed` yourself (bytes.fromhex → POST /tx/submit) ``` Go: `bridge.QuickTx.Build(yaml, utxos, params)` / `bridge.Account.SignTx(mnemonic, ccl.Testnet, 0, 0, txCbor)`. JS: `bridge.quicktx.build(yaml, utxos, params, null, additionalSigners)` / `bridge.account.signTx(mnemonic, TESTNET, 0, 0, txCbor)`. Rust: `bridge.quicktx().build(&yaml, &utxos, ¶ms, None, additional_signers)?` / Go: `bridge.QuickTx.Build(yaml, utxos, pp, additionalSigners)` — the count is **positional** in Go/Rust. **Argument-order gotcha:** Python's `sign_tx(mnemonic, tx_cbor, network, ...)` puts the transaction *before* the network; Go/JS/Rust use `(mnemonic, network, account_index, address_index, tx_cbor)`. ## 4. Networks `MAINNET = 0`, `TESTNET = 1`, `PREPROD = 2`, `PREVIEW = 3`. Required for every key-deriving call; validated before the FFI call. **These are CCL enum ordinals, NOT on-chain network ids** — inverted for mainnet: `Network.MAINNET == 0` but a mainnet address's on-chain `network_id` is `1`. Never feed `address.info()["network_id"]` into a `network` parameter. ## 5. Chain-data shapes UTXOs (list; quantities are **strings**): ```json [{ "tx_hash": "…64hex", "output_index": 0, "address": "addr_test1…", "amount": [ { "unit": "lovelace", "quantity": "100000000" }, { "unit": "", "quantity": "500" } ] }] ``` Protocol parameters: the standard Blockfrost-style object (`min_fee_a`, `min_fee_b`, `max_tx_size`, `key_deposit`, `pool_deposit`, `coins_per_utxo_size`, `price_mem`, `price_step`, `collateral_percent`, cost models, …). Unknown fields are ignored. Keep quantities as strings end-to-end (JS: avoid parsing them into `number`). ## 6. TxPlan YAML — transaction format One format for all wrappers. Skeleton: ```yaml version: 1.0 variables: # optional ${name} substitution to: addr_test1... context: # optional; for multi-sender compose fee_payer: addr_test1... transaction: - tx: from: addr_test1... # sender / default fee payer intents: - type: payment address: ${to} amounts: - unit: lovelace quantity: "5000000" # inputs: — collect_from / reference_input / script_collect_from # scripts: — native_script / validator ``` Verified intent shapes (field names matter — do not guess): ```yaml # Staking (sign with payment+stake) - type: stake_registration stake_address: stake_test1uq... - type: stake_deregistration stake_address: stake_test1uq... refund_address: addr_test1qz... - type: stake_delegation stake_address: stake_test1uq... pool_id: pool1... - type: stake_withdrawal reward_address: stake_test1uq... amount: 0 # full balance must be withdrawn; 0 when empty # DRep lifecycle (sign with payment+drep); credential = gov API verification_key_hash - type: drep_registration # drep_update identical; drep_deregistration drops anchors drep_credential_hex: <56hex> drep_credential_type: key_hash anchor_url: https://example.com/meta.json anchor_hash: <64hex> # Voting - type: voting_delegation # sign payment+stake address: stake_test1uq... drep_hex: "8102" # serialized DRep drep_type: abstain # abstain | no_confidence | key DRep - type: governance_proposal # sign payment gov_action_hex: "8106" # serialized GovAction (8106 = info) return_address: stake_test1uq... anchor_url: ... anchor_hash: <64hex> - type: voting # sign payment+drep voter_hex: 8202581c<28bytehex> # serialized Voter gov_action_tx_hash: <64hex> gov_action_index: 0 vote: "YES" # YES | NO | ABSTAIN # Native-script mint (sign payment; plus policy key if sig-keyed) - type: minting assets: [{ name: TestNFT, value: 1 }] # negative value burns receiver: addr_test1vz... script_hex: "820180" script_type: 0 # Metadata (value is a JSON string; labels are top-level keys) - type: metadata metadata: '{"674": {"msg": "hello"}}' # Treasury donation - type: donation current_treasury_value: 0 donation_amount: 1000000 # Explicit inputs (under `inputs:`, beside `intents:`) - type: collect_from utxo_refs: [{ tx_hash: <64hex>, output_index: 0 }] - type: reference_input refs: [{ tx_hash: <64hex>, output_index: 0 }] # Plutus spend (inputs + validator under scripts:) inputs: - type: script_collect_from utxo_refs: [{ tx_hash: <64hex>, output_index: 0 }] redeemer: { int: 0 } # PlutusData in JSON form datum: { int: 42 } # must hash to the locked output's datum_hash scripts: - type: validator role: spend # or: mint (with script_minting intent + policyId) cbor_hex: