|
| 1 | +--- |
| 2 | +title: "Session 16: UI ↔ Smart Contracts (Wallets + Tx flow) - Notes" |
| 3 | +sidebar_label: Session Notes |
| 4 | +slug: /working-group/q2-2026/sessions/16-ui-smart-contract-interaction/session-notes |
| 5 | +--- |
| 6 | + |
| 7 | +# Session 16: UI ↔ Smart Contracts (Wallets + Tx flow) - Notes |
| 8 | + |
| 9 | +This guide explains **how a UI app interacts with Cardano smart contracts** (validators) in a production-style way, with clear architecture options, security notes, and diagrams. |
| 10 | + |
| 11 | +## What “interacting with a smart contract” means on Cardano |
| 12 | + |
| 13 | +On Cardano (eUTxO), “calling a contract” is **building a transaction** that: |
| 14 | + |
| 15 | +- **Spends one or more UTxOs** (including script-locked UTxOs at a script address) |
| 16 | +- **Provides redeemers + datums** as required by the validator |
| 17 | +- **Satisfies script conditions** (signatures, time bounds, minting policies, etc.) |
| 18 | +- **Pays fees / min-ADA** and produces new outputs |
| 19 | + |
| 20 | +The validator runs during tx validation. Your UI (plus SDKs/services) does the *off-chain* work: selecting UTxOs, constructing outputs, attaching witnesses, then submitting. |
| 21 | + |
| 22 | +--- |
| 23 | + |
| 24 | +## End-to-end flow (high-level) |
| 25 | + |
| 26 | +```mermaid |
| 27 | +flowchart LR |
| 28 | + UI["UI App<br/>React / Vue / etc"] -->|CIP-30| Wallet["Browser wallet<br/>Lace / Eternl / Nami / ..."] |
| 29 | + UI --> SDK["Tx builder SDK<br/>Lucid-evo / MeshJS / Blaze"] |
| 30 | + SDK --> Data["Chain data provider<br/>Blockfrost / Koios / Maestro<br/>+ optional indexer: Kupo"] |
| 31 | + SDK --> Eval["Tx evaluate / simulate<br/>Ogmios or provider API"] |
| 32 | + Wallet -->|signTx| Signed[Signed Tx Witnesses] |
| 33 | + SDK -->|submitTx| Node["Submit to network<br/>Node / Ogmios / provider"] |
| 34 | + Node --> Conf["Confirmation<br/>+ indexing"] |
| 35 | + Conf --> UI |
| 36 | +``` |
| 37 | + |
| 38 | +**Key point**: the wallet usually **does not** “build” the tx. It signs and submits (depending on wallet capabilities). Your SDK + data provider handle most of the logic. |
| 39 | + |
| 40 | +--- |
| 41 | + |
| 42 | +## Transaction lifecycle (practical checklist) |
| 43 | + |
| 44 | +### 1) Connect wallet (CIP-30) |
| 45 | +- Request access to wallet APIs (network id, addresses, UTxOs, collateral). |
| 46 | +- Detect unsupported capabilities early (collateral, signData, etc.). |
| 47 | + |
| 48 | +### 2) Fetch required on-chain state |
| 49 | +- Wallet state: spendable UTxOs + change address. |
| 50 | +- App state: script UTxOs to spend, reference scripts, datum/redeemer schema, token metadata. |
| 51 | +- Optional: query by policy-id/asset, datum hash, script address via an indexer (Kupo) or provider. |
| 52 | + |
| 53 | +### 3) Build the transaction |
| 54 | +Common pieces: |
| 55 | +- Inputs: user UTxOs + script UTxOs |
| 56 | +- Outputs: updated script output (state machine), payments, change |
| 57 | +- Mint/burn: attach minting policy scripts + redeemers (if needed) |
| 58 | +- Validity interval: time bounds (important for “expiring” actions) |
| 59 | +- Required signers: pubkey hashes that must sign |
| 60 | +- Attachments: datums, redeemers, scripts or **reference scripts** (CIP-33) |
| 61 | + |
| 62 | +### 4) Evaluate (recommended) |
| 63 | +Before user signs, estimate: |
| 64 | +- Execution units (CPU/mem) |
| 65 | +- Fees |
| 66 | +- Min-ADA for outputs |
| 67 | + |
| 68 | +This is where Ogmios (or provider evaluation endpoints) helps you avoid “fails script” surprises. |
| 69 | + |
| 70 | +### 5) Ask wallet to sign |
| 71 | +- Wallet signs **only the required keys** (and sometimes all inputs depending on the wallet). |
| 72 | +- UX: show the user what they’re signing (amounts, recipients, tokens). |
| 73 | + |
| 74 | +### 6) Submit + confirm |
| 75 | +- Submit via wallet or SDK/provider. |
| 76 | +- Track tx hash until confirmed (or “failed” / “rolled back”). |
| 77 | +- Update UI state (pending → confirmed), refresh UTxO/indexer views. |
| 78 | + |
| 79 | +--- |
| 80 | + |
| 81 | +## Architecture options (recommended 2–3 ways) |
| 82 | + |
| 83 | +Below are **three pro-level integration patterns**, ordered from most common to most specialized. |
| 84 | + |
| 85 | +### Option A (recommended default): Client-built tx + wallet signing (CIP-30) |
| 86 | + |
| 87 | +**Best for**: most dApps; simplest mental model; non-custodial. |
| 88 | + |
| 89 | +```mermaid |
| 90 | +sequenceDiagram |
| 91 | + autonumber |
| 92 | + participant U as User |
| 93 | + participant UI as UI App |
| 94 | + participant W as Wallet (CIP-30) |
| 95 | + participant P as Provider/Indexer (Blockfrost/Koios/Maestro/Kupo) |
| 96 | + participant N as Network |
| 97 | +
|
| 98 | + U->>UI: Click "Deposit / Swap / Claim" |
| 99 | + UI->>W: enable() |
| 100 | + UI->>W: getUtxos(), getChangeAddress() |
| 101 | + UI->>P: fetch script UTxOs + datum (query) |
| 102 | + UI->>UI: build unsigned tx (SDK) |
| 103 | + UI->>P: evaluate tx (optional but recommended) |
| 104 | + UI->>W: signTx(unsignedTx) |
| 105 | + UI->>W: submitTx(signedTx) or UI->>P: submitTx(signedTx) |
| 106 | + N-->>UI: txHash + confirmation later |
| 107 | +``` |
| 108 | + |
| 109 | +- **Pros**: non-custodial, minimal backend, quick iteration, fewer infra concerns. |
| 110 | +- **Cons**: heavier client logic; provider rate limits; complex indexer queries can be slow; secrets can’t live in browser (so you rely on public providers). |
| 111 | + |
| 112 | +**Pro tips** |
| 113 | +- Prefer **reference scripts** (CIP-33) and datum hashes where possible to reduce tx size. |
| 114 | +- Add robust “pending” UX; handle mempool time + reorgs gracefully. |
| 115 | +- Cache chain reads, debounce refreshes, and show clear error explanations (collateral missing, insufficient ADA for min-UTxO, invalid interval, etc.). |
| 116 | + |
| 117 | +--- |
| 118 | + |
| 119 | +### Option B (recommended for production apps): Hybrid build — backend composes tx, wallet signs |
| 120 | + |
| 121 | +**Best for**: complex protocols; better reliability; private provider keys; better indexing and caching; better protection against UI “logic drift”. |
| 122 | + |
| 123 | +Pattern: the backend produces **an unsigned tx (CBOR)** or **a partially-constructed tx**, the wallet signs in the browser, then either client or server submits. |
| 124 | + |
| 125 | +```mermaid |
| 126 | +flowchart TB |
| 127 | + UI["UI App"] -->|request intent<br/>params| API["Backend API<br/>Tx composer"] |
| 128 | + API --> IDX["Indexer + node bridge<br/>Kupo + Ogmios<br/>or Blockfrost / Maestro"] |
| 129 | + API -->|unsigned tx CBOR<br/>+ summary| UI |
| 130 | + UI -->|CIP-30 signTx| W[Wallet] |
| 131 | + UI -->|submitTx| N["Network<br/>node / provider"] |
| 132 | +``` |
| 133 | + |
| 134 | +- **Pros**: backend centralizes protocol logic, supports caching, can choose best UTxO(s), can enforce invariants and “sanity checks”, can protect provider API keys. |
| 135 | +- **Cons**: more infra; you must carefully design trust boundaries (UI should verify summary); still need wallet signing UX. |
| 136 | + |
| 137 | +**Trust boundary guidance** |
| 138 | +- The backend should return a **human-readable tx summary** (what the tx is intended to do) alongside CBOR. |
| 139 | +- The UI should validate: network, recipients, amounts, policy IDs, and action parameters before prompting the user to sign. |
| 140 | + |
| 141 | +--- |
| 142 | + |
| 143 | +### Option C (specialized): Server-side signing (custodial or delegated keys) |
| 144 | + |
| 145 | +**Best for**: enterprise flows, custodial wallets, scheduled/automated operations, “agent” services. |
| 146 | + |
| 147 | +```mermaid |
| 148 | +sequenceDiagram |
| 149 | + autonumber |
| 150 | + participant UI as UI App |
| 151 | + participant API as Backend |
| 152 | + participant KMS as KMS/HSM |
| 153 | + participant N as Network |
| 154 | +
|
| 155 | + UI->>API: request action |
| 156 | + API->>API: build tx |
| 157 | + API->>KMS: sign tx |
| 158 | + API->>N: submit signed tx |
| 159 | + API-->>UI: tx hash + status |
| 160 | +``` |
| 161 | + |
| 162 | +- **Pros**: best automation; consistent submission; easier for non-crypto users. |
| 163 | +- **Cons**: custody/security liability; regulatory/compliance implications; key management complexity; larger blast radius. |
| 164 | + |
| 165 | +**If you do this**, treat it like a payments system: HSM/KMS, strict authZ, audit logs, rate limits, and incident response plans. |
| 166 | + |
| 167 | +--- |
| 168 | + |
| 169 | +## Which SDK / tools to pick (practical) |
| 170 | + |
| 171 | +You can mix-and-match, but pick one “lane” and standardize: |
| 172 | + |
| 173 | +- **Frontend tx building**: MeshJS, Lucid-evo, Blaze (common choices in the ecosystem). |
| 174 | +- **Node bridge (evaluation / submission)**: Ogmios (tx eval + submission), plus a real node behind it. |
| 175 | +- **UTxO indexing**: Kupo (query script UTxOs and datum hashes efficiently). |
| 176 | +- **Hosted provider APIs**: Blockfrost / Koios / Maestro (great for fast startup; mind rate limits). |
| 177 | + |
| 178 | +--- |
| 179 | + |
| 180 | +## Common UI pitfalls (and how pros avoid them) |
| 181 | + |
| 182 | +- **UTxO concurrency**: two users trying to spend the same script UTxO → one fails. |
| 183 | + - Mitigate via batching, “queue” patterns, or designing contracts that avoid single-UTxO hotspots. |
| 184 | +- **Min-ADA surprises**: outputs holding tokens require enough ADA. |
| 185 | + - Compute min-UTxO in builder; show friendly error and “add ADA” suggestion. |
| 186 | +- **Script size / fees**: attaching full scripts increases fees and can exceed limits. |
| 187 | + - Prefer reference scripts (CIP-33) and reference inputs. |
| 188 | +- **Network mismatch**: user wallet on the wrong network (Preview/Preprod/Mainnet). |
| 189 | + - Hard block with a clear message + switch-network instructions. |
| 190 | +- **Poor signing UX**: user can’t tell what they’re signing. |
| 191 | + - Display a concise summary: “Action, amounts, recipients, tokens, fees (est), validity”. |
| 192 | + |
| 193 | +--- |
| 194 | + |
| 195 | +## Next steps |
| 196 | + |
| 197 | +See the curated links in [Resources](../session-resources/readme.md). If you already have an Aiken validator repo, this session pairs well with creating a minimal off-chain “tx composer” and wiring it to a UI. |
| 198 | + |
| 199 | +--- |
| 200 | + |
| 201 | +*These notes belong to the Q2 2026 Developer Experience Working Group.* |
| 202 | + |
0 commit comments