README.md 9.5 K raw
1
# Norns
2
3
![cover](site/og.png)
4
5
Interoperable web components for decentralized applications
6
7
## Overview and Reasoning
8
Some of the first crypto apps we build were in React, and it's possible we might be able to resurrect some of them if we tried. However the unfortunate reality is that web dev frameworks accelerate at an alarming rate, and that goes for blockchain related libraries as well (shudders at the memory of viem v1 -> v2 and ethers v5 -> v6). It doesn't have to be like that though.
9
10
Web components are independant pieces of Javascript that can be imported to plain HTML but also frameworks as well. They're atomic, existing on their own and able to out-last any framework as long as we keep using Javscript (unfortunately I think that is the case). Some notable existing web component libraries include [Material Web](https://github.com/material-components/material-web) and [Web Awesome](https://github.com/shoelace-style/webawesome).
11
12
The goal of Norns is to provide the Ethereum ecosystem a set of simple yet powerful web components for building decentralized applications. The advantage we have today is that we've experienced good DX from modern frameworks, so we have the ability to build components that feel familiar to devs building UIs for smart contracts.
13
14
>[!NOTE]
15
> This project is still in early development, so if you have ideas, bugs, or feature requests, just open an issue!
16
17
## Quickstart
18
19
### 1. Initialize `norns` with your package manager of choice
20
21
```bash
22
npx norns-ui@latest init
23
```
24
25
Provide the following information as prompted:
26
- Path to where the components will be stored (will use `src/components` by default)
27
- If you want to include type definitions
28
  - Select framework for type defintions: `typescript`, `react`, `svelte`, `vue`
29
30
This will create a `norns.json` file in the root of your project with your selections
31
32
### 2. Add components
33
34
Using the `norns.json` the CLI will install them to the provided path in the config.
35
36
```bash
37
npx norns-ui@latest add connect-wallet
38
npx norns-ui@latest add contract-call
39
npx norns-ui@latest add contract-read
40
```
41
42
### 3. Use components
43
44
These web components should work in virtually any framework setup, whether you're in React, Vue, Svelte, or just plain HTML.
45
46
**HTML/Vanilla JS**
47
48
```html
49
<!DOCTYPE html>
50
<html lang="en">
51
<head>
52
  <meta charset="UTF-8">
53
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
54
  <title>Norns Example</title>
55
</head>
56
<body>
57
  <div class="container">
58
    <connect-wallet chain-id="1"></connect-wallet>
59
  </div>
60
  <script src="./components/connect-wallet.js"></script>
61
</body>
62
</html>
63
```
64
65
**React**
66
67
```tsx
68
import { useEffect, useRef } from "react";
69
import "./components/connect-wallet";
70
71
function App() {
72
  const walletRef = useRef<any>(null);
73
74
  useEffect(() => {
75
    const walletElement = walletRef.current;
76
    if (!walletElement) return;
77
78
    walletElement.onWalletConnected = (detail: any) => {
79
      console.log("connected: ", detail);
80
    };
81
  }, []);
82
83
  return (
84
    <div>
85
      <connect-wallet chain-id="1" ref={walletRef}></connect-wallet>
86
    </div>
87
  );
88
}
89
```
90
91
**Vue**
92
93
```vue
94
<script setup lang="ts">
95
import './components/connect-wallet'
96
</script>
97
98
<template>
99
  <div>
100
    <connect-wallet chain-id="1"></connect-wallet>
101
  </div>
102
</template>
103
```
104
105
**Svelte**
106
107
```svelte
108
<script lang="ts">
109
import "./components/connect-wallet";
110
</script>
111
112
<main>
113
  <connect-wallet chain-id="1"></connect-wallet>
114
</main>
115
```
116
117
**TypeScript**
118
119
```typescript
120
import "./components/connect-wallet";
121
122
const wallet = document.querySelector('connect-wallet');
123
wallet?.addEventListener('wallet-connected', (event) => {
124
  console.log('Wallet connected:', event.detail);
125
});
126
127
document.body.innerHTML = `
128
  <connect-wallet chain-id="1"></connect-wallet>
129
`;
130
```
131
132
## Usage
133
134
Each component has multiple parameters that can be passed in to designate properties like chain ID, contract address, ABI, and more.
135
136
### `connect-wallet`
137
138
A Web3 wallet connection component that supports Ethereum wallet integration with ENS resolution, balance display, and multi-chain support.
139
140
**Attributes:**
141
- `chain-id` - Ethereum chain ID in hex or decimal format (default: `"1"` for mainnet)
142
- `background` - Background color (default: `"#232323"`)
143
- `foreground` - Text color (default: `"#ffffff"`)
144
- `primary` - Primary button color (default: `"#5F8787"`)
145
- `secondary` - Secondary/hover color (default: `"#6F9797"`)
146
- `border-radius` - Border radius for UI elements (default: `"4px"`)
147
148
**Events:**
149
- `wallet-connected` - Fired when wallet is successfully connected
150
- `wallet-disconnected` - Fired when wallet is disconnected
151
- `wallet-error` - Fired when wallet connection fails
152
153
**Example:**
154
```html
155
<connect-wallet
156
  chain-id="11155111"
157
  primary="#4F46E5"
158
  background="#1F2937"
159
  border-radius="8px">
160
</connect-wallet>
161
```
162
163
### `contract-call`
164
165
A custom HTML element for interacting with Ethereum smart contracts. Supports both read-only (view/pure) and write operations through wallet integration.
166
167
**Attributes:**
168
- `contract-address` (required) - The Ethereum contract address
169
- `method-name` (required) - The contract method to call
170
- `method-args` - JSON array of method arguments (default: `[]`)
171
- `abi` - JSON string of the contract ABI
172
- `abi-url` - URL to fetch the contract ABI from
173
- `chain-id` - Ethereum chain ID in decimal or hex format (default: `"1"` for mainnet)
174
- `button-text` - Text displayed on the call button (default: `"Call Contract"`)
175
- `background` - Background color (default: `"#232323"`)
176
- `foreground` - Text color (default: `"#ffffff"`)
177
- `primary` - Primary button color (default: `"#5F8787"`)
178
- `secondary` - Secondary/hover color (default: `"#6F9797"`)
179
- `border-radius` - Border radius for UI elements (default: `"4px"`)
180
- `error-color` - Color for error messages (default: `"#E78A53"`)
181
- `success-color` - Color for success messages (default: `"#5F8787"`)
182
183
**Events:**
184
- `abi-loaded` - Fired when ABI is successfully loaded from URL
185
- `abi-error` - Fired when ABI loading fails
186
- `contract-call-success` - Fired when contract call succeeds
187
- `contract-call-error` - Fired when contract call fails
188
189
**Example:**
190
```html
191
<contract-call
192
  contract-address="0x8C9EC9c13812C7F9F26AB934d4bF36206240dDA8"
193
  chain-id="11155111"
194
  method-name="increment"
195
  abi='[{"inputs":[],"name":"increment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newNumber","type":"uint256"}],"name":"setNumber","outputs":[],"stateMutability":"nonpayable","type":"function"}]'
196
  button-text="Increment">
197
</contract-call>
198
```
199
200
### `contract-read`
201
202
A custom HTML element for reading state from Ethereum smart contracts. Automatically loads and displays read-only contract state on mount. Supports both wallet integration and direct RPC calls.
203
204
**Attributes:**
205
- `contract-address` (required) - The Ethereum contract address
206
- `method-name` (required) - The contract method to call
207
- `method-args` - JSON array of method arguments (default: `[]`)
208
- `abi` - JSON string of the contract ABI
209
- `abi-url` - URL to fetch the contract ABI from
210
- `rpc-url` - RPC URL for direct calls (used when wallet is not available)
211
- `chain-id` - Ethereum chain ID in decimal or hex format (default: `"1"` for mainnet)
212
- `background` - Background color (default: `"#232323"`)
213
- `foreground` - Text color (default: `"#ffffff"`)
214
- `primary` - Primary color (default: `"#5F8787"`)
215
- `border-radius` - Border radius for UI elements (default: `"4px"`)
216
- `error-color` - Color for error messages (default: `"#E78A53"`)
217
- `success-color` - Color for success messages (default: `"#5F8787"`)
218
219
**Events:**
220
- `abi-loaded` - Fired when ABI is successfully loaded from URL
221
- `abi-error` - Fired when ABI loading fails
222
- `contract-read-success` - Fired when contract read succeeds
223
- `contract-read-error` - Fired when contract read fails
224
225
**Example:**
226
```html
227
<contract-read
228
  contract-address="0x8C9EC9c13812C7F9F26AB934d4bF36206240dDA8"
229
  chain-id="11155111"
230
  method-name="number"
231
  rpc-url="https://sepolia.drpc.org"
232
  abi='[{"inputs":[],"name":"increment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newNumber","type":"uint256"}],"name":"setNumber","outputs":[],"stateMutability":"nonpayable","type":"function"}]'
233
  button-text="Current Count">
234
</contract-read>
235
```
236
237
## Local Development Setup
238
239
1. Clone and install dependencies with [Bun](https://bun.sh)
240
241
```bash
242
git clone https://github.com/stevedylandev/norns
243
cd norns
244
bun install
245
```
246
247
2. Run the dev server
248
249
```bash
250
bun dev
251
```
252
253
This will run a simple server for `site/index.html` which imports components from `src/component/`
254
255
3. Build
256
257
```bash
258
bun run build
259
```
260
261
After editing components and testing them in the dev server you can run the `build` command to generate the CLI from `src/index.ts` that will create a `dist` folder. This enables users to run something like `npx norns-ui@latest init` to setup a project and add components, similar to shadcn/ui.
262
263
Examples can be found under the `examples` directory, containing pre-installed components for multiple frameworks.
264
265
## Contributing
266
267
Norns is still in early development but definitely open to contributions! Just open an issue to get the ball rolling :)
268
269
## Contact
270
271
Feel free to reach out to any of my [socials](https://stevedylan.dev/links) or [shoot me an email](mailto:contact@stevedylan.dev)