Skip to content

Commit 496682e

Browse files
authored
Merge pull request #236 from IntersectMBO/devex-sessions
docs: add Session 20 production SDK materials
2 parents 2409e02 + 97ac0b6 commit 496682e

5 files changed

Lines changed: 376 additions & 0 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"label": "Session 20: Building a Production Cardano SDK",
3+
"position": 20,
4+
"link": {
5+
"type": "generated-index",
6+
"description": "End-to-end walkthrough of production SDK practices on Cardano: from Aiken validators to a demo dApp, using the DCU Toolkit as the case study."
7+
}
8+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
title: "Session 20: Building a Production Cardano SDK: From Validators to dApp - Recordings"
3+
sidebar_label: Recordings
4+
slug: /working-group/q2-2026/sessions/20-cardano-production-sdk/recordings
5+
---
6+
7+
# Session 20: Building a Production Cardano SDK: From Validators to dApp - Recordings
8+
9+
**Session date:** 11 June 2026
10+
11+
## Recording 1 (2026/06/11)
12+
13+
🎥 **Building a Production Cardano SDK: From Validators to dApp**
14+
15+
<iframe
16+
src="https://www.youtube.com/embed/LgtSZ8vPGPU"
17+
title="Session 20: Building a Production Cardano SDK: From Validators to dApp"
18+
width="100%"
19+
height="480"
20+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
21+
allowfullscreen
22+
style={{border: 0, borderRadius: '12px', boxShadow: '0 16px 40px rgba(1, 40, 170, 0.18)'}}
23+
/>
24+
25+
**Watch on YouTube:** [Building a Production Cardano SDK: From Validators to dApp](https://www.youtube.com/watch?v=LgtSZ8vPGPU)
26+
27+
### Highlights
28+
29+
- How community savings groups work, where social trust can fail, and the experiment: what happens when the treasurer is a validator?
30+
- The three-layer architecture: Aiken validators, the Effect-based SDK, and the demo dApp.
31+
- CIP-68 token pairs for on-chain identity.
32+
- ProgramRunner execution modes (`unsafeRun`, `safeRun`, and `program`) and the typed error taxonomy.
33+
- CLI demo: creating an account on Preprod and inspecting the CIP-68 token pair.
34+
- Demo dApp: creating a circle, joining from another wallet, and observing the pooled funds increase.
35+
- Q&A on first-recipient default risk, dispute handling, guarantor models, and future multisig governance.
36+
37+
For the curated technical walkthrough, see the [session notes](../session-notes/readme.md). The [session resources](../session-resources/readme.md) collect the repositories, tools, and standards referenced during the session.
38+
39+
---
40+
41+
*This recording belongs to the Q2 2026 Developer Experience Working Group.*
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
---
2+
title: "Session 20: Building a Production Cardano SDK: From Validators to dApp - Notes"
3+
sidebar_label: Session Notes
4+
slug: /working-group/q2-2026/sessions/20-cardano-production-sdk/session-notes
5+
---
6+
7+
# Building a Production Cardano SDK: From Validators to dApp
8+
9+
## Introduction
10+
11+
This session continues the offchain and SDK building track started in Session 14. Where Session 14 walked through the structure of an offchain repository, this session goes end to end through the **practices of building and shipping a production-grade SDK**, using a source-available case study: the [DCU Toolkit](https://github.com/tx-meta/dcu-kit) (Decentralized Credit Unions), an MVP infrastructure for cooperative finance on Cardano under active development, together with a demo web application built on top of it. We cover why the product exists, how the three layers fit together, and what it takes to ship an SDK that other developers can actually build on.
12+
13+
## Session at a Glance
14+
15+
| | |
16+
|---|---|
17+
| **Date** | 11 June 2026 |
18+
| **Format** | Technical walkthrough, CLI demonstration, and demo dApp walkthrough |
19+
| **Presenter** | Harun Mwangi |
20+
| **Case study** | DCU Toolkit on Cardano Preprod |
21+
22+
:::tip If you remember one thing from this session
23+
On Cardano, **your application builds the transaction; the validator only says yes or no.** Smart contracts here are not running programs that hold your logic. They are pure functions that approve or reject a state transition. Everything in this session (the SDK, the endpoints, the UI) is layers of convenience around that one idea. If you keep this mental model, the rest of the ecosystem stops being confusing.
24+
:::
25+
26+
---
27+
28+
## Why This Exists
29+
30+
Group savings schemes — Chamas, Tontines, Susu, Chit funds, Tandas — are how [419 million adults save semi-formally](https://www.findevgateway.org/blog/2022/09/path-financial-inclusion-must-include-saving-small-groups) worldwide. They run on social trust, and the recurring failure is always the same shape: a treasurer or organizer holds the pooled funds with no enforceable rules, and eventually someone absconds with the pot. Regulation and audits are post-hoc, and a plain app with a database only relocates the trust to whoever runs the server.
31+
32+
The DCU Toolkit is an experiment: **what happens when the treasurer is a validator?** Custody without a custodian, with rules enforced before each transaction instead of audited after the collapse. Cardano fits because its deterministic eUTxO model makes each group's treasury an independent UTxO whose outcome is known before the transaction is submitted. Each failure mode maps to a validator check:
33+
34+
| What goes wrong today | What the toolkit encodes |
35+
|---|---|
36+
| Treasurer absconds with the pot | Funds locked in a Treasury UTxO; payouts enforced by the validator |
37+
| Organizer rug-pulls the group | `creator_bond` forfeited if the group is deleted while members are active |
38+
| Member defaults mid-cycle | `collateral_rounds` locked at join; pro-rata pots so the cycle never stalls |
39+
| Fake identities, no audit trail | CIP-68 membership token pairs; full history on chain |
40+
41+
Its validators, SDK, specification, and examples are public and auditable. The toolkit remains under active development; whether it holds up with real communities, under real usability constraints, is what the experiment is for.
42+
43+
---
44+
45+
## What is a ROSCA?
46+
47+
A **Rotating Savings and Credit Association**: a fixed group of members each contribute the same amount per cycle, and each cycle one member receives the entire pooled pot, rotating until everyone has been paid exactly once.
48+
49+
The on-chain mapping:
50+
- **Members** lock ADA (or any Cardano-native token, including stablecoins) into a Treasury UTxO when they join.
51+
- **Intervals** advance on a fixed schedule encoded in the Group datum.
52+
- **Payouts** go to the member whose `assigned_slot` matches the current interval, enforced by the Treasury validator.
53+
54+
---
55+
56+
## What the Creator Configures
57+
58+
A group is not one fixed shape. At creation the admin sets rules that the validators then enforce for the group's lifetime. Two of these change how money actually moves:
59+
60+
- **Contribution funding — per-cycle or full-upfront.** Members can be required to deposit each interval, or allowed to deposit their whole multi-cycle obligation at once (useful for crowdfunding-style groups, or a member who wants to prepay while the validator draws it down each interval). A validator can never *prevent* a deposit, only enforce a minimum — so full-upfront is an allowance layered on top of the per-cycle rule, not a separate contract.
61+
- **Payout mode — push or claim.** In **push (auto-pay)** mode the payout is permissionless: the member, the admin, or any participant can submit the transaction, and the validator sends the pot to whoever holds the current interval's `assigned_slot`. This is the safeguard against a recipient who goes silent. In **claim (pool)** mode the member must actively withdraw their own pot.
62+
63+
The economic parameters — cycle length, contribution amount, joining fee, early-exit penalty, and the `creator_bond` — are also set here and frozen on chain at `startGroup`.
64+
65+
---
66+
67+
## Architecture: Three Layers
68+
69+
```mermaid
70+
flowchart TB
71+
subgraph APP["Application Layer"]
72+
K["Web app (Next.js)"]
73+
EX["Example CLI scripts"]
74+
CR["Cron daemon (cycle automation)"]
75+
end
76+
subgraph SDK["Middleware: @tx-meta/dcu-kit (TypeScript + Effect)"]
77+
EP["17 tx-builder endpoints<br/>account (3) · group (9) · treasury (5)"]
78+
PR["ProgramRunner<br/>unsafeRun · safeRun · program"]
79+
ERR["12-error taxonomy<br/>typed Data.TaggedError"]
80+
LE["Lucid Evolution<br/>Blockfrost / Emulator provider"]
81+
end
82+
subgraph CHAIN["Onchain: Cardano L1 (Aiken validators)"]
83+
AV["Account<br/>CIP-68 membership"]
84+
GV["Group<br/>lifecycle + rotation"]
85+
TV["Treasury<br/>locked funds + payouts"]
86+
SV["Settings<br/>protocol parameters"]
87+
end
88+
K --> EP
89+
EX --> EP
90+
CR --> EP
91+
EP --> PR --> LE
92+
LE --> AV & GV & TV & SV
93+
```
94+
95+
The session focused on the **middle layer**, since that is where most Cardano application developers will spend their time.
96+
97+
---
98+
99+
## Onchain, Briefly: CIP-68 Pairs
100+
101+
Smart contracts cannot efficiently read data stored in tokens sitting in user wallets, so every identity in the protocol is a **synchronized pair of tokens**:
102+
103+
| Token | Where it lives | What it does |
104+
|---|---|---|
105+
| **Reference NFT** `(100)` | Locked at the validator | Holds the datum that contracts can read |
106+
| **User Auth NFT** `(222)` | The user's wallet | Proves ownership and authorizes transactions |
107+
108+
Both are minted atomically. At validation time the contract reads the reference datum and checks that you hold the auth token, **without ever taking it from your wallet**. The same pattern covers groups: the Group Reference NFT lives at the Group validator, and the Group Auth NFT is admin authority.
109+
110+
Validators in the repo: `account-validator.ak`, `group-validator.ak`, `treasury-validator.ak`, `settings-validator.ak`, plus `always-fails.ak` used to permanently lock deployed reference scripts.
111+
112+
---
113+
114+
## The SDK: Every Endpoint Returns a ProgramRunner
115+
116+
```typescript
117+
import { createAccount } from "@tx-meta/dcu-kit";
118+
119+
const [selected_out_ref] = await lucid.wallet().getUtxos();
120+
121+
// 1. Throws on failure (scripts, quick tooling)
122+
const tx = await createAccount(lucid, { selected_out_ref }).unsafeRun();
123+
124+
// 2. Returns an Either, never throws (production UIs)
125+
const result = await createAccount(lucid, { selected_out_ref }).safeRun();
126+
127+
// 3. Raw Effect, composes with your own pipeline
128+
const program = createAccount(lucid, { selected_out_ref }).program();
129+
```
130+
131+
One API, three execution modes, chosen by the integrator rather than the SDK author. `selected_out_ref` is consumed as entropy for the CIP-68 token name, which guarantees global uniqueness (no two UTxOs ever share a `txHash#index`).
132+
133+
### Why Effect Instead of Plain Promises
134+
135+
For financial transactions, failure handling is the product, not an afterthought:
136+
- A **12-error taxonomy** of typed `Data.TaggedError`s (missing UTxO, invalid datum, insufficient funds, and so on), each catchable by tag.
137+
- No uncaught throws: builders fail gracefully and explicitly.
138+
- Pipelines compose: retry, timeout, and concurrency come for free.
139+
140+
### Anatomy of an Endpoint
141+
142+
```text
143+
sdk/src/
144+
├── endpoints/distributePayout.ts ← one file per operation
145+
│ Config type → datum/redeemer schemas → tx build → makeReturn()
146+
├── core/
147+
│ ├── errors.ts ← 12-error taxonomy (built FIRST)
148+
│ ├── types.ts ← datum + redeemer schemas
149+
│ ├── plutus.json ← compiled Aiken blueprint
150+
│ └── validators/ ← policy IDs derived from the blueprint
151+
└── index.ts ← barrel export
152+
```
153+
154+
Build order when starting any SDK: errors, then types, then validators, then endpoints one at a time, each with its test before the next. This layout is identical across the team's SDKs, so integrators learn it once.
155+
156+
### The Endpoint Surface
157+
158+
The seventeen endpoints — three on Account, nine on Group, five on Treasury — cover the whole lifecycle. Beyond the create/join/start/payout path shown below, the Group set also includes `updateGroup`, `deleteGroup`, `exitGroup`, `triggerNextCycle`, `extendGraceWindow`, and `terminateDefault`:
159+
160+
- `triggerNextCycle` advances the rotation using the rules frozen at `startGroup`.
161+
- `extendGraceWindow` gives a member who is behind more time before removal.
162+
- `terminateDefault` removes a member who has missed contributions in a contributing-path group.
163+
164+
---
165+
166+
## Preprod Walkthrough: From SDK to Demo dApp
167+
168+
The `sdk/examples/` directory contains CLI scripts for exercising the endpoints. Together they support the protocol lifecycle:
169+
170+
```bash
171+
pnpm run create-account # ADMIN, USER1, USER2
172+
pnpm run create-group # ADMIN bonds and sets the rules
173+
pnpm run join-group # users lock collateral
174+
pnpm run start-group # rotation schedule fixed on chain
175+
pnpm run distribute-payout # validator pays round 1's member
176+
pnpm run claim-payout
177+
```
178+
179+
During this session, the live walkthrough covered the first part of that lifecycle:
180+
181+
1. Building and locally packing the SDK for use by the examples.
182+
2. Running the `create-account` example against Preprod.
183+
3. Inspecting the resulting transaction and its CIP-68 reference and user NFTs.
184+
4. Connecting a Lace test wallet to the demo dApp and creating an on-chain account.
185+
5. Creating a new group, presented as a **circle** in the user interface, with its cycle and financial rules.
186+
6. Joining an existing circle from another wallet and observing its pot grow from 50 ADA to 100 ADA.
187+
188+
The rotation was not started during the session because of time. The sequence below shows the complete protocol flow that the SDK is designed to support, rather than only the transactions executed in the live demonstration.
189+
190+
```mermaid
191+
sequenceDiagram
192+
participant A as Admin
193+
participant U as Members
194+
participant S as DCU SDK
195+
participant T as Treasury Validator
196+
197+
A->>S: createGroup (bond + rules)
198+
U->>S: joinGroup (lock collateral)
199+
A->>S: startGroup (schedule frozen on chain)
200+
loop Each cycle
201+
S->>T: distributePayout tx
202+
T->>T: check interval + assigned_slot
203+
T->>U: pot to this round's member
204+
end
205+
```
206+
207+
Reference scripts are deployed once per SDK version and permanently locked at an `alwaysFails` address: they are a witness-size optimization and can never move funds.
208+
209+
---
210+
211+
## The Integration Case Study: A Demo Web App (Kyama)
212+
213+
The proof that the SDK works for a real integrator is the [live demo web application](https://kyama.vercel.app/) built on top of it. One button, all the layers:
214+
215+
**"Distribute Payout"** → React hook → `distributePayout(lucid, cfg).safeRun()` → tx phase UI → confirmed on chain.
216+
217+
- Typed errors map one-to-one to user-facing messages.
218+
- `tx-phase` and `tx-progress-bar` components are driven directly by SDK states.
219+
- Wallet connect, chain-data hooks, and route guards all sit on the same 17 endpoints.
220+
221+
In the demo UI, groups are presented to users as **circles** (or pods) — friendlier language for the same on-chain group. The live walkthrough created a circle on Preprod and joined an existing one from a second wallet; because each join makes the member's first contribution, the pot visibly grew from 50 ADA to 100 ADA.
222+
223+
---
224+
225+
## Production Discipline
226+
227+
| CI job | Gates |
228+
|---|---|
229+
| Verify SDK | format, lint, types, build, emulator test suite |
230+
| Verify Aiken | format, build, on-chain unit tests |
231+
| Verify Design Specs | the Typst design spec must compile |
232+
233+
All three must pass before merge; publishing fires on a GitHub Release, with a CHANGELOG and MIGRATION guide per version. "Production smart contract" means the spec, the validators, and the SDK are versioned and gated together.
234+
235+
---
236+
237+
## The Recipe: Applying This to Your Own SDK
238+
239+
Everything above generalizes. If you are wrapping your own validators in an SDK, this is the method:
240+
241+
1. **Start from the blueprint.** `plutus.json` is the contract between layers; derive policy IDs and script addresses from it, never hardcode them.
242+
2. **Build the error taxonomy first.** Every endpoint imports from it, and typed failures designed up front are what make a polished UX possible downstream.
243+
3. **Schemas next.** Datum and redeemer types must mirror the onchain design spec exactly; blueprint alignment is the offchain code's entire job.
244+
4. **One endpoint at a time, each with its test before the next.** An emulator test suite keeps the loop fast; save Preprod for end-to-end verification.
245+
5. **Return a runner, not a promise.** Expose throw / Either / Effect modes and let the integrator choose; an SDK should not impose its error-handling style.
246+
6. **Ship examples as first-class code.** One CLI script per endpoint doubles as living documentation and a manual integration test.
247+
7. **Version the whole stack together.** Blueprint, SDK, spec, and reference scripts in one release with CI gates on all of them; a recompiled validator must never silently strand your integrators.
248+
249+
---
250+
251+
## Open Problems (Honest Limitations)
252+
253+
This is an MVP under active development, and some failure modes are not yet fully solved. Naming them is part of the method:
254+
255+
- **The first recipient absconding is the hard case.** Once the first member receives the pot, nothing on chain compels them to keep contributing. There is no bulletproof fix today. The current safeguard is the `creator_bond`, which can be forfeited to cover members at risk; ideas under exploration include a **guarantor model** (a member's payout is backed by another party) and **equal-loss sharing** (a default is absorbed proportionally across the whole group, so no single member takes the entire hit).
256+
- **Identity is a placeholder.** CIP-68 membership pairs give an audit trail, but they do not prove real-world identity. The intended direction is ZK-proofed KYC, so identity can be verified without being exposed on chain.
257+
- **Governance is not multisig yet.** The creator/admin currently holds elevated control. Multisig is planned for sensitive actions such as proposals and voting, so control decentralizes as the protocol matures.
258+
259+
---
260+
261+
## Key Takeaways
262+
263+
- **Your app builds the transaction; the validator only approves or rejects.** This is the single mental model every Cardano newcomer should anchor on.
264+
- **Real-world trust failures are the use case.** Each documented fraud maps to a specific validator check; smart contracts here are not abstract, they are a missing audit running before every transaction.
265+
- **SDKs drive adoption.** Wrapping validators in a typed, well-documented SDK lets application developers build without reading Plutus or Aiken.
266+
- **Design the failure paths first.** A typed error taxonomy built before any endpoint is what makes a polished UX possible downstream.
267+
- **Ship the whole stack.** Blueprint, SDK, examples, docs, and CI gates moving in lockstep is what separates a demo from infrastructure.
268+
- **Be explicit about what remains unsolved.** The session's closing discussion identified first-recipient default, real-world identity, dispute handling, and centralized admin control as open design problems rather than presenting the MVP as finished financial infrastructure.
269+
270+
---
271+
272+
*These notes belong to the Q2 2026 Developer Experience Working Group.*

0 commit comments

Comments
 (0)