Skip to content

Commit 046eaed

Browse files
authored
Merge pull request #145 from pasevin/cursor/openzeppelin-uikit-documentation-5e15
docs(uikit): add comprehensive UIKit documentation section
2 parents 11febce + 7bd1f0d commit 046eaed

22 files changed

Lines changed: 1739 additions & 194 deletions
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
---
2+
title: Architecture
3+
---
4+
5+
OpenZeppelin UIKit is built as a layered stack of independently installable packages. This page explains how those layers fit together, how the capability-driven adapter model works, and how runtimes manage lifecycle across multiple ecosystems.
6+
7+
## Package Layers
8+
9+
The packages form a dependency chain where each layer builds on the ones below it. Lower layers are lighter and more generic; higher layers add React-specific and domain-specific behavior.
10+
11+
```mermaid
12+
%%{init: {'flowchart': {'nodeSpacing': 20, 'rankSpacing': 40}} }%%
13+
flowchart TD
14+
Storage(["7 · ui-storage"])
15+
Renderer(["6 · ui-renderer"])
16+
ReactPkg(["5 · ui-react"])
17+
Components(["4 · ui-components"])
18+
Styles(["3 · ui-styles"])
19+
Utils(["2 · ui-utils"])
20+
Types(["1 · ui-types"])
21+
22+
Storage --> Utils
23+
Renderer --> Components
24+
ReactPkg --> Components
25+
Components --> Styles
26+
Components --> Utils
27+
Utils --> Types
28+
29+
style Storage fill:#e8eaf6,stroke:#5c6bc0,color:#1a237e
30+
style Renderer fill:#e8eaf6,stroke:#5c6bc0,color:#1a237e
31+
style ReactPkg fill:#e8eaf6,stroke:#5c6bc0,color:#1a237e
32+
style Components fill:#e0f2f1,stroke:#26a69a,color:#004d40
33+
style Styles fill:#e0f2f1,stroke:#26a69a,color:#004d40
34+
style Utils fill:#fff3e0,stroke:#ff9800,color:#e65100
35+
style Types fill:#fff3e0,stroke:#ff9800,color:#e65100
36+
```
37+
38+
**Color key:** <span style={{color: '#5c6bc0'}}>■</span> Application layers (5–7) · <span style={{color: '#26a69a'}}>■</span> UI & design (3–4) · <span style={{color: '#ff9800'}}>■</span> Foundation (1–2)
39+
40+
| Layer | Package | Responsibility |
41+
| --- | --- | --- |
42+
| 1 | `@openzeppelin/ui-types` | TypeScript interfaces for capabilities, schemas, form models, networks, transactions, and execution config. No runtime code: pure type definitions. |
43+
| 2 | `@openzeppelin/ui-utils` | Framework-agnostic helpers: `AppConfigService` for environment/config loading, structured logger, validation utilities, and routing helpers. |
44+
| 3 | `@openzeppelin/ui-styles` | Tailwind CSS 4 theme tokens using OKLCH color space. Ships CSS variables and custom variants (dark mode). No JavaScript. |
45+
| 4 | `@openzeppelin/ui-components` | React UI primitives (buttons, dialogs, cards, tabs) and blockchain-aware form fields (address, amount, bytes, enum, map). Built on Radix UI + shadcn/ui patterns. |
46+
| 5 | `@openzeppelin/ui-react` | `RuntimeProvider` for managing `EcosystemRuntime` instances per network. `WalletStateProvider` for global wallet state. Derived hooks for cross-ecosystem wallet abstraction. |
47+
| 6 | `@openzeppelin/ui-renderer` | `TransactionForm` for schema-driven transaction forms. `ContractStateWidget` for view function queries. `ExecutionConfigDisplay`, `AddressBookWidget`, address book components. |
48+
| 7 | `@openzeppelin/ui-storage` | `EntityStorage` and `KeyValueStorage` base classes on Dexie.js/IndexedDB. Account alias plugin for address-to-name mapping. |
49+
50+
<a id="capabilities"></a>
51+
## Capabilities
52+
53+
The UIKit type system defines 13 **capabilities**: small, focused interfaces that describe what an adapter can do.
54+
55+
Capabilities are organized into three tiers based on their requirements:
56+
57+
```mermaid
58+
%%{init: {'flowchart': {'nodeSpacing': 30, 'rankSpacing': 30}} }%%
59+
flowchart TD
60+
T1["<b>Tier 1 (Lightweight)</b><br/>Addressing · Explorer · NetworkCatalog · UiLabels"]
61+
T2["<b>Tier 2 (Network-Aware)</b><br/>ContractLoading · Schema · TypeMapping · Query"]
62+
T3["<b>Tier 3 (Stateful)</b><br/>Execution · Wallet · UiKit · Relayer · AccessControl"]
63+
64+
T1 --"may import"--> T2 --"may import"--> T3
65+
66+
style T1 fill:#e8eaf6,stroke:#5c6bc0,color:#000
67+
style T2 fill:#e0f2f1,stroke:#26a69a,color:#000
68+
style T3 fill:#fff3e0,stroke:#ff9800,color:#000
69+
```
70+
71+
**Tier 1** requires no runtime context: safe to import anywhere. **Tier 2** needs a `networkConfig`. **Tier 3** additionally needs wallet state and participates in the `dispose()` lifecycle. Each higher tier may import from lower tiers, but never the reverse.
72+
73+
| Capability | Tier | Purpose |
74+
| --- | --- | --- |
75+
| `Addressing` | 1 | Address validation, formatting, checksumming |
76+
| `Explorer` | 1 | Block explorer URL generation |
77+
| `NetworkCatalog` | 1 | Available network listing and metadata |
78+
| `UiLabels` | 1 | Human-readable labels for ecosystem-specific terms |
79+
| `ContractLoading` | 2 | Fetch and parse contract ABIs/IDLs |
80+
| `Schema` | 2 | Transform contract definitions into form-renderable schemas |
81+
| `TypeMapping` | 2 | Map blockchain types (e.g. `uint256`) to form field types |
82+
| `Query` | 2 | Execute read-only contract calls (view functions) |
83+
| `Execution` | 3 | Sign, broadcast, and track transactions |
84+
| `Wallet` | 3 | Connect/disconnect wallets, account state, chain switching |
85+
| `UiKit` | 3 | Ecosystem-specific React components and hooks |
86+
| `Relayer` | 3 | Gas-sponsored transaction execution via relayers |
87+
| `AccessControl` | 3 | Role-based access control queries and snapshots |
88+
89+
### Capability Bundles
90+
91+
Higher-level components request specific **bundles** of capabilities rather than the full set. For example, `TransactionForm` expects a `TransactionFormCapabilities` type: an intersection of the capabilities needed for form rendering, execution, and status tracking.
92+
93+
This means you can pass a partial adapter that only implements what the component actually needs.
94+
95+
<a id="runtimes"></a>
96+
## Runtimes and Profiles
97+
98+
### Ecosystem Runtimes
99+
100+
An `EcosystemRuntime` is a live instance that bundles capabilities for a specific network. Capabilities created within the same runtime share runtime-scoped state (network config, wallet connection, caches) and are disposed together.
101+
102+
Runtimes are created by ecosystem adapter packages:
103+
104+
```tsx
105+
import { ecosystemDefinition } from '@openzeppelin/adapter-evm';
106+
107+
const runtime = await ecosystemDefinition.createRuntime(
108+
'composer', // profile name
109+
ethereumMainnetConfig // network config
110+
);
111+
112+
// Access capabilities from the runtime
113+
const address = runtime.addressing.formatAddress('0x...');
114+
const schema = await runtime.schema.generateFormSchema(contractDef);
115+
const txHash = await runtime.execution.signAndBroadcast(txData, execConfig);
116+
117+
// Clean up when done
118+
runtime.dispose();
119+
```
120+
121+
### Profiles
122+
123+
Adapters support five standard profiles that define which capabilities are included:
124+
125+
| Profile | Use Case | Tier 1 | Tier 2 | Tier 3 |
126+
| --- | --- | --- | --- | --- |
127+
| `declarative` | Address formatting, explorer links || - | - |
128+
| `viewer` | Read contract state, no wallet needed ||| - |
129+
| `transactor` | Execute transactions, basic wallet ||| Execution, Wallet |
130+
| `composer` | Full UI with form rendering ||| ✓ (most) |
131+
| `operator` | Administrative tools, access control ||| ✓ (all) |
132+
133+
Choose the lightest profile that fits your use case. A dashboard that only displays contract state can use `viewer`; a full transaction builder should use `composer` or `operator`.
134+
135+
### Runtime Lifecycle
136+
137+
```mermaid
138+
sequenceDiagram
139+
participant App as Application
140+
participant RP as RuntimeProvider
141+
participant Adapter as Ecosystem Adapter
142+
143+
App->>RP: Mount with resolveRuntime
144+
App->>RP: setActiveNetworkId("ethereum-mainnet")
145+
RP->>Adapter: createRuntime("composer", networkConfig)
146+
Adapter-->>RP: EcosystemRuntime
147+
148+
Note over RP: Cached by network ID
149+
150+
App->>RP: setActiveNetworkId("polygon-mainnet")
151+
RP->>Adapter: createRuntime("composer", polygonConfig)
152+
Adapter-->>RP: New EcosystemRuntime
153+
154+
Note over RP: Both runtimes cached
155+
156+
App->>RP: Unmount
157+
RP->>RP: dispose() all cached runtimes
158+
```
159+
160+
`RuntimeProvider` maintains a **per-network-id registry** of runtimes. When a network is selected for the first time, the runtime is created asynchronously and cached. On unmount, all runtimes are disposed, releasing any wallet connections, subscriptions, or internal state.
161+
162+
## Execution Strategies
163+
164+
The execution system supports multiple ways to submit a transaction. The adapter selects the appropriate strategy based on the `ExecutionConfig`:
165+
166+
```mermaid
167+
flowchart LR
168+
Form["TransactionForm"] --> Exec["ExecutionCapability"]
169+
Exec --> Strategy{"Method?"}
170+
Strategy -->|EOA| EOA["Direct wallet signing"]
171+
Strategy -->|Relayer| Relay["Gas-sponsored via Relayer"]
172+
EOA --> Chain["Blockchain"]
173+
Relay --> Chain
174+
```
175+
176+
Each ecosystem adapter defines which execution methods it supports. The EVM adapter supports both EOA and Relayer; other ecosystems may support only EOA.
177+
178+
## How It Connects
179+
180+
Putting it all together, here is how a typical application uses UIKit with an Ecosystem Adapter:
181+
182+
```mermaid
183+
%%{init: {'flowchart': {'nodeSpacing': 20, 'rankSpacing': 40}} }%%
184+
flowchart TD
185+
App(["Your React App"])
186+
RP(["RuntimeProvider"])
187+
WSP(["WalletStateProvider"])
188+
TF(["TransactionForm"])
189+
CSW(["ContractStateWidget"])
190+
AdapterEVM(["adapter-evm"])
191+
AdapterStellar(["adapter-stellar"])
192+
Ethereum(["Ethereum"])
193+
Stellar(["Stellar"])
194+
195+
App --> RP --> WSP
196+
WSP --> TF & CSW
197+
RP -.->|createRuntime| AdapterEVM & AdapterStellar
198+
AdapterEVM --> Ethereum
199+
AdapterStellar --> Stellar
200+
201+
style App fill:#e8eaf6,stroke:#5c6bc0,color:#1a237e
202+
style RP fill:#e0f2f1,stroke:#26a69a,color:#004d40
203+
style WSP fill:#e0f2f1,stroke:#26a69a,color:#004d40
204+
style TF fill:#e0f2f1,stroke:#26a69a,color:#004d40
205+
style CSW fill:#e0f2f1,stroke:#26a69a,color:#004d40
206+
style AdapterEVM fill:#fff3e0,stroke:#ff9800,color:#e65100
207+
style AdapterStellar fill:#fff3e0,stroke:#ff9800,color:#e65100
208+
style Ethereum fill:#fce4ec,stroke:#e91e63,color:#880e4f
209+
style Stellar fill:#fce4ec,stroke:#e91e63,color:#880e4f
210+
```
211+
212+
## Next Steps
213+
214+
- [Components](/tools/uikit/components): Explore all available UI primitives and form fields
215+
- [React Integration](/tools/uikit/react-integration): Deep dive into providers, hooks, and wallet state
216+
- [Building an adapter](/ecosystem-adapters/building-an-adapter): Background on the adapter pattern and ecosystem integrations

0 commit comments

Comments
 (0)