cardano-checkout-py/README.md

134 lines
5.8 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 [the host app](https://git.sulkta.com/example/host-app)'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 the host app.
DB-coupled modules (monitor, scheduler) ship with a `TODO: refactor to Store
protocol` marker — they work as-is when paired with the host app'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 │
│ (the host app / example-studio / 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 example-studio 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://mirror-node.example:5001"], # the cold host's kubo over the LAN/VPN
)
cid = await client.add(photo_bytes, filename="order-0001.jpg")
# Image now served by the hot host (low latency) AND pinned on the cold host (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 (the cold host 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.