@ethereum-entity-registry/sdk 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +345 -0
  2. package/package.json +17 -1
package/README.md ADDED
@@ -0,0 +1,345 @@
1
+ # @ethereum-entity-registry/sdk
2
+
3
+ [![npm](https://img.shields.io/npm/v/@ethereum-entity-registry/sdk)](https://www.npmjs.com/package/@ethereum-entity-registry/sdk)
4
+
5
+ TypeScript SDK and React hooks for the [Ethereum Entity Registry](https://github.com/ethereum-entity-registry) — a shared on-chain registry that maps off-chain identifiers (GitHub repos, DNS domains) to Ethereum addresses.
6
+
7
+ Every identifier gets a deterministic deposit address before its owner has ever touched Ethereum. Funds accumulate there until the owner claims and takes control.
8
+
9
+ > **Status:** Research prototype. Contracts are not audited. Do not use in production.
10
+
11
+ ## Install
12
+
13
+ ```sh
14
+ npm install @ethereum-entity-registry/sdk
15
+ ```
16
+
17
+ **Peer dependencies**
18
+
19
+ ```sh
20
+ npm install viem wagmi @tanstack/react-query sonner
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```ts
26
+ import { EntityRegistrySDK } from "@ethereum-entity-registry/sdk";
27
+
28
+ // Read-only (no wallet)
29
+ const sdk = new EntityRegistrySDK();
30
+
31
+ // With a wallet for write operations
32
+ const sdk = new EntityRegistrySDK(walletClient);
33
+
34
+ // Explicit chain (defaults to chain from wallet, or hardhat locally)
35
+ const sdk = new EntityRegistrySDK(walletClient, 84532); // Base Sepolia
36
+ ```
37
+
38
+ **Supported chains**
39
+
40
+ | Chain | ID |
41
+ |---|---|
42
+ | Mainnet | `1` |
43
+ | Sepolia | `11155111` |
44
+ | Base | `8453` |
45
+ | Base Sepolia | `84532` |
46
+ | Hardhat (local) | `31337` |
47
+
48
+ ---
49
+
50
+ ## SDK Reference
51
+
52
+ ### `sdk.registry`
53
+
54
+ #### `resolve(input, token?)`
55
+
56
+ Resolve any identifier string to its on-chain state.
57
+
58
+ ```ts
59
+ const state = await sdk.registry.resolve("github.com/org/repo");
60
+ // state.id — bytes32 identifier
61
+ // state.depositAddress — deterministic account address (fund here)
62
+ // state.owner — registered owner, or null if unclaimed
63
+
64
+ // Pass a token address to include the balance
65
+ const state = await sdk.registry.resolve("github.com/org/repo", tokenAddress);
66
+ // state.balance — ERC-20 balance at the deposit address
67
+ ```
68
+
69
+ All of these formats are accepted:
70
+
71
+ ```ts
72
+ sdk.registry.resolve("github:org/repo");
73
+ sdk.registry.resolve("https://github.com/org/repo");
74
+ sdk.registry.resolve("example.com");
75
+ sdk.registry.resolve("dns:example.com");
76
+ sdk.registry.resolve("npmjs.com/package/foo");
77
+ ```
78
+
79
+ #### `ownerOf(id)`
80
+
81
+ ```ts
82
+ const owner = await sdk.registry.ownerOf(id); // Address | null
83
+ ```
84
+
85
+ #### `predictAddress(id)`
86
+
87
+ Compute the deterministic deposit address without an RPC call.
88
+
89
+ ```ts
90
+ const address = await sdk.registry.predictAddress(id);
91
+ ```
92
+
93
+ #### `toId(namespace, canonicalString)`
94
+
95
+ Derive the bytes32 identifier for a namespace/value pair.
96
+
97
+ ```ts
98
+ const id = await sdk.registry.toId("github", "org/repo");
99
+ ```
100
+
101
+ #### `claim(input, proof)`
102
+
103
+ Submit a verified proof to register ownership on-chain.
104
+
105
+ ```ts
106
+ await sdk.registry.claim("github.com/org/repo", proofBytes);
107
+ ```
108
+
109
+ #### `revoke(input)`
110
+
111
+ Release ownership of a claimed identifier.
112
+
113
+ ```ts
114
+ await sdk.registry.revoke("github.com/org/repo");
115
+ ```
116
+
117
+ #### `linkIds(primaryId, aliasIds)` / `unlinkIds(primaryId, aliasIds)`
118
+
119
+ Create or remove aliases between identifiers (e.g. link a GitHub org to a domain).
120
+
121
+ ```ts
122
+ await sdk.registry.linkIds(primaryId, [aliasId1, aliasId2]);
123
+ await sdk.registry.unlinkIds(primaryId, [aliasId1]);
124
+ ```
125
+
126
+ #### `deployAccount(id)`
127
+
128
+ Explicitly deploy the identity account contract for an identifier (auto-deployed on first `execute` otherwise).
129
+
130
+ ```ts
131
+ await sdk.registry.deployAccount(id);
132
+ ```
133
+
134
+ ---
135
+
136
+ ### `sdk.account`
137
+
138
+ #### `execute(accountAddress, target, data, value?)`
139
+
140
+ Call any contract from the identity account. Only the registered owner can call this.
141
+
142
+ ```ts
143
+ await sdk.account.execute(accountAddress, target, data);
144
+ await sdk.account.execute(accountAddress, target, data, parseEther("0.1"));
145
+ ```
146
+
147
+ #### `encodeERC20Transfer(token, recipient, amount)`
148
+
149
+ Encode an ERC-20 transfer to be executed via the identity account.
150
+
151
+ ```ts
152
+ const { target, data } = sdk.account.encodeERC20Transfer(
153
+ tokenAddress,
154
+ recipient,
155
+ amount,
156
+ );
157
+ await sdk.account.execute(state.depositAddress, target, data);
158
+ ```
159
+
160
+ #### `encodeWarehouseWithdraw(warehouse, account, token)`
161
+
162
+ Encode a Splits Warehouse withdrawal.
163
+
164
+ ```ts
165
+ const call = sdk.account.encodeWarehouseWithdraw(
166
+ warehouseAddress,
167
+ state.depositAddress,
168
+ tokenAddress,
169
+ );
170
+ await sdk.account.execute(state.depositAddress, call.target, call.data);
171
+ ```
172
+
173
+ ---
174
+
175
+ ### Utility functions
176
+
177
+ #### `parseUrl(input)`
178
+
179
+ Parse any URL or namespace-prefixed string into its components.
180
+
181
+ ```ts
182
+ import { parseUrl } from "@ethereum-entity-registry/sdk";
183
+
184
+ parseUrl("https://github.com/org/repo");
185
+ // → { namespace: "github", canonicalString: "org/repo", formatted: "github:org/repo" }
186
+
187
+ parseUrl("example.com");
188
+ // → { namespace: "dns", canonicalString: "example.com", formatted: "dns:example.com" }
189
+ ```
190
+
191
+ #### `toId(namespace, canonicalString)`
192
+
193
+ Pure local computation of the bytes32 identifier — no RPC call needed.
194
+
195
+ ```ts
196
+ import { toId } from "@ethereum-entity-registry/sdk";
197
+
198
+ const id = toId("github", "org/repo");
199
+ // keccak256(abi.encode("github", "org/repo"))
200
+ ```
201
+
202
+ ---
203
+
204
+ ## React Hooks
205
+
206
+ ### Setup
207
+
208
+ Wrap your app with `EntityRegistryProvider`:
209
+
210
+ ```tsx
211
+ import { EntityRegistryProvider } from "@ethereum-entity-registry/sdk";
212
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
213
+
214
+ const queryClient = new QueryClient();
215
+
216
+ function App() {
217
+ return (
218
+ <QueryClientProvider client={queryClient}>
219
+ <EntityRegistryProvider walletClient={walletClient}>
220
+ {/* ... */}
221
+ </EntityRegistryProvider>
222
+ </QueryClientProvider>
223
+ );
224
+ }
225
+ ```
226
+
227
+ ### Read hooks
228
+
229
+ ```tsx
230
+ import {
231
+ useOwnerOf,
232
+ usePredictAddress,
233
+ useToId,
234
+ } from "@ethereum-entity-registry/sdk";
235
+
236
+ // Resolve owner of an identifier
237
+ const { data: owner } = useOwnerOf(id);
238
+
239
+ // Get the deterministic deposit address
240
+ const { data: depositAddress } = usePredictAddress(id);
241
+
242
+ // Compute bytes32 id from namespace + string
243
+ const { data: id } = useToId("github", "org/repo");
244
+ ```
245
+
246
+ ### Write hooks
247
+
248
+ ```tsx
249
+ import {
250
+ useClaim,
251
+ useRevoke,
252
+ useLinkIds,
253
+ useUnlinkIds,
254
+ useDeployAccount,
255
+ useExecute,
256
+ } from "@ethereum-entity-registry/sdk";
257
+
258
+ function ClaimButton({ input, proof }) {
259
+ const claim = useClaim();
260
+
261
+ return (
262
+ <button
263
+ onClick={() => claim.mutate({ input, proof })}
264
+ disabled={claim.isPending}
265
+ >
266
+ Claim
267
+ </button>
268
+ );
269
+ }
270
+
271
+ function ExecuteButton({ accountAddress, target, data }) {
272
+ const execute = useExecute();
273
+
274
+ return (
275
+ <button onClick={() => execute.mutate({ accountAddress, target, data })}>
276
+ Execute
277
+ </button>
278
+ );
279
+ }
280
+ ```
281
+
282
+ ---
283
+
284
+ ## Claim Flow
285
+
286
+ ### GitHub
287
+
288
+ ```ts
289
+ // 1. Redirect to the OAuth gateway
290
+ window.location.href = `/claim/github?owner=org&repo=repo&claimant=${address}`;
291
+
292
+ // 2. After OAuth, the gateway returns with a signed proof
293
+ const proof = new URLSearchParams(window.location.search).get("proof");
294
+
295
+ // 3. Submit on-chain
296
+ await sdk.registry.claim("github.com/org/repo", proof);
297
+ ```
298
+
299
+ ### DNS
300
+
301
+ ```ts
302
+ // 1. Add a TXT record to your domain:
303
+ // _eth-entity.example.com → "0xYourAddress"
304
+
305
+ // 2. Request a proof from the signing service
306
+ const res = await fetch("/api/proof/dns", {
307
+ method: "POST",
308
+ body: JSON.stringify({ domain: "example.com", claimant: address }),
309
+ });
310
+ const { proof } = await res.json();
311
+
312
+ // 3. Submit on-chain
313
+ await sdk.registry.claim("example.com", proof);
314
+ ```
315
+
316
+ ---
317
+
318
+ ## On-Chain Integration (Solidity)
319
+
320
+ ```solidity
321
+ import {IEntityRegistry} from "@ethereum-entity-registry/contracts/contracts/IEntityRegistry.sol";
322
+
323
+ address registry = 0x081a5907ab0A77fCc84cf217B62730b9341Ee687; // Base Sepolia
324
+
325
+ bytes32 id = keccak256(abi.encode("github", "org/repo"));
326
+ address owner = IEntityRegistry(registry).ownerOf(id);
327
+
328
+ // ownerOf resolves through aliases transparently
329
+ ```
330
+
331
+ **Deployed addresses**
332
+
333
+ | Network | Registry |
334
+ |---|---|
335
+ | Base Sepolia | `0x081a5907ab0A77fCc84cf217B62730b9341Ee687` |
336
+ | Sepolia | see `deployments.json` |
337
+
338
+ ---
339
+
340
+ ## Links
341
+
342
+ - [GitHub](https://github.com/ethereum-entity-registry)
343
+ - [Documentation](https://ethereum-entity-registry.vercel.app/docs)
344
+ - [npm](https://www.npmjs.com/package/@ethereum-entity-registry/sdk)
345
+ - [Contracts](https://www.npmjs.com/package/@ethereum-entity-registry/contracts)
package/package.json CHANGED
@@ -1,7 +1,23 @@
1
1
  {
2
2
  "name": "@ethereum-entity-registry/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
+ "description": "TypeScript SDK and React hooks for the Ethereum Entity Registry",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/carlbarrdahl/ethereum-canonical-registry",
9
+ "directory": "packages/sdk"
10
+ },
11
+ "homepage": "https://github.com/carlbarrdahl/ethereum-canonical-registry#readme",
12
+ "keywords": [
13
+ "ethereum",
14
+ "registry",
15
+ "identity",
16
+ "github",
17
+ "dns",
18
+ "viem",
19
+ "wagmi"
20
+ ],
5
21
  "files": [
6
22
  "dist"
7
23
  ],