TRACE Example App
Full-stack SAP Fiori app showing how ODATANO drops Cardano into enterprise workflows. Tracks pharmaceutical batches manufacturer → distributor → pharmacy with NFTs as on-chain proof and CIP-30 browser wallet signing.
Highlights
- Batch NFT minting: Manufacturer mints one NFT per batch with on-chain datum (Plutus V3, Aiken)
- Chain of custody: Each handoff is a Plutus spend with a continuing-output datum update
- Document anchoring: SHA-256 hashes of certs / lab reports / cold-chain telemetry via CIP-20 metadata
- Public verification: Anyone can verify a batch’s full custody chain on-chain
- Zero key custody: All signing in the user’s browser wallet
Stack
| Layer | Tech |
|---|---|
| Smart contract | Aiken (Plutus V3) |
| Network | Cardano preview |
| Chain gateway | @odatano/core (CAP plugin) |
| Backend | SAP CAP v9, Node.js, TypeScript |
| Database | SQLite (dev) / SAP HANA (prod) |
| Frontend | Freestyle SAPUI5 (sap_horizon) |
| Signing | CIP-30 (Nami, Eternl, Lace) |
Signing Flow
1. User clicks "Mint NFT"
2. App → OData action { unsignedCbor, buildId }
3. App → wallet.signTx(cbor) wallet popup
4. User confirms { signedCbor }
5. App → SubmitSigned { txHash, status: "SUBMITTED" }
6. Background poll (30 s) status: "CONFIRMED" | "FAILED"
Smart Contract
Datum: ChainOfCustody { manufacturer, current_holder, batch_id, step }
Redeemer: Action::Transfer { next_holder }
Mint policy: Only the parameterized manufacturer VKH can mint, exactly 1 token per tx.
Spend validator: Transfer requires the current holder’s signature + a continuing output with updated datum.
Quick Start
git clone https://github.com/ODATANO/TRACE && cd TRACE
npm install
# change dummy blockfrost api key in package.json
npm run deploy
Open http://localhost:4004/trace/webapp/index.html.
Data Model
Participants (Manufacturer | Distributor | Pharmacy | Regulator)
└──< Batches (DRAFT → MINTED → IN_TRANSIT → DELIVERED | RECALLED)
├──< OnChainAssets (policyId, assetName, UTxO ref)
├──< ProofEvents (MINT, TRANSFER, VERIFY, DOCUMENT_ANCHOR)
└──< DocumentAnchors (doc hash, type, cold-chain temps)