@inkd/sdk 0.9.0

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 (106) hide show
  1. package/README.md +288 -0
  2. package/dist/InkdClient.d.ts +89 -0
  3. package/dist/InkdClient.d.ts.map +1 -0
  4. package/dist/InkdClient.js +398 -0
  5. package/dist/InkdClient.js.map +1 -0
  6. package/dist/ProjectRegistry.d.ts +655 -0
  7. package/dist/ProjectRegistry.d.ts.map +1 -0
  8. package/dist/ProjectRegistry.js +708 -0
  9. package/dist/ProjectRegistry.js.map +1 -0
  10. package/dist/__tests__/InkdClient.advanced.test.d.ts +10 -0
  11. package/dist/__tests__/InkdClient.advanced.test.d.ts.map +1 -0
  12. package/dist/__tests__/InkdClient.advanced.test.js +588 -0
  13. package/dist/__tests__/InkdClient.advanced.test.js.map +1 -0
  14. package/dist/__tests__/InkdClient.connectArweave.test.d.ts +10 -0
  15. package/dist/__tests__/InkdClient.connectArweave.test.d.ts.map +1 -0
  16. package/dist/__tests__/InkdClient.connectArweave.test.js +132 -0
  17. package/dist/__tests__/InkdClient.connectArweave.test.js.map +1 -0
  18. package/dist/__tests__/InkdClient.test.d.ts +2 -0
  19. package/dist/__tests__/InkdClient.test.d.ts.map +1 -0
  20. package/dist/__tests__/InkdClient.test.js +259 -0
  21. package/dist/__tests__/InkdClient.test.js.map +1 -0
  22. package/dist/__tests__/ProjectRegistry.test.d.ts +8 -0
  23. package/dist/__tests__/ProjectRegistry.test.d.ts.map +1 -0
  24. package/dist/__tests__/ProjectRegistry.test.js +689 -0
  25. package/dist/__tests__/ProjectRegistry.test.js.map +1 -0
  26. package/dist/__tests__/arweave.test.d.ts +9 -0
  27. package/dist/__tests__/arweave.test.d.ts.map +1 -0
  28. package/dist/__tests__/arweave.test.js +353 -0
  29. package/dist/__tests__/arweave.test.js.map +1 -0
  30. package/dist/__tests__/encryption.test.d.ts +2 -0
  31. package/dist/__tests__/encryption.test.d.ts.map +1 -0
  32. package/dist/__tests__/encryption.test.js +154 -0
  33. package/dist/__tests__/encryption.test.js.map +1 -0
  34. package/dist/__tests__/errors.test.d.ts +2 -0
  35. package/dist/__tests__/errors.test.d.ts.map +1 -0
  36. package/dist/__tests__/errors.test.js +136 -0
  37. package/dist/__tests__/errors.test.js.map +1 -0
  38. package/dist/__tests__/events.test.d.ts +10 -0
  39. package/dist/__tests__/events.test.d.ts.map +1 -0
  40. package/dist/__tests__/events.test.js +380 -0
  41. package/dist/__tests__/events.test.js.map +1 -0
  42. package/dist/__tests__/index.InkdClient.test.d.ts +8 -0
  43. package/dist/__tests__/index.InkdClient.test.d.ts.map +1 -0
  44. package/dist/__tests__/index.InkdClient.test.js +422 -0
  45. package/dist/__tests__/index.InkdClient.test.js.map +1 -0
  46. package/dist/__tests__/multicall.test.d.ts +9 -0
  47. package/dist/__tests__/multicall.test.d.ts.map +1 -0
  48. package/dist/__tests__/multicall.test.js +362 -0
  49. package/dist/__tests__/multicall.test.js.map +1 -0
  50. package/dist/__tests__/types.test.d.ts +2 -0
  51. package/dist/__tests__/types.test.d.ts.map +1 -0
  52. package/dist/__tests__/types.test.js +35 -0
  53. package/dist/__tests__/types.test.js.map +1 -0
  54. package/dist/abi.d.ts +2632 -0
  55. package/dist/abi.d.ts.map +1 -0
  56. package/dist/abi.js +3423 -0
  57. package/dist/abi.js.map +1 -0
  58. package/dist/arweave.d.ts +45 -0
  59. package/dist/arweave.d.ts.map +1 -0
  60. package/dist/arweave.js +154 -0
  61. package/dist/arweave.js.map +1 -0
  62. package/dist/encryption.d.ts +52 -0
  63. package/dist/encryption.d.ts.map +1 -0
  64. package/dist/encryption.js +80 -0
  65. package/dist/encryption.js.map +1 -0
  66. package/dist/errors.d.ts +63 -0
  67. package/dist/errors.d.ts.map +1 -0
  68. package/dist/errors.js +124 -0
  69. package/dist/errors.js.map +1 -0
  70. package/dist/events.d.ts +136 -0
  71. package/dist/events.d.ts.map +1 -0
  72. package/dist/events.js +131 -0
  73. package/dist/events.js.map +1 -0
  74. package/dist/hooks/index.d.ts +5 -0
  75. package/dist/hooks/index.d.ts.map +1 -0
  76. package/dist/hooks/index.js +12 -0
  77. package/dist/hooks/index.js.map +1 -0
  78. package/dist/hooks/useInkd.d.ts +24 -0
  79. package/dist/hooks/useInkd.d.ts.map +1 -0
  80. package/dist/hooks/useInkd.js +109 -0
  81. package/dist/hooks/useInkd.js.map +1 -0
  82. package/dist/hooks/useInkdHolder.d.ts +16 -0
  83. package/dist/hooks/useInkdHolder.d.ts.map +1 -0
  84. package/dist/hooks/useInkdHolder.js +45 -0
  85. package/dist/hooks/useInkdHolder.js.map +1 -0
  86. package/dist/hooks/useInscriptions.d.ts +17 -0
  87. package/dist/hooks/useInscriptions.d.ts.map +1 -0
  88. package/dist/hooks/useInscriptions.js +46 -0
  89. package/dist/hooks/useInscriptions.js.map +1 -0
  90. package/dist/hooks/useToken.d.ts +16 -0
  91. package/dist/hooks/useToken.d.ts.map +1 -0
  92. package/dist/hooks/useToken.js +45 -0
  93. package/dist/hooks/useToken.js.map +1 -0
  94. package/dist/index.d.ts +54 -0
  95. package/dist/index.d.ts.map +1 -0
  96. package/dist/index.js +290 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/multicall.d.ts +134 -0
  99. package/dist/multicall.d.ts.map +1 -0
  100. package/dist/multicall.js +182 -0
  101. package/dist/multicall.js.map +1 -0
  102. package/dist/types.d.ts +187 -0
  103. package/dist/types.d.ts.map +1 -0
  104. package/dist/types.js +32 -0
  105. package/dist/types.js.map +1 -0
  106. package/package.json +78 -0
@@ -0,0 +1,708 @@
1
+ "use strict";
2
+ /**
3
+ * @file ProjectRegistry.ts
4
+ * @description TypeScript client for InkdRegistry.sol — the core project registry contract.
5
+ * Use this module to create projects, push versions, manage collaborators,
6
+ * and transfer ownership on-chain.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { ProjectRegistry } from "@inkd/sdk";
11
+ * import { createWalletClient, createPublicClient, http } from "viem";
12
+ * import { base } from "viem/chains";
13
+ *
14
+ * const registry = new ProjectRegistry({
15
+ * registryAddress: "0x...",
16
+ * tokenAddress: "0x...",
17
+ * chainId: 8453,
18
+ * });
19
+ *
20
+ * registry.connect(walletClient, publicClient);
21
+ *
22
+ * // Create a project (locks 1 $INKD)
23
+ * const { projectId } = await registry.createProject({
24
+ * name: "my-agent-brain",
25
+ * description: "Persistent memory store for AI agent",
26
+ * license: "MIT",
27
+ * isPublic: true,
28
+ * isAgent: true,
29
+ * agentEndpoint: "https://api.myagent.xyz",
30
+ * });
31
+ *
32
+ * // Push a version
33
+ * await registry.pushVersion({
34
+ * projectId,
35
+ * arweaveHash: "ar://your-file-hash",
36
+ * versionTag: "v1.0.0",
37
+ * changelog: "Initial release",
38
+ * });
39
+ * ```
40
+ */
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.ProjectRegistry = exports.InsufficientEthBalance = exports.InsufficientInkdBalance = exports.RegistryNotConnected = exports.INKD_ERC20_ABI = exports.INKD_REGISTRY_ABI = void 0;
43
+ // ─── ABIs ─────────────────────────────────────────────────────────────────────
44
+ /** Minimal ABI fragment for InkdRegistry.sol */
45
+ exports.INKD_REGISTRY_ABI = [
46
+ // ── Read ──────────────────────────────────────────────────────────────────
47
+ {
48
+ type: "function",
49
+ name: "projectCount",
50
+ inputs: [],
51
+ outputs: [{ name: "", type: "uint256" }],
52
+ stateMutability: "view",
53
+ },
54
+ {
55
+ type: "function",
56
+ name: "versionFee",
57
+ inputs: [],
58
+ outputs: [{ name: "", type: "uint256" }],
59
+ stateMutability: "view",
60
+ },
61
+ {
62
+ type: "function",
63
+ name: "transferFee",
64
+ inputs: [],
65
+ outputs: [{ name: "", type: "uint256" }],
66
+ stateMutability: "view",
67
+ },
68
+ {
69
+ type: "function",
70
+ name: "TOKEN_LOCK_AMOUNT",
71
+ inputs: [],
72
+ outputs: [{ name: "", type: "uint256" }],
73
+ stateMutability: "view",
74
+ },
75
+ {
76
+ type: "function",
77
+ name: "getProject",
78
+ inputs: [{ name: "projectId", type: "uint256" }],
79
+ outputs: [
80
+ {
81
+ name: "",
82
+ type: "tuple",
83
+ components: [
84
+ { name: "id", type: "uint256" },
85
+ { name: "name", type: "string" },
86
+ { name: "description", type: "string" },
87
+ { name: "license", type: "string" },
88
+ { name: "readmeHash", type: "string" },
89
+ { name: "owner", type: "address" },
90
+ { name: "isPublic", type: "bool" },
91
+ { name: "isAgent", type: "bool" },
92
+ { name: "agentEndpoint", type: "string" },
93
+ { name: "createdAt", type: "uint256" },
94
+ { name: "versionCount", type: "uint256" },
95
+ { name: "exists", type: "bool" },
96
+ ],
97
+ },
98
+ ],
99
+ stateMutability: "view",
100
+ },
101
+ {
102
+ type: "function",
103
+ name: "getVersion",
104
+ inputs: [
105
+ { name: "projectId", type: "uint256" },
106
+ { name: "versionIndex", type: "uint256" },
107
+ ],
108
+ outputs: [
109
+ {
110
+ name: "",
111
+ type: "tuple",
112
+ components: [
113
+ { name: "projectId", type: "uint256" },
114
+ { name: "arweaveHash", type: "string" },
115
+ { name: "versionTag", type: "string" },
116
+ { name: "changelog", type: "string" },
117
+ { name: "pushedBy", type: "address" },
118
+ { name: "pushedAt", type: "uint256" },
119
+ ],
120
+ },
121
+ ],
122
+ stateMutability: "view",
123
+ },
124
+ {
125
+ type: "function",
126
+ name: "getVersionCount",
127
+ inputs: [{ name: "projectId", type: "uint256" }],
128
+ outputs: [{ name: "", type: "uint256" }],
129
+ stateMutability: "view",
130
+ },
131
+ {
132
+ type: "function",
133
+ name: "getCollaborators",
134
+ inputs: [{ name: "projectId", type: "uint256" }],
135
+ outputs: [{ name: "", type: "address[]" }],
136
+ stateMutability: "view",
137
+ },
138
+ {
139
+ type: "function",
140
+ name: "getOwnerProjects",
141
+ inputs: [{ name: "owner_", type: "address" }],
142
+ outputs: [{ name: "", type: "uint256[]" }],
143
+ stateMutability: "view",
144
+ },
145
+ {
146
+ type: "function",
147
+ name: "getAgentProjects",
148
+ inputs: [
149
+ { name: "offset", type: "uint256" },
150
+ { name: "limit", type: "uint256" },
151
+ ],
152
+ outputs: [
153
+ {
154
+ name: "",
155
+ type: "tuple[]",
156
+ components: [
157
+ { name: "id", type: "uint256" },
158
+ { name: "name", type: "string" },
159
+ { name: "description", type: "string" },
160
+ { name: "license", type: "string" },
161
+ { name: "readmeHash", type: "string" },
162
+ { name: "owner", type: "address" },
163
+ { name: "isPublic", type: "bool" },
164
+ { name: "isAgent", type: "bool" },
165
+ { name: "agentEndpoint", type: "string" },
166
+ { name: "createdAt", type: "uint256" },
167
+ { name: "versionCount", type: "uint256" },
168
+ { name: "exists", type: "bool" },
169
+ ],
170
+ },
171
+ ],
172
+ stateMutability: "view",
173
+ },
174
+ {
175
+ type: "function",
176
+ name: "isCollaborator",
177
+ inputs: [
178
+ { name: "projectId", type: "uint256" },
179
+ { name: "collaborator", type: "address" },
180
+ ],
181
+ outputs: [{ name: "", type: "bool" }],
182
+ stateMutability: "view",
183
+ },
184
+ {
185
+ type: "function",
186
+ name: "nameTaken",
187
+ inputs: [{ name: "name", type: "string" }],
188
+ outputs: [{ name: "", type: "bool" }],
189
+ stateMutability: "view",
190
+ },
191
+ // ── Write ─────────────────────────────────────────────────────────────────
192
+ {
193
+ type: "function",
194
+ name: "createProject",
195
+ inputs: [
196
+ { name: "name", type: "string" },
197
+ { name: "description", type: "string" },
198
+ { name: "license", type: "string" },
199
+ { name: "isPublic", type: "bool" },
200
+ { name: "readmeHash", type: "string" },
201
+ { name: "isAgent", type: "bool" },
202
+ { name: "agentEndpoint", type: "string" },
203
+ ],
204
+ outputs: [],
205
+ stateMutability: "nonpayable",
206
+ },
207
+ {
208
+ type: "function",
209
+ name: "pushVersion",
210
+ inputs: [
211
+ { name: "projectId", type: "uint256" },
212
+ { name: "arweaveHash", type: "string" },
213
+ { name: "versionTag", type: "string" },
214
+ { name: "changelog", type: "string" },
215
+ ],
216
+ outputs: [],
217
+ stateMutability: "payable",
218
+ },
219
+ {
220
+ type: "function",
221
+ name: "addCollaborator",
222
+ inputs: [
223
+ { name: "projectId", type: "uint256" },
224
+ { name: "collaborator", type: "address" },
225
+ ],
226
+ outputs: [],
227
+ stateMutability: "nonpayable",
228
+ },
229
+ {
230
+ type: "function",
231
+ name: "removeCollaborator",
232
+ inputs: [
233
+ { name: "projectId", type: "uint256" },
234
+ { name: "collaborator", type: "address" },
235
+ ],
236
+ outputs: [],
237
+ stateMutability: "nonpayable",
238
+ },
239
+ {
240
+ type: "function",
241
+ name: "transferProject",
242
+ inputs: [
243
+ { name: "projectId", type: "uint256" },
244
+ { name: "newOwner", type: "address" },
245
+ ],
246
+ outputs: [],
247
+ stateMutability: "payable",
248
+ },
249
+ {
250
+ type: "function",
251
+ name: "setVisibility",
252
+ inputs: [
253
+ { name: "projectId", type: "uint256" },
254
+ { name: "isPublic", type: "bool" },
255
+ ],
256
+ outputs: [],
257
+ stateMutability: "nonpayable",
258
+ },
259
+ {
260
+ type: "function",
261
+ name: "setReadme",
262
+ inputs: [
263
+ { name: "projectId", type: "uint256" },
264
+ { name: "arweaveHash", type: "string" },
265
+ ],
266
+ outputs: [],
267
+ stateMutability: "nonpayable",
268
+ },
269
+ {
270
+ type: "function",
271
+ name: "setAgentEndpoint",
272
+ inputs: [
273
+ { name: "projectId", type: "uint256" },
274
+ { name: "endpoint", type: "string" },
275
+ ],
276
+ outputs: [],
277
+ stateMutability: "nonpayable",
278
+ },
279
+ // ── Events ────────────────────────────────────────────────────────────────
280
+ {
281
+ type: "event",
282
+ name: "ProjectCreated",
283
+ inputs: [
284
+ { name: "projectId", type: "uint256", indexed: true },
285
+ { name: "owner", type: "address", indexed: true },
286
+ { name: "name", type: "string", indexed: false },
287
+ { name: "license", type: "string", indexed: false },
288
+ ],
289
+ },
290
+ {
291
+ type: "event",
292
+ name: "VersionPushed",
293
+ inputs: [
294
+ { name: "projectId", type: "uint256", indexed: true },
295
+ { name: "arweaveHash", type: "string", indexed: false },
296
+ { name: "versionTag", type: "string", indexed: false },
297
+ { name: "pushedBy", type: "address", indexed: false },
298
+ ],
299
+ },
300
+ ];
301
+ /** Minimal ABI fragment for InkdToken.sol (ERC-20 approve) */
302
+ exports.INKD_ERC20_ABI = [
303
+ {
304
+ type: "function",
305
+ name: "approve",
306
+ inputs: [
307
+ { name: "spender", type: "address" },
308
+ { name: "amount", type: "uint256" },
309
+ ],
310
+ outputs: [{ name: "", type: "bool" }],
311
+ stateMutability: "nonpayable",
312
+ },
313
+ {
314
+ type: "function",
315
+ name: "allowance",
316
+ inputs: [
317
+ { name: "owner", type: "address" },
318
+ { name: "spender", type: "address" },
319
+ ],
320
+ outputs: [{ name: "", type: "uint256" }],
321
+ stateMutability: "view",
322
+ },
323
+ {
324
+ type: "function",
325
+ name: "balanceOf",
326
+ inputs: [{ name: "account", type: "address" }],
327
+ outputs: [{ name: "", type: "uint256" }],
328
+ stateMutability: "view",
329
+ },
330
+ ];
331
+ // ─── Errors ───────────────────────────────────────────────────────────────────
332
+ class RegistryNotConnected extends Error {
333
+ constructor() {
334
+ super("ProjectRegistry: call connect() before making on-chain calls");
335
+ this.name = "RegistryNotConnected";
336
+ }
337
+ }
338
+ exports.RegistryNotConnected = RegistryNotConnected;
339
+ class InsufficientInkdBalance extends Error {
340
+ constructor(balance, required) {
341
+ super(`ProjectRegistry: insufficient $INKD balance. ` +
342
+ `Have ${balance}, need ${required}`);
343
+ this.name = "InsufficientInkdBalance";
344
+ }
345
+ }
346
+ exports.InsufficientInkdBalance = InsufficientInkdBalance;
347
+ class InsufficientEthBalance extends Error {
348
+ constructor(fee) {
349
+ super(`ProjectRegistry: insufficient ETH. Need at least ${fee} wei for fees`);
350
+ this.name = "InsufficientEthBalance";
351
+ }
352
+ }
353
+ exports.InsufficientEthBalance = InsufficientEthBalance;
354
+ // ─── ProjectRegistry ──────────────────────────────────────────────────────────
355
+ /**
356
+ * TypeScript client for InkdRegistry.sol.
357
+ *
358
+ * Wraps all on-chain registry operations with typed inputs/outputs,
359
+ * automatic $INKD approval, and fee estimation.
360
+ */
361
+ class ProjectRegistry {
362
+ config;
363
+ walletClient = null;
364
+ publicClient = null;
365
+ constructor(config) {
366
+ this.config = config;
367
+ }
368
+ // ─── Connection ─────────────────────────────────────────────────────────────
369
+ /**
370
+ * Attach viem wallet + public clients.
371
+ * Must be called before any on-chain write.
372
+ */
373
+ connect(walletClient, publicClient) {
374
+ this.walletClient = walletClient;
375
+ this.publicClient = publicClient;
376
+ }
377
+ // ─── Read ────────────────────────────────────────────────────────────────────
378
+ /** Get a project by ID. Returns null if the project does not exist. */
379
+ async getProject(projectId) {
380
+ this.requirePublic();
381
+ const raw = await this.publicClient.readContract({
382
+ address: this.config.registryAddress,
383
+ abi: exports.INKD_REGISTRY_ABI,
384
+ functionName: "getProject",
385
+ args: [projectId],
386
+ });
387
+ return raw.exists ? raw : null;
388
+ }
389
+ /** Get a specific version from a project. */
390
+ async getVersion(projectId, versionIndex) {
391
+ this.requirePublic();
392
+ return this.publicClient.readContract({
393
+ address: this.config.registryAddress,
394
+ abi: exports.INKD_REGISTRY_ABI,
395
+ functionName: "getVersion",
396
+ args: [projectId, versionIndex],
397
+ });
398
+ }
399
+ /** Get all versions of a project in chronological order. */
400
+ async getAllVersions(projectId) {
401
+ this.requirePublic();
402
+ const count = await this.publicClient.readContract({
403
+ address: this.config.registryAddress,
404
+ abi: exports.INKD_REGISTRY_ABI,
405
+ functionName: "getVersionCount",
406
+ args: [projectId],
407
+ });
408
+ return Promise.all(Array.from({ length: Number(count) }, (_, i) => this.getVersion(projectId, BigInt(i))));
409
+ }
410
+ /** Get all project IDs owned by an address. */
411
+ async getOwnerProjects(owner) {
412
+ this.requirePublic();
413
+ return this.publicClient.readContract({
414
+ address: this.config.registryAddress,
415
+ abi: exports.INKD_REGISTRY_ABI,
416
+ functionName: "getOwnerProjects",
417
+ args: [owner],
418
+ });
419
+ }
420
+ /** Get all collaborators of a project. */
421
+ async getCollaborators(projectId) {
422
+ this.requirePublic();
423
+ return this.publicClient.readContract({
424
+ address: this.config.registryAddress,
425
+ abi: exports.INKD_REGISTRY_ABI,
426
+ functionName: "getCollaborators",
427
+ args: [projectId],
428
+ });
429
+ }
430
+ /** Check if an address is a collaborator on a project. */
431
+ async isCollaborator(projectId, address) {
432
+ this.requirePublic();
433
+ return this.publicClient.readContract({
434
+ address: this.config.registryAddress,
435
+ abi: exports.INKD_REGISTRY_ABI,
436
+ functionName: "isCollaborator",
437
+ args: [projectId, address],
438
+ });
439
+ }
440
+ /** Check if a project name is already taken (case-insensitive). */
441
+ async isNameTaken(name) {
442
+ this.requirePublic();
443
+ return this.publicClient.readContract({
444
+ address: this.config.registryAddress,
445
+ abi: exports.INKD_REGISTRY_ABI,
446
+ functionName: "nameTaken",
447
+ args: [name.toLowerCase()],
448
+ });
449
+ }
450
+ /** Get all agent projects with optional pagination. */
451
+ async getAgentProjects(offset = 0n, limit = 100n) {
452
+ this.requirePublic();
453
+ return this.publicClient.readContract({
454
+ address: this.config.registryAddress,
455
+ abi: exports.INKD_REGISTRY_ABI,
456
+ functionName: "getAgentProjects",
457
+ args: [offset, limit],
458
+ });
459
+ }
460
+ /** Get the current version fee (ETH wei). */
461
+ async getVersionFee() {
462
+ this.requirePublic();
463
+ return this.publicClient.readContract({
464
+ address: this.config.registryAddress,
465
+ abi: exports.INKD_REGISTRY_ABI,
466
+ functionName: "versionFee",
467
+ });
468
+ }
469
+ /** Get the current transfer fee (ETH wei). */
470
+ async getTransferFee() {
471
+ this.requirePublic();
472
+ return this.publicClient.readContract({
473
+ address: this.config.registryAddress,
474
+ abi: exports.INKD_REGISTRY_ABI,
475
+ functionName: "transferFee",
476
+ });
477
+ }
478
+ /** Get the total number of projects on-chain. */
479
+ async getProjectCount() {
480
+ this.requirePublic();
481
+ return this.publicClient.readContract({
482
+ address: this.config.registryAddress,
483
+ abi: exports.INKD_REGISTRY_ABI,
484
+ functionName: "projectCount",
485
+ });
486
+ }
487
+ // ─── Write ───────────────────────────────────────────────────────────────────
488
+ /**
489
+ * Create a new project on-chain.
490
+ *
491
+ * Automatically approves the 1 $INKD token lock if the current allowance
492
+ * is insufficient.
493
+ *
494
+ * @throws {InsufficientInkdBalance} if caller has less than 1 $INKD.
495
+ */
496
+ async createProject(opts) {
497
+ this.requireWallet();
498
+ const lockAmount = await this.publicClient.readContract({
499
+ address: this.config.registryAddress,
500
+ abi: exports.INKD_REGISTRY_ABI,
501
+ functionName: "TOKEN_LOCK_AMOUNT",
502
+ });
503
+ const account = this.walletClient.account.address;
504
+ // Check balance
505
+ const balance = await this.publicClient.readContract({
506
+ address: this.config.tokenAddress,
507
+ abi: exports.INKD_ERC20_ABI,
508
+ functionName: "balanceOf",
509
+ args: [account],
510
+ });
511
+ if (balance < lockAmount) {
512
+ throw new InsufficientInkdBalance(balance, lockAmount);
513
+ }
514
+ // Approve if needed
515
+ const allowance = await this.publicClient.readContract({
516
+ address: this.config.tokenAddress,
517
+ abi: exports.INKD_ERC20_ABI,
518
+ functionName: "allowance",
519
+ args: [account, this.config.registryAddress],
520
+ });
521
+ if (allowance < lockAmount) {
522
+ const approveTx = await this.walletClient.writeContract({
523
+ address: this.config.tokenAddress,
524
+ abi: exports.INKD_ERC20_ABI,
525
+ functionName: "approve",
526
+ args: [this.config.registryAddress, lockAmount],
527
+ });
528
+ await this.publicClient.waitForTransactionReceipt({ hash: approveTx });
529
+ }
530
+ // Create project
531
+ const hash = await this.walletClient.writeContract({
532
+ address: this.config.registryAddress,
533
+ abi: exports.INKD_REGISTRY_ABI,
534
+ functionName: "createProject",
535
+ args: [
536
+ opts.name,
537
+ opts.description ?? "",
538
+ opts.license ?? "MIT",
539
+ opts.isPublic ?? true,
540
+ opts.readmeHash ?? "",
541
+ opts.isAgent ?? false,
542
+ opts.agentEndpoint ?? "",
543
+ ],
544
+ });
545
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
546
+ const projectId = this.extractProjectIdFromLogs(receipt.logs);
547
+ return { hash, projectId };
548
+ }
549
+ /**
550
+ * Push a new version to an existing project.
551
+ *
552
+ * Automatically reads the current versionFee and sends the exact amount.
553
+ * If you want to overpay (all excess goes to treasury), pass `value` explicitly.
554
+ *
555
+ * @throws {InsufficientEthBalance} if caller's ETH balance < versionFee.
556
+ */
557
+ async pushVersion(opts, value) {
558
+ this.requireWallet();
559
+ const fee = value ?? (await this.getVersionFee());
560
+ const hash = await this.walletClient.writeContract({
561
+ address: this.config.registryAddress,
562
+ abi: exports.INKD_REGISTRY_ABI,
563
+ functionName: "pushVersion",
564
+ args: [
565
+ opts.projectId,
566
+ opts.arweaveHash,
567
+ opts.versionTag,
568
+ opts.changelog ?? "",
569
+ ],
570
+ value: fee,
571
+ });
572
+ await this.publicClient.waitForTransactionReceipt({ hash });
573
+ const versionCount = await this.publicClient.readContract({
574
+ address: this.config.registryAddress,
575
+ abi: exports.INKD_REGISTRY_ABI,
576
+ functionName: "getVersionCount",
577
+ args: [opts.projectId],
578
+ });
579
+ return { hash, versionIndex: versionCount - 1n };
580
+ }
581
+ /** Add a collaborator to a project. Caller must be the project owner. */
582
+ async addCollaborator(projectId, collaborator) {
583
+ this.requireWallet();
584
+ const hash = await this.walletClient.writeContract({
585
+ address: this.config.registryAddress,
586
+ abi: exports.INKD_REGISTRY_ABI,
587
+ functionName: "addCollaborator",
588
+ args: [projectId, collaborator],
589
+ });
590
+ await this.publicClient.waitForTransactionReceipt({ hash });
591
+ return hash;
592
+ }
593
+ /** Remove a collaborator from a project. Caller must be the project owner. */
594
+ async removeCollaborator(projectId, collaborator) {
595
+ this.requireWallet();
596
+ const hash = await this.walletClient.writeContract({
597
+ address: this.config.registryAddress,
598
+ abi: exports.INKD_REGISTRY_ABI,
599
+ functionName: "removeCollaborator",
600
+ args: [projectId, collaborator],
601
+ });
602
+ await this.publicClient.waitForTransactionReceipt({ hash });
603
+ return hash;
604
+ }
605
+ /**
606
+ * Transfer project ownership to a new address.
607
+ * Automatically reads the current transferFee and sends the exact amount.
608
+ *
609
+ * Note: the 1 $INKD lock stays with the project — it is NOT refunded or
610
+ * transferred back to the old owner.
611
+ */
612
+ async transferProject(projectId, newOwner, value) {
613
+ this.requireWallet();
614
+ const fee = value ?? (await this.getTransferFee());
615
+ const hash = await this.walletClient.writeContract({
616
+ address: this.config.registryAddress,
617
+ abi: exports.INKD_REGISTRY_ABI,
618
+ functionName: "transferProject",
619
+ args: [projectId, newOwner],
620
+ value: fee,
621
+ });
622
+ await this.publicClient.waitForTransactionReceipt({ hash });
623
+ return hash;
624
+ }
625
+ /** Set project public/private visibility. Caller must be the project owner. */
626
+ async setVisibility(projectId, isPublic) {
627
+ this.requireWallet();
628
+ const hash = await this.walletClient.writeContract({
629
+ address: this.config.registryAddress,
630
+ abi: exports.INKD_REGISTRY_ABI,
631
+ functionName: "setVisibility",
632
+ args: [projectId, isPublic],
633
+ });
634
+ await this.publicClient.waitForTransactionReceipt({ hash });
635
+ return hash;
636
+ }
637
+ /** Update the README Arweave hash. Caller must be the project owner. */
638
+ async setReadme(projectId, arweaveHash) {
639
+ this.requireWallet();
640
+ const hash = await this.walletClient.writeContract({
641
+ address: this.config.registryAddress,
642
+ abi: exports.INKD_REGISTRY_ABI,
643
+ functionName: "setReadme",
644
+ args: [projectId, arweaveHash],
645
+ });
646
+ await this.publicClient.waitForTransactionReceipt({ hash });
647
+ return hash;
648
+ }
649
+ /** Update the agent endpoint URL. Caller must be the project owner. */
650
+ async setAgentEndpoint(projectId, endpoint) {
651
+ this.requireWallet();
652
+ const hash = await this.walletClient.writeContract({
653
+ address: this.config.registryAddress,
654
+ abi: exports.INKD_REGISTRY_ABI,
655
+ functionName: "setAgentEndpoint",
656
+ args: [projectId, endpoint],
657
+ });
658
+ await this.publicClient.waitForTransactionReceipt({ hash });
659
+ return hash;
660
+ }
661
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
662
+ /**
663
+ * Estimate the total ETH cost of one version push.
664
+ * (versionFee — gas excluded)
665
+ */
666
+ async estimatePushCost() {
667
+ return this.getVersionFee();
668
+ }
669
+ /**
670
+ * Estimate the total ETH cost of a project transfer.
671
+ * (transferFee — gas excluded)
672
+ */
673
+ async estimateTransferCost() {
674
+ return this.getTransferFee();
675
+ }
676
+ // ─── Internal ────────────────────────────────────────────────────────────────
677
+ requireWallet() {
678
+ if (!this.walletClient || !this.publicClient) {
679
+ throw new RegistryNotConnected();
680
+ }
681
+ }
682
+ requirePublic() {
683
+ if (!this.publicClient)
684
+ throw new RegistryNotConnected();
685
+ }
686
+ /**
687
+ * Extract the new project ID from the ProjectCreated event.
688
+ * Falls back to 0n if not found (should not happen under normal conditions).
689
+ */
690
+ extractProjectIdFromLogs(logs) {
691
+ for (const log of logs) {
692
+ const l = log;
693
+ // ProjectCreated(uint256 indexed projectId, ...)
694
+ // topics[1] = projectId
695
+ if (l.topics && l.topics.length >= 2) {
696
+ try {
697
+ return BigInt(l.topics[1]);
698
+ }
699
+ catch {
700
+ continue;
701
+ }
702
+ }
703
+ }
704
+ return 0n;
705
+ }
706
+ }
707
+ exports.ProjectRegistry = ProjectRegistry;
708
+ //# sourceMappingURL=ProjectRegistry.js.map