cardano-checkout-py/README.md
Kayos dc6378eda6 v0.1.0-dev: initial extraction from TradeCraft + new abstractions
Sulkta Coop's Python SDK for merchant-side Cardano payments +
NFT certificate-of-authenticity minting. Zero-custody by design.

Extracted from TradeCraft's services/cardano_*.py (2,400+ lines of
production Cardano-mainnet code) and restructured as an installable
Python package.

Package layout (cardano_checkout/):
- addresses.py   — lifted verbatim: CIP-1852 HD derivation, pure pycardano
- oracles.py     — lifted from cardano_price.py: Koios ADA/USD feed w/ 5m cache
- monitor.py     — lifted verbatim (SQLAlchemy-coupled; v0.2 refactors to Store)
- scheduler.py   — lifted verbatim (same refactor note)
- invoice.py     — NEW: framework-agnostic Invoice dataclass + lifecycle enum
- store.py       — NEW: InvoiceStore Protocol for pluggable persistence
- mint.py        — NEW: CIP-25 v2 metadata builder (works); tx submission stub for v0.2
- ipfs.py        — NEW: kubo HTTP client with primary-pin + mirror-pin pattern
- txbuild.py     — NEW: v0.2 stub for PyCardano / Ogmios tx construction

Design:
- Consumers provide xpub + InvoiceStore impl. SDK provides everything else.
- IPFS: local kubo for upload + serve, optional mirror pins for archival.
  Chromaticcraft pattern: Rackham kubo primary, Lucy kubo mirror.
- NFT: single native-script policy per merchant studio (CIP-25 v2, not CIP-68
  — full wallet coverage, no mutability needed for static certs). Policy skey
  stays under Sulkta cold-custody (Lucy pattern); signing is an external
  hand-off like ADAMaps payouts.

Tests: pure-module smoke tests pass for invoice, store-protocol, CIP-25
metadata envelope, IPFS client import, txbuild stub module. Address
derivation tests ship but require pycardano + will exercise in CI.

LICENSE: Apache-2.0 (matches upstream Cardano tooling).

Next (v0.2 scope):
- Refactor monitor + scheduler around InvoiceStore (drop SQLAlchemy coupling)
- Wire mint.mint_nft_cert to PyCardano + local Ogmios on Rackham
- txbuild: Ogmios chain-context + cold-signer hand-off shape
- chromaticcraft Phase 2 imports the SDK as its first external consumer
2026-04-23 18:04:00 -07:00

134 lines
5.7 KiB
Markdown

# cardano-checkout
Python SDK for merchant-side Cardano payments + NFT certificate-of-authenticity minting.
**Zero-custody by design:** the merchant provides a wallet xpub. The SDK derives
unique receive addresses per invoice, polls the chain for payment, and optionally
mints a CIP-25 NFT cert on confirmation. The platform never holds or moves funds.
Extracted from [TradeCraft](http://192.168.0.5:3001/TradeCraft/tradecraft)'s
`services/cardano_*.py` modules (2,400+ lines of production code running on the
Cardano mainnet) and packaged for reuse across the Sulkta Coop product family.
## Status
**v0.1.0-dev — alpha extraction.** Pure modules lifted verbatim from TradeCraft.
DB-coupled modules (monitor, scheduler) ship with a `TODO: refactor to Store
protocol` marker — they work as-is when paired with TradeCraft's SQLAlchemy models
but will be refactored to the generic `InvoiceStore` Protocol in v0.2.
| Module | Status | Notes |
|---|---|---|
| `addresses` | ✅ stable | CIP-1852 HD derivation; pure pycardano |
| `oracles` | ✅ stable | ADA/USD price via Koios with 5-min cache |
| `invoice` + `store` | ✅ new | Framework-agnostic invoice + persistence Protocol |
| `mint` | ⏳ stub | CIP-25 v2 metadata builder works; tx submission in v0.2 |
| `ipfs` | ✅ working | kubo HTTP API client w/ optional mirror-pin |
| `monitor` | 🟡 SQLAlchemy-coupled | v0.2 target: refactor around `InvoiceStore` |
| `scheduler` | 🟡 SQLAlchemy-coupled | v0.2 target: same |
| `txbuild` | ❌ v0.2 | Full PyCardano tx construction via Ogmios |
## Design
```
┌────────────────────────────────────────────────────────┐
│ Merchant App │
│ (TradeCraft / chromaticcraft / your-product) │
└──────────────┬───────────────────────┬─────────────────┘
│ │
uses │ implements │ imports
▼ ▼
┌──────────────┐ ┌────────────────────────┐
│ InvoiceStore │ ◄────── │ cardano_checkout SDK │
│ (your DB) │ │ │
└──────────────┘ │ addresses ← pure │
│ oracles ← pure │
│ invoice ← dataclass │
│ monitor ← polls chain │
│ scheduler ← bg loop │
│ mint ← NFT cert │
│ ipfs ← upload │
│ txbuild ← PyCardano wrappers │
└────────────────────────┘
talks to │
┌────────────────────────┐
│ Koios + Ogmios + kubo │
└────────────────────────┘
```
The merchant app provides:
1. A wallet xpub (account-level extended public key).
2. An `InvoiceStore` implementation (SQLAlchemy, Postgres, SQLite, in-memory — whatever).
The SDK provides:
1. Address derivation from the xpub.
2. Per-invoice payment monitoring against Koios.
3. ADA ↔ USD price conversion.
4. CIP-25 v2 NFT cert minting (v0.2).
5. IPFS upload + pinning for NFT image metadata.
## Quick start
```python
import asyncio
from cardano_checkout import addresses, oracles
# Derive a receive address for invoice #42
addr = addresses.derive_address(
xpub_hex="<your wallet xpub>",
index=42,
network="mainnet",
)
# Convert a USD price to lovelace at current market
async def main() -> None:
lovelace = await oracles.convert_usd_to_lovelace(99.00)
ada = lovelace / 1_000_000
print(f"Customer owes {ada:.4f} ADA for $99")
asyncio.run(main())
```
## IPFS: bake-then-mirror pattern
The SDK's `IPFSClient` expects a local kubo daemon (typically in the same
Docker image as the web app) for upload and primary pin, and takes an
optional list of mirror endpoints to `pin add` the CID on a second node
for archival redundancy.
Typical chromaticcraft deployment:
```python
from cardano_checkout import ipfs
client = ipfs.IPFSClient(
api_url="http://127.0.0.1:5001", # local kubo in the same container
mirror_api_urls=["http://192.168.254.5:5001"], # Lucy's kubo over the LAN/VPN
)
cid = await client.add(photo_bytes, filename="order-0001.jpg")
# Image now served by Rackham (low latency) AND pinned on Lucy (durability)
```
## NFT cert-of-authenticity design
One minting policy per merchant studio. Policy is a native script (no Plutus
required), optionally time-locked to make "no more editions after X" a
cryptographically verifiable claim.
CIP-25 v2 metadata. Single NFT per order. Policy skey never leaves the custody
host (Lucy in Sulkta's pattern). The SDK builds the metadata envelope + tx;
external signer does the signature.
## Installation
```
pip install 'cardano-checkout[sqlalchemy]' # if you're using SQLAlchemy
pip install cardano-checkout # core only
```
## License
Apache-2.0 — matches upstream Cardano tooling.