# Session Handoff: cq - CBOR Query Tool for Cardano

## Project Overview

`cq` is a CLI tool for inspecting and querying Cardano transactions encoded in CBOR format - think "jq for Cardano CBOR." It addresses a real pain point from the 2025 Cardano Developer Survey where developers lack good CLI tooling for debugging CBOR transactions. The tool parses transactions from file/hex/stdin, supports dot-notation queries with wildcards (e.g., `outputs.*.address`), formats addresses as bech32, and provides pretty terminal output with colors or JSON for piping.

---

## Current Status: Phase 2 Complete - Ready for Release

The tool is fully functional with comprehensive features implemented and tested:

- **44 unit tests** - All passing
- **35 integration tests** - All passing
- **Build is clean** - No warnings
- **4 test fixtures** - Real preprod transactions covering diverse scenarios

### What Was Completed This Session

1. **Fixed CML API compile errors** - Resolved 13 errors with CML 6.0 field names:
   - `UnitInterval` uses `.start`/`.end` not `.numerator`/`.denominator`
   - Conway cert types use `deposit` not `coin` field
   - `DRep::AlwaysAbstain`/`AlwaysNoConfidence` are struct variants
   - `RewardAddress.to_address()` takes ownership - must clone first

2. **Implemented certificates extraction** - All Babbage + Conway types in `engine.rs`

3. **Implemented withdrawals extraction** - With bech32 reward address formatting

4. **Added pretty output sections** - Certificates table, Withdrawals table in `pretty.rs`

5. **Fetched real test fixtures from preprod** via Koios API:
   - `preprod_plutus.cbor` - Plutus tx with multi-assets, collateral, inline datum
   - `pool_registration.cbor` - Pool registration certificate
   - `drep_registration.cbor` - Conway DRep registration

6. **Added 10 new integration tests** - Now 35 total (was 25)

7. **Added script_data_hash, collateral_return, total_collateral** - Extraction and display

---

## Design Decisions (Confirmed)

| Decision | Choice | Rationale |
|----------|--------|-----------|
| Era Support | Babbage + Conway only | 99%+ of current usage, ship fast, extend later |
| Hex Input | With/without 0x prefix | Common in Cardano tooling (cardano-cli, wallets) |
| Binary Display | Truncate with size | Show `<script: 2.3KB>` to preserve readability |
| Datum/Redeemer | Raw CBOR only (v1) | Avoid interpretation rabbit hole, tight scope |
| Test Fixtures | Real (preprod) + synthetic | Realistic data plus edge cases |
| Network Detection | Auto from address header | Address header byte: 0=testnet, 1=mainnet |
| Rust Edition | 2024 | User has Rust 1.92.0, latest stable |

---

## Technical Stack

### Cargo.toml Dependencies
```toml
clap = { version = "4.5", features = ["derive", "env"] }  # CLI parsing
cml-core = "6.0"      # Cardano Multiplatform Lib - core
cml-chain = "6.0"     # CML - chain types (Transaction, Address, etc.)
cml-crypto = "6.0"    # CML - crypto (TransactionHash, RawBytesEncoding)
ciborium = "0.2"      # CBOR diagnostic notation
hex = "0.4"           # Hex encoding/decoding
colored = "2.1"       # Terminal colors
comfy-table = "7.1"   # Pretty tables
serde = "1.0"         # Serialization
serde_json = "1.0"    # JSON output
thiserror = "2.0"     # Error derive macro
anyhow = "1.0"        # Error propagation
```

### Architecture
```
Input (file/hex/stdin) → Input Detection → CBOR Decoding → Query Engine → Formatter → Output
```

---

## CML API Notes (Critical for Future Development)

These are hard-won lessons from debugging CML 6.0:

- `RawBytesEncoding` trait must be imported for `.to_raw_bytes()` method
- `PolicyId` is at `cml_chain::PolicyId`, NOT `cml_chain::assets::PolicyId`
- `Value.multiasset` (not `multi_asset`)
- `NetworkId` is a struct with `.network` field, not an enum
- `TransactionMetadatum::Map` is a tuple struct wrapping entries, not named fields
- `Redeemers` doesn't have `.len()` directly
- `AuxiliaryData` doesn't have `plutus_v3_scripts()` accessor
- `UnitInterval` uses `.start`/`.end` not `.numerator`/`.denominator`
- Conway cert types use `deposit` not `coin` field
- `DRep::AlwaysAbstain`/`AlwaysNoConfidence` are struct variants with `encodings` field
- `RewardAddress.to_address()` takes ownership - must clone first

---

## File Structure

```
cq/
├── Cargo.toml                    # Dependencies configured
├── Cargo.lock                    # Locked dependencies
├── src/
│   ├── main.rs                   # CLI entry point, exit codes
│   ├── lib.rs                    # Library root, run() function
│   ├── cli.rs                    # Clap argument parsing, input detection
│   ├── error.rs                  # Error types with thiserror
│   ├── input/
│   │   ├── mod.rs                # Module root
│   │   ├── detect.rs             # InputSource enum, format heuristics
│   │   └── read.rs               # File/stdin/hex reading
│   ├── decode/
│   │   ├── mod.rs                # Module root
│   │   └── transaction.rs        # CML integration, DecodedTransaction
│   ├── query/
│   │   ├── mod.rs                # Module root
│   │   ├── path.rs               # QueryPath, PathSegment parsing
│   │   ├── shortcuts.rs          # Query alias expansion (17 shortcuts)
│   │   └── engine.rs             # Query execution, transaction_to_json (800+ lines)
│   └── format/
│       ├── mod.rs                # Module root
│       ├── json.rs               # JSON output
│       ├── raw.rs                # CBOR diagnostic notation
│       └── pretty.rs             # Colored terminal output with tables (600+ lines)
├── tests/
│   ├── cli.rs                    # 35 integration tests
│   └── fixtures/
│       ├── babbage_simple.cbor   # Simple ADA transfer (original)
│       ├── preprod_plutus.cbor   # Plutus tx (multi-asset, collateral, inline datum)
│       ├── pool_registration.cbor # Pool registration certificate
│       └── drep_registration.cbor # Conway DRep registration
└── SESSION_HANDOFF.md            # This file
```

---

## Key Files to Know

### `src/query/engine.rs` (Most Complex)
- `transaction_to_json()` - Converts CML Transaction to JSON for querying
- `certificate_to_json()` - Handles all 17 certificate types
- `drep_to_json()` - Conway DRep serialization
- `output_to_json()` - Handles Alonzo vs Conway output formats
- `execute_path_with_wildcards()` - Wildcard query expansion

### `src/query/shortcuts.rs`
Contains all 17 query shortcuts mapping (e.g., `fee` → `body.fee`)

### `src/format/pretty.rs`
- `format_full_transaction()` - Main pretty output
- `format_certificates()` - Certificate table
- `format_withdrawals()` - Withdrawals table
- `format_lovelace()` - ADA conversion with `--ada` flag

---

## All Query Shortcuts

| Shortcut | Expands To | Description |
|----------|------------|-------------|
| `fee` | `body.fee` | Transaction fee |
| `inputs` | `body.inputs` | Input UTxOs |
| `outputs` | `body.outputs` | Output UTxOs |
| `hash` | (computed) | Transaction hash |
| `metadata` | `auxiliary_data.metadata` | Transaction metadata |
| `witnesses` | `witness_set` | Signatures & scripts |
| `ttl` | `body.ttl` | Time to live |
| `mint` | `body.mint` | Minted assets |
| `certs` | `body.certs` | Certificates |
| `withdrawals` | `body.withdrawals` | Stake withdrawals |
| `collateral` | `body.collateral_inputs` | Collateral inputs |
| `required_signers` | `body.required_signers` | Required signers |
| `network_id` | `body.network_id` | Network ID |
| `validity_start` | `body.validity_interval_start` | Valid from slot |
| `script_data_hash` | `body.script_data_hash` | Plutus script data hash |
| `collateral_return` | `body.collateral_return` | Collateral return output |
| `total_collateral` | `body.total_collateral` | Total collateral amount |

---

## Certificate Types Supported

### Babbage Era
- `StakeRegistration`, `StakeDeregistration`, `StakeDelegation`
- `PoolRegistration`, `PoolRetirement`

### Conway Era (Governance)
- `RegCert`, `UnregCert`
- `VoteDelegCert`, `StakeVoteDelegCert`
- `StakeRegDelegCert`, `VoteRegDelegCert`, `StakeVoteRegDelegCert`
- `AuthCommitteeHotCert`, `ResignCommitteeColdCert`
- `RegDrepCert`, `UnregDrepCert`, `UpdateDrepCert`

---

## Usage Examples

```bash
# Show full transaction (pretty output)
cq tests/fixtures/babbage_simple.cbor

# Query specific field
cq fee tests/fixtures/babbage_simple.cbor           # 171,617
cq fee tests/fixtures/babbage_simple.cbor --ada     # 0.171617 ADA

# Query hash
cq hash tests/fixtures/babbage_simple.cbor

# Nested queries
cq outputs.0.address tests/fixtures/babbage_simple.cbor
cq outputs.0.value.coin tests/fixtures/babbage_simple.cbor --ada

# Wildcard queries
cq outputs.*.address tests/fixtures/babbage_simple.cbor

# JSON output
cq tests/fixtures/babbage_simple.cbor --json

# Stdin support
cat tests/fixtures/babbage_simple.cbor | cq
cat tests/fixtures/babbage_simple.cbor | cq fee

# Hex input
cq 84a40081825820852ec7f7...

# Validation mode
cq tests/fixtures/babbage_simple.cbor --check && echo "Valid!"

# Query certificates
cq certs tests/fixtures/pool_registration.cbor --json

# Query script data hash
cq script_data_hash tests/fixtures/preprod_plutus.cbor
```

---

## Running Tests

```bash
# Run all tests
cargo test

# Run only integration tests
cargo test --test cli

# Run specific test
cargo test test_pool_registration_certificate
```

---

## Remaining Tasks (Optional Enhancements)

| Task | Priority | Notes |
|------|----------|-------|
| **README.md** | High | Public documentation for GitHub release |
| **GitHub Actions CI** | High | Automated testing on push/PR |
| **cargo-dist setup** | Medium | Binary releases for macOS/Linux/Windows |
| **Performance verification** | Low | Confirm < 10ms startup, < 5ms decode |
| **Withdrawals fixture** | Low | Need real tx with stake withdrawals |
| **Minting fixture** | Low | Token minting transaction example |

---

## How to Fetch More Test Fixtures

Use Koios API to get real transactions from preprod:

```bash
# Get recent block transactions
curl -s 'https://preprod.koios.rest/api/v1/tip'
curl -s -X POST 'https://preprod.koios.rest/api/v1/block_txs' \
  -H 'Content-Type: application/json' \
  -d '{"_block_hashes": ["BLOCK_HASH"]}'

# Get transaction CBOR
curl -s -X POST 'https://preprod.koios.rest/api/v1/tx_cbor' \
  -H 'Content-Type: application/json' \
  -d '{"_tx_hashes": ["TX_HASH"]}'

# Save to fixture
echo "CBOR_HEX" | xxd -r -p > tests/fixtures/new_fixture.cbor
```

---

## Quick Commands

```bash
# Build
cargo build

# Build release
cargo build --release

# Run on fixture
cargo run -- tests/fixtures/babbage_simple.cbor

# Run tests
cargo test

# Check for warnings
cargo clippy
```

---

## Plan File Location

Full implementation plan: `/home/grishmin/.claude/plans/iterative-growing-fairy.md`

---

## Session Context

This session continued from a previous context where the MVP was complete. The focus was on Phase 2 improvements:

1. Fixing broken `certs` and `withdrawals` shortcuts (had no backend)
2. Adding comprehensive test fixtures from preprod
3. Adding Conway governance support
4. Adding Plutus-related fields (script_data_hash, collateral_return)

All Phase 2 goals were achieved. The tool is ready for public release with optional polish items remaining.
