moltlaunch 2.0.0 → 2.0.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 (105) hide show
  1. package/package.json +5 -1
  2. package/.claude/commands/deploy.md +0 -33
  3. package/.claude/hooks/regenerate-docs.sh +0 -12
  4. package/.claude/settings.json +0 -15
  5. package/.env.example +0 -2
  6. package/.github/workflows/deploy.yml +0 -37
  7. package/ROADMAP.md +0 -29
  8. package/contracts/MandateEscrowV4.sol +0 -281
  9. package/contracts/mocks/MockFlaunchBuyback.sol +0 -24
  10. package/hardhat.config.cjs +0 -29
  11. package/scripts/check-deploy-cost.ts +0 -15
  12. package/scripts/deploy-escrow-v4.ts +0 -81
  13. package/scripts/deploy-escrow.cjs +0 -22
  14. package/scripts/generate-docs.ts +0 -309
  15. package/shared/manifest.json +0 -87
  16. package/site/.vscode/extensions.json +0 -4
  17. package/site/.vscode/launch.json +0 -11
  18. package/site/README.md +0 -43
  19. package/site/astro.config.mjs +0 -21
  20. package/site/functions/agent/[[path]].ts +0 -9
  21. package/site/functions/task/[[path]].ts +0 -9
  22. package/site/index.html.bak +0 -1755
  23. package/site/package-lock.json +0 -6165
  24. package/site/package.json +0 -17
  25. package/site/public/_redirects +0 -1
  26. package/site/public/art/hero.webp +0 -0
  27. package/site/public/favicon.ico +0 -0
  28. package/site/public/favicon.svg +0 -4
  29. package/site/public/logo.png +0 -0
  30. package/site/public/skill.md +0 -276
  31. package/site/src/components/AgentGridCard.astro +0 -97
  32. package/site/src/components/AgentRow.astro +0 -75
  33. package/site/src/components/Footer.astro +0 -71
  34. package/site/src/components/GigCard.astro +0 -36
  35. package/site/src/components/Navbar.astro +0 -93
  36. package/site/src/components/ReviewCard.astro +0 -29
  37. package/site/src/components/SkillPill.astro +0 -19
  38. package/site/src/components/StatusBadge.astro +0 -27
  39. package/site/src/components/TaskEntry.astro +0 -98
  40. package/site/src/layouts/Layout.astro +0 -268
  41. package/site/src/lib/api.ts +0 -342
  42. package/site/src/pages/404.astro +0 -33
  43. package/site/src/pages/admin.astro +0 -445
  44. package/site/src/pages/agent/[...id].astro +0 -678
  45. package/site/src/pages/agents/index.astro +0 -235
  46. package/site/src/pages/dashboard.astro +0 -244
  47. package/site/src/pages/docs.astro +0 -191
  48. package/site/src/pages/how.astro +0 -156
  49. package/site/src/pages/index.astro +0 -226
  50. package/site/src/pages/leaderboard.astro +0 -155
  51. package/site/src/pages/task/[...id].astro +0 -1467
  52. package/site/src/styles/global.css +0 -159
  53. package/site/tailwind.config.mjs +0 -94
  54. package/site/tsconfig.json +0 -5
  55. package/site/wrangler.toml +0 -5
  56. package/src/commands/accept.ts +0 -135
  57. package/src/commands/agents.ts +0 -190
  58. package/src/commands/approve.ts +0 -127
  59. package/src/commands/claim.ts +0 -130
  60. package/src/commands/decline.ts +0 -55
  61. package/src/commands/dispute.ts +0 -92
  62. package/src/commands/earnings.ts +0 -86
  63. package/src/commands/feedback.ts +0 -147
  64. package/src/commands/gig.ts +0 -141
  65. package/src/commands/hire.ts +0 -96
  66. package/src/commands/inbox.ts +0 -135
  67. package/src/commands/message.ts +0 -97
  68. package/src/commands/profile.ts +0 -62
  69. package/src/commands/quote.ts +0 -80
  70. package/src/commands/refund.ts +0 -82
  71. package/src/commands/register.ts +0 -250
  72. package/src/commands/resolve.ts +0 -104
  73. package/src/commands/reviews.ts +0 -78
  74. package/src/commands/revise.ts +0 -65
  75. package/src/commands/submit.ts +0 -123
  76. package/src/commands/tasks.ts +0 -224
  77. package/src/commands/view.ts +0 -122
  78. package/src/commands/wallet.ts +0 -42
  79. package/src/index.ts +0 -285
  80. package/src/lib/agent0.ts +0 -158
  81. package/src/lib/auth.ts +0 -25
  82. package/src/lib/constants.ts +0 -55
  83. package/src/lib/escrow.ts +0 -374
  84. package/src/lib/files.ts +0 -87
  85. package/src/lib/flaunch.ts +0 -277
  86. package/src/lib/mandate.ts +0 -623
  87. package/src/lib/tasks.ts +0 -466
  88. package/src/lib/types.ts +0 -112
  89. package/src/lib/wallet.ts +0 -119
  90. package/src/lib/x402.ts +0 -86
  91. package/test/MandateEscrowV4.test.cjs +0 -568
  92. package/tsconfig.json +0 -19
  93. package/tsup.config.ts +0 -15
  94. package/worker/package-lock.json +0 -1812
  95. package/worker/package.json +0 -18
  96. package/worker/src/agents.ts +0 -755
  97. package/worker/src/auth.ts +0 -126
  98. package/worker/src/files.ts +0 -40
  99. package/worker/src/index.ts +0 -963
  100. package/worker/src/profiles.ts +0 -85
  101. package/worker/src/ratelimit.ts +0 -45
  102. package/worker/src/tasks.ts +0 -498
  103. package/worker/src/types.ts +0 -95
  104. package/worker/tsconfig.json +0 -15
  105. package/worker/wrangler.toml +0 -19
@@ -1,623 +0,0 @@
1
- // MANDATE: ERC-8004 Contract Interactions
2
- // Identity Registry, Reputation Registry
3
- // Contracts: https://github.com/erc-8004/erc-8004-contracts
4
-
5
- import {
6
- createPublicClient,
7
- createWalletClient,
8
- http,
9
- keccak256,
10
- toBytes,
11
- type Address,
12
- type Log,
13
- decodeEventLog,
14
- } from "viem";
15
- import { base } from "viem/chains";
16
- import { privateKeyToAccount } from "viem/accounts";
17
- import { CONTRACTS, METADATA_KEYS, BASE_RPC_URL } from "./constants.js";
18
- import type { Agent, ReputationSummary, Wallet } from "./types.js";
19
-
20
- // ERC-8004 Identity Registry ABI (from official repo)
21
- const IDENTITY_REGISTRY_ABI = [
22
- // Register with URI and metadata
23
- {
24
- name: "register",
25
- type: "function",
26
- stateMutability: "nonpayable",
27
- inputs: [
28
- { name: "agentURI", type: "string" },
29
- {
30
- name: "metadata",
31
- type: "tuple[]",
32
- components: [
33
- { name: "metadataKey", type: "string" },
34
- { name: "metadataValue", type: "bytes" },
35
- ],
36
- },
37
- ],
38
- outputs: [{ name: "agentId", type: "uint256" }],
39
- },
40
- // Register with just URI
41
- {
42
- name: "register",
43
- type: "function",
44
- stateMutability: "nonpayable",
45
- inputs: [{ name: "agentURI", type: "string" }],
46
- outputs: [{ name: "agentId", type: "uint256" }],
47
- },
48
- // Register empty
49
- {
50
- name: "register",
51
- type: "function",
52
- stateMutability: "nonpayable",
53
- inputs: [],
54
- outputs: [{ name: "agentId", type: "uint256" }],
55
- },
56
- {
57
- name: "setAgentWallet",
58
- type: "function",
59
- stateMutability: "nonpayable",
60
- inputs: [
61
- { name: "agentId", type: "uint256" },
62
- { name: "newWallet", type: "address" },
63
- { name: "deadline", type: "uint256" },
64
- { name: "signature", type: "bytes" },
65
- ],
66
- outputs: [],
67
- },
68
- {
69
- name: "getAgentWallet",
70
- type: "function",
71
- stateMutability: "view",
72
- inputs: [{ name: "agentId", type: "uint256" }],
73
- outputs: [{ name: "", type: "address" }],
74
- },
75
- {
76
- name: "unsetAgentWallet",
77
- type: "function",
78
- stateMutability: "nonpayable",
79
- inputs: [{ name: "agentId", type: "uint256" }],
80
- outputs: [],
81
- },
82
- {
83
- name: "getMetadata",
84
- type: "function",
85
- stateMutability: "view",
86
- inputs: [
87
- { name: "agentId", type: "uint256" },
88
- { name: "metadataKey", type: "string" },
89
- ],
90
- outputs: [{ name: "", type: "bytes" }],
91
- },
92
- {
93
- name: "setMetadata",
94
- type: "function",
95
- stateMutability: "nonpayable",
96
- inputs: [
97
- { name: "agentId", type: "uint256" },
98
- { name: "metadataKey", type: "string" },
99
- { name: "metadataValue", type: "bytes" },
100
- ],
101
- outputs: [],
102
- },
103
- {
104
- name: "setAgentURI",
105
- type: "function",
106
- stateMutability: "nonpayable",
107
- inputs: [
108
- { name: "agentId", type: "uint256" },
109
- { name: "newURI", type: "string" },
110
- ],
111
- outputs: [],
112
- },
113
- {
114
- name: "tokenURI",
115
- type: "function",
116
- stateMutability: "view",
117
- inputs: [{ name: "tokenId", type: "uint256" }],
118
- outputs: [{ name: "", type: "string" }],
119
- },
120
- {
121
- name: "ownerOf",
122
- type: "function",
123
- stateMutability: "view",
124
- inputs: [{ name: "tokenId", type: "uint256" }],
125
- outputs: [{ name: "", type: "address" }],
126
- },
127
- {
128
- name: "balanceOf",
129
- type: "function",
130
- stateMutability: "view",
131
- inputs: [{ name: "owner", type: "address" }],
132
- outputs: [{ name: "", type: "uint256" }],
133
- },
134
- // Events
135
- {
136
- name: "Registered",
137
- type: "event",
138
- inputs: [
139
- { name: "agentId", type: "uint256", indexed: true },
140
- { name: "agentURI", type: "string", indexed: false },
141
- { name: "owner", type: "address", indexed: true },
142
- ],
143
- },
144
- {
145
- name: "MetadataSet",
146
- type: "event",
147
- inputs: [
148
- { name: "agentId", type: "uint256", indexed: true },
149
- { name: "indexedMetadataKey", type: "string", indexed: true },
150
- { name: "metadataKey", type: "string", indexed: false },
151
- { name: "metadataValue", type: "bytes", indexed: false },
152
- ],
153
- },
154
- ] as const;
155
-
156
- // ERC-8004 Reputation Registry ABI (from official repo)
157
- const REPUTATION_REGISTRY_ABI = [
158
- {
159
- name: "giveFeedback",
160
- type: "function",
161
- stateMutability: "nonpayable",
162
- inputs: [
163
- { name: "agentId", type: "uint256" },
164
- { name: "value", type: "int128" },
165
- { name: "valueDecimals", type: "uint8" },
166
- { name: "tag1", type: "string" },
167
- { name: "tag2", type: "string" },
168
- { name: "endpoint", type: "string" },
169
- { name: "feedbackURI", type: "string" },
170
- { name: "feedbackHash", type: "bytes32" },
171
- ],
172
- outputs: [],
173
- },
174
- {
175
- name: "getSummary",
176
- type: "function",
177
- stateMutability: "view",
178
- inputs: [
179
- { name: "agentId", type: "uint256" },
180
- { name: "clientAddresses", type: "address[]" },
181
- { name: "tag1", type: "string" },
182
- { name: "tag2", type: "string" },
183
- ],
184
- outputs: [
185
- { name: "count", type: "uint64" },
186
- { name: "summaryValue", type: "int128" },
187
- { name: "summaryValueDecimals", type: "uint8" },
188
- ],
189
- },
190
- {
191
- name: "revokeFeedback",
192
- type: "function",
193
- stateMutability: "nonpayable",
194
- inputs: [
195
- { name: "agentId", type: "uint256" },
196
- { name: "feedbackIndex", type: "uint64" },
197
- ],
198
- outputs: [],
199
- },
200
- {
201
- name: "readFeedback",
202
- type: "function",
203
- stateMutability: "view",
204
- inputs: [
205
- { name: "agentId", type: "uint256" },
206
- { name: "clientAddress", type: "address" },
207
- { name: "feedbackIndex", type: "uint64" },
208
- ],
209
- outputs: [
210
- { name: "value", type: "int128" },
211
- { name: "valueDecimals", type: "uint8" },
212
- { name: "tag1", type: "string" },
213
- { name: "tag2", type: "string" },
214
- { name: "isRevoked", type: "bool" },
215
- ],
216
- },
217
- {
218
- name: "readAllFeedback",
219
- type: "function",
220
- stateMutability: "view",
221
- inputs: [
222
- { name: "agentId", type: "uint256" },
223
- { name: "clientAddresses", type: "address[]" },
224
- { name: "tag1", type: "string" },
225
- { name: "tag2", type: "string" },
226
- { name: "includeRevoked", type: "bool" },
227
- ],
228
- outputs: [
229
- { name: "clients", type: "address[]" },
230
- { name: "feedbackIndexes", type: "uint64[]" },
231
- { name: "values", type: "int128[]" },
232
- { name: "valueDecimals", type: "uint8[]" },
233
- { name: "tag1s", type: "string[]" },
234
- { name: "tag2s", type: "string[]" },
235
- { name: "revokedStatuses", type: "bool[]" },
236
- ],
237
- },
238
- {
239
- name: "getClients",
240
- type: "function",
241
- stateMutability: "view",
242
- inputs: [{ name: "agentId", type: "uint256" }],
243
- outputs: [{ name: "", type: "address[]" }],
244
- },
245
- {
246
- name: "getLastIndex",
247
- type: "function",
248
- stateMutability: "view",
249
- inputs: [
250
- { name: "agentId", type: "uint256" },
251
- { name: "clientAddress", type: "address" },
252
- ],
253
- outputs: [{ name: "", type: "uint64" }],
254
- },
255
- // Events
256
- {
257
- name: "NewFeedback",
258
- type: "event",
259
- inputs: [
260
- { name: "agentId", type: "uint256", indexed: true },
261
- { name: "clientAddress", type: "address", indexed: true },
262
- { name: "feedbackIndex", type: "uint64", indexed: false },
263
- { name: "value", type: "int128", indexed: false },
264
- { name: "valueDecimals", type: "uint8", indexed: false },
265
- { name: "indexedTag1", type: "string", indexed: true },
266
- { name: "tag1", type: "string", indexed: false },
267
- { name: "tag2", type: "string", indexed: false },
268
- { name: "endpoint", type: "string", indexed: false },
269
- { name: "feedbackURI", type: "string", indexed: false },
270
- { name: "feedbackHash", type: "bytes32", indexed: false },
271
- ],
272
- },
273
- {
274
- name: "FeedbackRevoked",
275
- type: "event",
276
- inputs: [
277
- { name: "agentId", type: "uint256", indexed: true },
278
- { name: "clientAddress", type: "address", indexed: true },
279
- { name: "feedbackIndex", type: "uint64", indexed: true },
280
- ],
281
- },
282
- ] as const;
283
-
284
- function getPublicClient() {
285
- return createPublicClient({
286
- chain: base,
287
- transport: http(BASE_RPC_URL),
288
- });
289
- }
290
-
291
- function getWalletClient(wallet: Wallet) {
292
- const account = privateKeyToAccount(wallet.privateKey);
293
- return createWalletClient({
294
- account,
295
- chain: base,
296
- transport: http(BASE_RPC_URL),
297
- });
298
- }
299
-
300
- // Encode string to bytes for metadata
301
- function encodeString(value: string): `0x${string}` {
302
- return `0x${Buffer.from(value, "utf-8").toString("hex")}`;
303
- }
304
-
305
- // Decode bytes to string from metadata
306
- function decodeString(value: `0x${string}`): string {
307
- if (!value || value === "0x") return "";
308
- return Buffer.from(value.slice(2), "hex").toString("utf-8");
309
- }
310
-
311
- // Encode bigint to bytes for metadata (32 bytes, big-endian)
312
- function encodeBigInt(value: bigint): `0x${string}` {
313
- return `0x${value.toString(16).padStart(64, "0")}`;
314
- }
315
-
316
- // Decode bytes to bigint from metadata
317
- function decodeBigInt(value: `0x${string}`): bigint {
318
- if (!value || value === "0x") return 0n;
319
- return BigInt(value);
320
- }
321
-
322
- /**
323
- * Register a new agent in the ERC-8004 Identity Registry
324
- */
325
- export async function registerAgent(
326
- wallet: Wallet,
327
- agentURI: string,
328
- metadata: {
329
- skills: string[];
330
- endpoint: string;
331
- priceWei: bigint;
332
- flaunchToken?: `0x${string}`;
333
- }
334
- ): Promise<{ agentId: bigint; txHash: `0x${string}` }> {
335
- const client = getWalletClient(wallet);
336
- const publicClient = getPublicClient();
337
-
338
- const metadataEntries: Array<{ metadataKey: string; metadataValue: `0x${string}` }> = [
339
- { metadataKey: METADATA_KEYS.SKILLS, metadataValue: encodeString(metadata.skills.join(",")) },
340
- { metadataKey: METADATA_KEYS.ENDPOINT, metadataValue: encodeString(metadata.endpoint) },
341
- { metadataKey: METADATA_KEYS.PRICE_WEI, metadataValue: encodeBigInt(metadata.priceWei) },
342
- ];
343
-
344
- if (metadata.flaunchToken) {
345
- metadataEntries.push({
346
- metadataKey: METADATA_KEYS.FLAUNCH_TOKEN,
347
- metadataValue: metadata.flaunchToken,
348
- });
349
- }
350
-
351
- const txHash = await client.writeContract({
352
- address: CONTRACTS.IDENTITY_REGISTRY,
353
- abi: IDENTITY_REGISTRY_ABI,
354
- functionName: "register",
355
- args: [agentURI, metadataEntries],
356
- });
357
-
358
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
359
-
360
- // Parse agentId from Registered event
361
- let agentId = 0n;
362
- for (const log of receipt.logs) {
363
- try {
364
- const decoded = decodeEventLog({
365
- abi: IDENTITY_REGISTRY_ABI,
366
- data: log.data,
367
- topics: log.topics,
368
- });
369
- if (decoded.eventName === "Registered") {
370
- agentId = (decoded.args as { agentId: bigint }).agentId;
371
- break;
372
- }
373
- } catch {
374
- // Not our event, skip
375
- }
376
- }
377
-
378
- return { agentId, txHash };
379
- }
380
-
381
- /**
382
- * Get agent details from ERC-8004 registries
383
- */
384
- export async function getAgent(agentId: bigint): Promise<Agent | null> {
385
- const client = getPublicClient();
386
-
387
- try {
388
- // Get owner
389
- const owner = await client.readContract({
390
- address: CONTRACTS.IDENTITY_REGISTRY,
391
- abi: IDENTITY_REGISTRY_ABI,
392
- functionName: "ownerOf",
393
- args: [agentId],
394
- });
395
-
396
- // Get agent URI (metadata JSON)
397
- const agentURI = await client.readContract({
398
- address: CONTRACTS.IDENTITY_REGISTRY,
399
- abi: IDENTITY_REGISTRY_ABI,
400
- functionName: "tokenURI",
401
- args: [agentId],
402
- });
403
-
404
- // Get agent wallet (payment address)
405
- const agentWallet = await client.readContract({
406
- address: CONTRACTS.IDENTITY_REGISTRY,
407
- abi: IDENTITY_REGISTRY_ABI,
408
- functionName: "getAgentWallet",
409
- args: [agentId],
410
- });
411
-
412
- // Get MANDATE-specific metadata
413
- const [skillsBytes, endpointBytes, priceBytes] = await Promise.all([
414
- client.readContract({
415
- address: CONTRACTS.IDENTITY_REGISTRY,
416
- abi: IDENTITY_REGISTRY_ABI,
417
- functionName: "getMetadata",
418
- args: [agentId, METADATA_KEYS.SKILLS],
419
- }),
420
- client.readContract({
421
- address: CONTRACTS.IDENTITY_REGISTRY,
422
- abi: IDENTITY_REGISTRY_ABI,
423
- functionName: "getMetadata",
424
- args: [agentId, METADATA_KEYS.ENDPOINT],
425
- }),
426
- client.readContract({
427
- address: CONTRACTS.IDENTITY_REGISTRY,
428
- abi: IDENTITY_REGISTRY_ABI,
429
- functionName: "getMetadata",
430
- args: [agentId, METADATA_KEYS.PRICE_WEI],
431
- }),
432
- ]);
433
-
434
- // Get reputation summary
435
- const [count, summaryValue, summaryValueDecimals] = await client.readContract({
436
- address: CONTRACTS.REPUTATION_REGISTRY,
437
- abi: REPUTATION_REGISTRY_ABI,
438
- functionName: "getSummary",
439
- args: [agentId, [], "", ""],
440
- });
441
-
442
- // Parse metadata
443
- const skills = skillsBytes ? decodeString(skillsBytes as `0x${string}`).split(",").filter(Boolean) : [];
444
- const endpoint = endpointBytes ? decodeString(endpointBytes as `0x${string}`) : "";
445
- const priceWei = priceBytes ? decodeBigInt(priceBytes as `0x${string}`) : 0n;
446
-
447
- // Parse name/description from agentURI if it's a data URI or fetch from IPFS
448
- let name = `Agent #${agentId}`;
449
- let description = "";
450
-
451
- if (typeof agentURI === "string" && agentURI.startsWith("data:application/json")) {
452
- try {
453
- let jsonStr: string;
454
- if (agentURI.includes(";base64,")) {
455
- // Base64 encoded
456
- const base64 = agentURI.split(";base64,")[1];
457
- jsonStr = Buffer.from(base64, "base64").toString("utf-8");
458
- } else {
459
- // URL encoded
460
- jsonStr = decodeURIComponent(agentURI.split(",")[1]);
461
- }
462
- const meta = JSON.parse(jsonStr);
463
- name = meta.name || name;
464
- description = meta.description || "";
465
- } catch {
466
- // Couldn't parse, use defaults
467
- }
468
- }
469
-
470
- const agent: Agent = {
471
- agentId,
472
- owner: owner as `0x${string}`,
473
- agentURI: agentURI as string,
474
- agentWallet: (agentWallet as `0x${string}`) || owner,
475
- name,
476
- description,
477
- skills,
478
- endpoint,
479
- priceWei,
480
- reputation: {
481
- count,
482
- summaryValue,
483
- summaryValueDecimals,
484
- },
485
- };
486
-
487
- return agent;
488
- } catch (err) {
489
- // Agent doesn't exist or error reading
490
- return null;
491
- }
492
- }
493
-
494
- /**
495
- * Check if a wallet already has a registered agent.
496
- * Queries Transfer events from the Identity Registry to find the actual agentId.
497
- */
498
- export async function getAgentByOwner(ownerAddress: `0x${string}`): Promise<bigint | null> {
499
- const client = getPublicClient();
500
-
501
- try {
502
- const balance = await client.readContract({
503
- address: CONTRACTS.IDENTITY_REGISTRY,
504
- abi: IDENTITY_REGISTRY_ABI,
505
- functionName: "balanceOf",
506
- args: [ownerAddress],
507
- });
508
-
509
- if (balance === 0n) return null;
510
-
511
- // Query Registered events where owner matches
512
- const logs = await client.getLogs({
513
- address: CONTRACTS.IDENTITY_REGISTRY,
514
- event: {
515
- type: "event",
516
- name: "Registered",
517
- inputs: [
518
- { name: "agentId", type: "uint256", indexed: true },
519
- { name: "agentURI", type: "string", indexed: false },
520
- { name: "owner", type: "address", indexed: true },
521
- ],
522
- },
523
- args: { owner: ownerAddress },
524
- fromBlock: 0n,
525
- toBlock: "latest",
526
- });
527
-
528
- if (logs.length === 0) return null;
529
-
530
- // Return the most recent registration
531
- const lastLog = logs[logs.length - 1];
532
- return lastLog.args.agentId ?? null;
533
- } catch {
534
- return null;
535
- }
536
- }
537
-
538
- /**
539
- * Submit feedback for an agent after hiring
540
- * Links feedback to a completed task via feedbackHash (same keccak256 used in escrow)
541
- */
542
- export async function giveFeedback(
543
- wallet: Wallet,
544
- agentId: bigint,
545
- score: number, // 0-100
546
- options?: {
547
- taskId?: string; // Links feedback to a completed task
548
- agentContractAddress?: string; // Agent's contract address (CA) for tag2
549
- endpoint?: string;
550
- }
551
- ): Promise<`0x${string}`> {
552
- const client = getWalletClient(wallet);
553
- const publicClient = getPublicClient();
554
-
555
- // Compute feedbackHash from taskId (same hash used in escrow contract)
556
- const feedbackHash: `0x${string}` = options?.taskId
557
- ? keccak256(toBytes(options.taskId))
558
- : "0x0000000000000000000000000000000000000000000000000000000000000000";
559
-
560
- const feedbackURI = options?.taskId
561
- ? `moltlaunch:task:${options.taskId}`
562
- : "";
563
-
564
- const txHash = await client.writeContract({
565
- address: CONTRACTS.REPUTATION_REGISTRY,
566
- abi: REPUTATION_REGISTRY_ABI,
567
- functionName: "giveFeedback",
568
- args: [
569
- agentId,
570
- BigInt(score),
571
- 0, // No decimals for 0-100 score
572
- "mandate", // tag1: platform identifier
573
- options?.agentContractAddress || "", // tag2: agent's contract address
574
- options?.endpoint || "",
575
- feedbackURI,
576
- feedbackHash,
577
- ],
578
- });
579
-
580
- await publicClient.waitForTransactionReceipt({ hash: txHash });
581
-
582
- return txHash;
583
- }
584
-
585
- /**
586
- * Get reputation summary for an agent
587
- */
588
- export async function getReputationSummary(
589
- agentId: bigint,
590
- tag1?: string,
591
- tag2?: string
592
- ): Promise<ReputationSummary> {
593
- const client = getPublicClient();
594
-
595
- const [count, summaryValue, summaryValueDecimals] = await client.readContract({
596
- address: CONTRACTS.REPUTATION_REGISTRY,
597
- abi: REPUTATION_REGISTRY_ABI,
598
- functionName: "getSummary",
599
- args: [agentId, [], tag1 || "", tag2 || ""],
600
- });
601
-
602
- return {
603
- count,
604
- summaryValue,
605
- summaryValueDecimals,
606
- };
607
- }
608
-
609
- /**
610
- * Get all feedback for an agent
611
- */
612
- export async function getAllFeedback(agentId: bigint) {
613
- const client = getPublicClient();
614
-
615
- const result = await client.readContract({
616
- address: CONTRACTS.REPUTATION_REGISTRY,
617
- abi: REPUTATION_REGISTRY_ABI,
618
- functionName: "readAllFeedback",
619
- args: [agentId, [], "", "", false],
620
- });
621
-
622
- return result;
623
- }