v0.1.0-dev: initial public extraction + new abstractions
This commit is contained in:
commit
e38120cf11
17 changed files with 2429 additions and 0 deletions
134
README.md
Normal file
134
README.md
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
# 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue