cq 0.3.0

CBOR Query Tool for Cardano transactions - think 'jq for Cardano CBOR'
Documentation
# cq - CBOR Query Tool for Cardano

[![CI](https://github.com/karkigrishmin/cq/actions/workflows/ci.yml/badge.svg)](https://github.com/karkigrishmin/cq/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Crates.io](https://img.shields.io/crates/v/cq.svg)](https://crates.io/crates/cq)

**Think "jq for Cardano CBOR"** - A fast CLI tool to inspect and query Cardano transactions encoded in CBOR format.

Born from a real pain point in the [2025 Cardano Developer Survey](https://cardano.org): developers lack good CLI tooling for debugging CBOR transactions. `cq` fills that gap.

## Features

- **Parse transactions** from file, hex string, or stdin
- **Query with dot-notation** - `cq outputs.0.address tx.cbor`
- **Wildcard support** - `cq outputs.*.value tx.cbor`
- **Filter queries** - `cq 'outputs[value.coin > 1000000]' tx.cbor`
- **Plutus data decoding** - Datums and redeemers decoded to JSON
- **Address decoding** - `cq addr <bech32>` decodes any Cardano address
- **CIP metadata standards** - CIP-20 messages, CIP-25 NFTs, CIP-68 datum metadata
- **Asset name decoding** - Token names display as UTF-8 when valid
- **Bech32 addresses** - Auto-formatted for readability
- **Pretty terminal output** - Colors, tables, smart truncation
- **JSON output** - Perfect for piping to `jq`
- **Babbage + Conway eras** - Full support including governance
- **Blazing fast** - Native Rust, no WASM overhead

## Installation

### From crates.io (recommended)

```bash
cargo install cq
```

### Pre-built binaries

```bash
# Linux/macOS
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/karkigrishmin/cq/releases/latest/download/cq-installer.sh | sh

# Windows (PowerShell)
powershell -ExecutionPolicy Bypass -c "irm https://github.com/karkigrishmin/cq/releases/latest/download/cq-installer.ps1 | iex"
```

Or download directly from [GitHub Releases](https://github.com/karkigrishmin/cq/releases).

## Upgrading

To upgrade to the latest version:

### Check for updates
```bash
cq update
```

### Upgrade via cargo
```bash
cargo install cq --force
```

### Pre-built binaries
Re-run the installer script - it always fetches the latest version:
```bash
# Linux/macOS
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/karkigrishmin/cq/releases/latest/download/cq-installer.sh | sh

# Windows (PowerShell)
powershell -ExecutionPolicy Bypass -c "irm https://github.com/karkigrishmin/cq/releases/latest/download/cq-installer.ps1 | iex"
```

### From source

```bash
cargo install --git https://github.com/karkigrishmin/cq
```

## Quick Start

```bash
# Show full transaction (pretty output)
cq transaction.cbor

# Query specific fields
cq fee tx.cbor                    # Transaction fee
cq fee tx.cbor --ada              # Fee in ADA (not lovelace)
cq hash tx.cbor                   # Transaction hash

# Nested queries
cq outputs.0.address tx.cbor      # First output address
cq outputs.0.value.coin tx.cbor   # First output ADA amount
cq inputs.0.transaction_id tx.cbor

# Wildcard queries
cq outputs.*.address tx.cbor      # All output addresses
cq outputs.*.value tx.cbor        # All output values

# Different output formats
cq tx.cbor --json                 # JSON output
cq tx.cbor --raw                  # CBOR diagnostic notation

# Validation mode
cq tx.cbor --check && echo "Valid!"

# Read from stdin
cat tx.cbor | cq
cat tx.cbor | cq fee --ada

# Hex input (with or without 0x prefix)
cq 84a400818258203b40265111d8bb3c3c...
cq 0x84a400818258203b40265111d8bb3c3c...

# Filter queries (v0.2.0+)
cq 'outputs[value.coin > 1000000]' tx.cbor        # Outputs > 1 ADA
cq 'outputs[address.address ~ "addr1"]' tx.cbor   # Mainnet outputs
cq 'outputs[datum != null]' tx.cbor               # Outputs with datum

# Datum queries - decode Plutus data (v0.3.0+)
cq 'outputs.0.datum.value' tx.cbor --json         # Decoded datum structure
cq 'outputs.0.datum.value.constructor' tx.cbor    # Constructor index
cq 'outputs.0.datum.value.fields.0.int' tx.cbor   # First field (integer)
cq 'outputs.0.datum.value.fields.1.bytes' tx.cbor # Second field (bytes)

# Redeemer queries (v0.3.0+)
cq redeemers tx.cbor --json                       # All redeemers with decoded data
cq 'redeemers.0.purpose' tx.cbor                  # Redeemer purpose (spend/mint/etc)
cq 'redeemers.0.data' tx.cbor --json              # Decoded redeemer data
cq 'redeemers.0.ex_units' tx.cbor --json          # Execution units (mem/steps)

# Reference inputs (CIP-31, v0.3.0+)
cq reference_inputs tx.cbor --json                # Reference inputs (read-only)

# Decode any address (v0.2.0+)
cq addr addr1qy8ac7qqy0vtulyl7wntmsxc6wex80gvcyjy33qffrhm7sh927ysx5sftuw0dlft05dz3c7revpf7jx0xnlcjz3g69mq4afdhv
cq addr stake1uyehkck0lajq8gr28t9uxnuvgcqrc6070x3k9r8048z8y5gh6ffgw --json
```

## 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 |
| `reference_inputs` | `body.reference_inputs` | Reference inputs (CIP-31) |
| `redeemers` | `witness_set.redeemers` | Script redeemers |
| `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 |

## Example Output

```
$ cq transaction.cbor

Transaction
  Hash: 0edb4eac0b992ac4af71a2a52f41ab63c806e0ef4e5c5d9c7348ea03cf9a9e4e
  Valid: true

Body
  Fee: 171,617 lovelace

Inputs (1)
┌───┬─────────────────┬───────┐
│ # ┆ Transaction ID  ┆ Index │
╞═══╪═════════════════╪═══════╡
│ 0 ┆ 852ec7...73fa31 ┆ 0     │
└───┴─────────────────┴───────┘

Outputs (2)
┌───┬──────────────────────────┬────────────────────────┬───────┐
│ # ┆ Address                  ┆ Value                  ┆ Datum │
╞═══╪══════════════════════════╪════════════════════════╪═══════╡
│ 0 ┆ addr_test1vp9...jg52l8g8 ┆ 9,594,993,891 lovelace ┆ -     │
│ 1 ┆ addr_test1qz8...h7q3xhdsk│ 1,500,000 lovelace     ┆ -     │
└───┴──────────────────────────┴────────────────────────┴───────┘

Witnesses
  VKey signatures: 2
```

## Fetching Real Transactions

Use [Koios API](https://koios.rest) to fetch CBOR from mainnet/testnet:

```bash
# Mainnet
curl -s -X POST 'https://api.koios.rest/api/v1/tx_cbor' \
  -H 'Content-Type: application/json' \
  -d '{"_tx_hashes": ["YOUR_TX_HASH"]}' | jq -r '.[0].cbor' | xxd -r -p | cq

# Preprod testnet
curl -s -X POST 'https://preprod.koios.rest/api/v1/tx_cbor' \
  -H 'Content-Type: application/json' \
  -d '{"_tx_hashes": ["YOUR_TX_HASH"]}' | jq -r '.[0].cbor' | xxd -r -p | cq
```

**Pro tip** - Add this to your `.bashrc`:

```bash
cqtx() {
  curl -s -X POST 'https://api.koios.rest/api/v1/tx_cbor' \
    -H 'Content-Type: application/json' \
    -d "{\"_tx_hashes\": [\"$1\"]}" | jq -r '.[0].cbor' | xxd -r -p | cq "${@:2}"
}

# Usage: cqtx <tx_hash> [query] [flags]
# cqtx 31ed9234a830667a0152fbfe4a244f896f5aad459831a5620571465283ec5f0c
# cqtx 31ed9234... fee --ada
```

## Supported Certificate Types

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

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

## Exit Codes

| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | Validation failed (invalid CBOR/transaction) |
| 2 | Parse error |
| 3 | I/O error (file not found, etc.) |
| 4 | Query error (field not found, index out of bounds) |

## Comparison with Alternatives

| Feature | cq | cardano-cli | CQUISITOR | cbor.me |
|---------|-----|-------------|-----------|---------|
| Offline | Yes | Yes | No | No |
| Query syntax | Dot notation | Flags | GUI | N/A |
| JSON output | Yes | Yes | No | No |
| Scriptable | Yes | Yes | No | No |
| Pretty output | Yes | Limited | Yes | Yes |
| Install | `cargo install` | Heavy | Browser | Browser |

## Building from Source

```bash
git clone https://github.com/karkigrishmin/cq
cd cq
cargo build --release
./target/release/cq --help
```

### Requirements

- Rust 1.85+ (edition 2024)
- No system dependencies

### Running Tests

```bash
cargo test              # All tests (89 total)
cargo test --test cli   # Integration tests only
cargo test --lib        # Unit tests only
```

## Contributing

Contributions welcome! Please:

1. Fork the repository
2. Create a feature branch
3. Run `cargo test` and `cargo clippy`
4. Submit a PR

## License

MIT License - see [LICENSE](LICENSE) for details.

## Acknowledgments

- [CML (Cardano Multiplatform Lib)]https://github.com/dcSpark/cardano-multiplatform-lib for Cardano type parsing
- Inspired by the excellent [jq]https://stedolan.github.io/jq/ tool