@q00bs/agent-sdk 1.0.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 (85) hide show
  1. package/dist/Q00bsAgent.d.ts +331 -0
  2. package/dist/Q00bsAgent.d.ts.map +1 -0
  3. package/dist/Q00bsAgent.js +695 -0
  4. package/dist/Q00bsAgent.js.map +1 -0
  5. package/dist/abis/AgentEscrow.d.ts +336 -0
  6. package/dist/abis/AgentEscrow.d.ts.map +1 -0
  7. package/dist/abis/AgentEscrow.js +206 -0
  8. package/dist/abis/AgentEscrow.js.map +1 -0
  9. package/dist/abis/AgentRegistry.d.ts +496 -0
  10. package/dist/abis/AgentRegistry.d.ts.map +1 -0
  11. package/dist/abis/AgentRegistry.js +280 -0
  12. package/dist/abis/AgentRegistry.js.map +1 -0
  13. package/dist/abis/ConsensusModule.d.ts +270 -0
  14. package/dist/abis/ConsensusModule.d.ts.map +1 -0
  15. package/dist/abis/ConsensusModule.js +157 -0
  16. package/dist/abis/ConsensusModule.js.map +1 -0
  17. package/dist/abis/ERC8004Identity.d.ts +293 -0
  18. package/dist/abis/ERC8004Identity.d.ts.map +1 -0
  19. package/dist/abis/ERC8004Identity.js +223 -0
  20. package/dist/abis/ERC8004Identity.js.map +1 -0
  21. package/dist/abis/ERC8004Reputation.d.ts +362 -0
  22. package/dist/abis/ERC8004Reputation.d.ts.map +1 -0
  23. package/dist/abis/ERC8004Reputation.js +229 -0
  24. package/dist/abis/ERC8004Reputation.js.map +1 -0
  25. package/dist/abis/ERC8004Validation.d.ts +234 -0
  26. package/dist/abis/ERC8004Validation.d.ts.map +1 -0
  27. package/dist/abis/ERC8004Validation.js +162 -0
  28. package/dist/abis/ERC8004Validation.js.map +1 -0
  29. package/dist/abis/Q00bFactory.d.ts +123 -0
  30. package/dist/abis/Q00bFactory.d.ts.map +1 -0
  31. package/dist/abis/Q00bFactory.js +65 -0
  32. package/dist/abis/Q00bFactory.js.map +1 -0
  33. package/dist/abis/TheQ00bs.d.ts +119 -0
  34. package/dist/abis/TheQ00bs.d.ts.map +1 -0
  35. package/dist/abis/TheQ00bs.js +73 -0
  36. package/dist/abis/TheQ00bs.js.map +1 -0
  37. package/dist/abis/index.d.ts +9 -0
  38. package/dist/abis/index.d.ts.map +1 -0
  39. package/dist/abis/index.js +17 -0
  40. package/dist/abis/index.js.map +1 -0
  41. package/dist/client.d.ts +111 -0
  42. package/dist/client.d.ts.map +1 -0
  43. package/dist/client.js +134 -0
  44. package/dist/client.js.map +1 -0
  45. package/dist/consensus.d.ts +85 -0
  46. package/dist/consensus.d.ts.map +1 -0
  47. package/dist/consensus.js +227 -0
  48. package/dist/consensus.js.map +1 -0
  49. package/dist/constants.d.ts +85 -0
  50. package/dist/constants.d.ts.map +1 -0
  51. package/dist/constants.js +113 -0
  52. package/dist/constants.js.map +1 -0
  53. package/dist/discovery.d.ts +70 -0
  54. package/dist/discovery.d.ts.map +1 -0
  55. package/dist/discovery.js +214 -0
  56. package/dist/discovery.js.map +1 -0
  57. package/dist/erc8004.d.ts +311 -0
  58. package/dist/erc8004.d.ts.map +1 -0
  59. package/dist/erc8004.js +824 -0
  60. package/dist/erc8004.js.map +1 -0
  61. package/dist/errors.d.ts +107 -0
  62. package/dist/errors.d.ts.map +1 -0
  63. package/dist/errors.js +210 -0
  64. package/dist/errors.js.map +1 -0
  65. package/dist/escrow.d.ts +86 -0
  66. package/dist/escrow.d.ts.map +1 -0
  67. package/dist/escrow.js +267 -0
  68. package/dist/escrow.js.map +1 -0
  69. package/dist/index.d.ts +51 -0
  70. package/dist/index.d.ts.map +1 -0
  71. package/dist/index.js +118 -0
  72. package/dist/index.js.map +1 -0
  73. package/dist/privy.d.ts +197 -0
  74. package/dist/privy.d.ts.map +1 -0
  75. package/dist/privy.js +524 -0
  76. package/dist/privy.js.map +1 -0
  77. package/dist/trust.d.ts +49 -0
  78. package/dist/trust.d.ts.map +1 -0
  79. package/dist/trust.js +117 -0
  80. package/dist/trust.js.map +1 -0
  81. package/dist/types.d.ts +472 -0
  82. package/dist/types.d.ts.map +1 -0
  83. package/dist/types.js +36 -0
  84. package/dist/types.js.map +1 -0
  85. package/package.json +30 -0
@@ -0,0 +1,824 @@
1
+ "use strict";
2
+ /**
3
+ * @q00bs/agent-sdk — ERC-8004 Trustless Agents Manager
4
+ *
5
+ * This module integrates the ERC-8004 standard (Trustless Agents) into the
6
+ * Q00bs agent platform. ERC-8004 defines three on-chain registries that give
7
+ * agents interoperable identity, reputation, and validation across the
8
+ * broader ecosystem — not just within Q00bs.
9
+ *
10
+ * WHY ERC-8004?
11
+ * Q00bs agents already have identity via AgentRegistry (ERC-721) and trust
12
+ * via the q00b graph. ERC-8004 adds a PORTABLE layer:
13
+ * - Identity that other agent platforms can read and verify
14
+ * - Reputation that follows an agent across ecosystems
15
+ * - Validation from third-party auditors (compliance, capabilities)
16
+ *
17
+ * Base is already implementing ERC-8004, making it the canonical standard
18
+ * for agent identity on L2. Integrating now gives Q00bs agents first-mover
19
+ * advantage in the interoperable agent economy.
20
+ *
21
+ * ARCHITECTURE:
22
+ * ┌──────────────────┐ ┌────────────────────────────────────┐
23
+ * │ Q00bs │ │ ERC-8004 Registries (Base) │
24
+ * │ AgentRegistry │────▶│ IdentityRegistry (0x8004...432) │
25
+ * │ (your agents) │ │ ReputationRegistry (0x8004...b63) │
26
+ * │ │ │ ValidationRegistry (TBD) │
27
+ * └──────────────────┘ └────────────────────────────────────┘
28
+ *
29
+ * Q00bs agents register in BOTH registries:
30
+ * 1. AgentRegistry (Q00bs-specific: trust scores, q00b graph, escrow)
31
+ * 2. ERC-8004 IdentityRegistry (ecosystem-wide: portable identity)
32
+ *
33
+ * The ERC-8004 identity links back to the Q00bs agent via:
34
+ * - agentWallet (same wallet address)
35
+ * - agentURI (points to registration file with Q00bs metadata)
36
+ * - Metadata keys (e.g. "q00bs_agent_id", "q00bs_trust_score")
37
+ *
38
+ * THREE REGISTRIES:
39
+ *
40
+ * 1. IDENTITY REGISTRY (ERC-721)
41
+ * - Mint agent identity NFTs
42
+ * - Set agentURI (registration file)
43
+ * - Bind agent wallet with EIP-712/ERC-1271 proof
44
+ * - Store extensible key-value metadata
45
+ *
46
+ * 2. REPUTATION REGISTRY
47
+ * - Give signed fixed-point feedback to other agents
48
+ * - Read aggregate reputation summaries
49
+ * - Respond to feedback received
50
+ * - Self-feedback is prevented on-chain
51
+ *
52
+ * 3. VALIDATION REGISTRY (evolving)
53
+ * - Request validation from third-party validators
54
+ * - Read validation results and summaries
55
+ *
56
+ * REFERENCE: https://www.8004.org/build
57
+ *
58
+ * USAGE:
59
+ * ```ts
60
+ * const manager = new ERC8004Manager(publicClient, walletClient, logger);
61
+ *
62
+ * // Register an ERC-8004 identity
63
+ * const identity = await manager.registerIdentity('0xOwnerAddress');
64
+ *
65
+ * // Set the agent URI
66
+ * await manager.setAgentURI(identity.agentId, 'https://q00bs.com/agents/42.json');
67
+ *
68
+ * // Give feedback to another agent
69
+ * await manager.giveFeedback({
70
+ * subjectAgentId: 7,
71
+ * value: 4.5,
72
+ * decimals: 2,
73
+ * }, myAgentId);
74
+ *
75
+ * // Read reputation
76
+ * const summary = await manager.getReputationSummary(7);
77
+ * console.log(`Average: ${summary.average}`);
78
+ * ```
79
+ */
80
+ Object.defineProperty(exports, "__esModule", { value: true });
81
+ exports.ERC8004Manager = void 0;
82
+ const ERC8004Identity_1 = require("./abis/ERC8004Identity");
83
+ const ERC8004Reputation_1 = require("./abis/ERC8004Reputation");
84
+ const ERC8004Validation_1 = require("./abis/ERC8004Validation");
85
+ const errors_1 = require("./errors");
86
+ const constants_1 = require("./constants");
87
+ // ─────────────────────────────────────────────────────────────
88
+ // ERC-8004 MANAGER
89
+ // ─────────────────────────────────────────────────────────────
90
+ class ERC8004Manager {
91
+ publicClient;
92
+ walletClient;
93
+ logger;
94
+ // Registry addresses
95
+ identityRegistry;
96
+ reputationRegistry;
97
+ validationRegistry;
98
+ // Cached ERC-8004 identity for this agent
99
+ _erc8004AgentId;
100
+ /** The agent's ERC-8004 agentId (if registered). */
101
+ get erc8004AgentId() {
102
+ return this._erc8004AgentId;
103
+ }
104
+ /** The IdentityRegistry address being used. */
105
+ get identityRegistryAddress() {
106
+ return this.identityRegistry;
107
+ }
108
+ /** The ReputationRegistry address being used. */
109
+ get reputationRegistryAddress() {
110
+ return this.reputationRegistry;
111
+ }
112
+ constructor(publicClient, logger, walletClient, config) {
113
+ this.publicClient = publicClient;
114
+ this.walletClient = walletClient;
115
+ this.logger = logger;
116
+ // Use configured addresses or canonical Base mainnet defaults
117
+ this.identityRegistry = (config?.identityRegistryAddress || constants_1.ERC8004_IDENTITY_REGISTRY_ADDRESS);
118
+ this.reputationRegistry = (config?.reputationRegistryAddress || constants_1.ERC8004_REPUTATION_REGISTRY_ADDRESS);
119
+ this.validationRegistry = (config?.validationRegistryAddress || constants_1.ERC8004_VALIDATION_REGISTRY_ADDRESS);
120
+ this.logger.info(`ERC-8004 Manager initialized | Identity: ${this.identityRegistry} | Reputation: ${this.reputationRegistry}`);
121
+ }
122
+ // ─────────────────────────────────────────────────────────────
123
+ // IDENTITY REGISTRY
124
+ // ─────────────────────────────────────────────────────────────
125
+ /**
126
+ * Register a new ERC-8004 agent identity.
127
+ *
128
+ * Mints an ERC-721 token in the IdentityRegistry. The tokenId becomes
129
+ * the agent's ERC-8004 agentId.
130
+ *
131
+ * @param ownerAddress - Address to mint the identity NFT to.
132
+ * @returns The new ERC-8004 identity.
133
+ * @throws ERC8004RegistryError if the transaction fails.
134
+ *
135
+ * @example
136
+ * ```ts
137
+ * const identity = await erc8004.registerIdentity('0xYourAddress');
138
+ * console.log(`ERC-8004 ID: ${identity.agentId}`);
139
+ * console.log(`Identifier: ${identity.identifier}`);
140
+ * ```
141
+ */
142
+ async registerIdentity(ownerAddress) {
143
+ this.ensureWalletClient();
144
+ this.logger.info(`Registering ERC-8004 identity for ${ownerAddress}...`);
145
+ try {
146
+ const hash = await this.walletClient.writeContract({
147
+ address: this.identityRegistry,
148
+ abi: ERC8004Identity_1.ERC8004_IDENTITY_ABI,
149
+ functionName: 'register',
150
+ args: [ownerAddress],
151
+ });
152
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
153
+ this.logger.info(`ERC-8004 registration tx confirmed in block ${receipt.blockNumber}`);
154
+ // Parse agentId from Transfer event (ERC-721 mint: from=0x0, to=owner)
155
+ let agentId;
156
+ for (const log of receipt.logs) {
157
+ if (log.address?.toLowerCase() === this.identityRegistry.toLowerCase() &&
158
+ log.topics &&
159
+ log.topics.length >= 4) {
160
+ // Transfer event: topics[3] is the tokenId
161
+ agentId = Number(BigInt(log.topics[3]));
162
+ if (agentId > 0)
163
+ break;
164
+ }
165
+ }
166
+ if (!agentId) {
167
+ // Fallback: try to find from AgentRegistered event
168
+ for (const log of receipt.logs) {
169
+ if (log.topics && log.topics.length >= 3) {
170
+ const possibleId = Number(BigInt(log.topics[2]));
171
+ if (possibleId > 0) {
172
+ agentId = possibleId;
173
+ break;
174
+ }
175
+ }
176
+ }
177
+ }
178
+ if (!agentId) {
179
+ throw new errors_1.ERC8004Error('Registration succeeded but could not determine ERC-8004 agentId');
180
+ }
181
+ this._erc8004AgentId = agentId;
182
+ const identifier = this.buildIdentifier(agentId);
183
+ this.logger.info(`ERC-8004 identity registered: ${identifier} (agentId: ${agentId})`);
184
+ return {
185
+ agentId,
186
+ owner: ownerAddress,
187
+ agentURI: '',
188
+ agentWallet: '',
189
+ identifier,
190
+ };
191
+ }
192
+ catch (error) {
193
+ if (error instanceof errors_1.ERC8004Error)
194
+ throw error;
195
+ throw new errors_1.ERC8004RegistryError(this.identityRegistry, 'register', error instanceof Error ? error.message : String(error));
196
+ }
197
+ }
198
+ /**
199
+ * Get an ERC-8004 identity by agentId.
200
+ *
201
+ * @param agentId - The ERC-8004 agentId (tokenId).
202
+ * @returns The identity, or null if not found.
203
+ */
204
+ async getIdentity(agentId) {
205
+ try {
206
+ // Get owner
207
+ const owner = await this.publicClient.readContract({
208
+ address: this.identityRegistry,
209
+ abi: ERC8004Identity_1.ERC8004_IDENTITY_ABI,
210
+ functionName: 'ownerOf',
211
+ args: [BigInt(agentId)],
212
+ });
213
+ if (!owner || owner === '0x0000000000000000000000000000000000000000') {
214
+ return null;
215
+ }
216
+ // Get agentURI and agentWallet in parallel
217
+ const [agentURI, agentWallet] = await Promise.all([
218
+ this.publicClient.readContract({
219
+ address: this.identityRegistry,
220
+ abi: ERC8004Identity_1.ERC8004_IDENTITY_ABI,
221
+ functionName: 'tokenURI',
222
+ args: [BigInt(agentId)],
223
+ }).catch(() => ''),
224
+ this.publicClient.readContract({
225
+ address: this.identityRegistry,
226
+ abi: ERC8004Identity_1.ERC8004_IDENTITY_ABI,
227
+ functionName: 'getAgentWallet',
228
+ args: [BigInt(agentId)],
229
+ }).catch(() => '0x0000000000000000000000000000000000000000'),
230
+ ]);
231
+ return {
232
+ agentId,
233
+ owner,
234
+ agentURI,
235
+ agentWallet,
236
+ identifier: this.buildIdentifier(agentId),
237
+ };
238
+ }
239
+ catch {
240
+ return null;
241
+ }
242
+ }
243
+ /**
244
+ * Set the agentURI (tokenURI) for an ERC-8004 identity.
245
+ *
246
+ * The agentURI should point to a JSON file describing the agent
247
+ * (name, capabilities, endpoints, etc.).
248
+ *
249
+ * @param agentId - The ERC-8004 agentId.
250
+ * @param uri - The URI to set (IPFS, HTTPS, etc.).
251
+ *
252
+ * @example
253
+ * ```ts
254
+ * await erc8004.setAgentURI(42, 'ipfs://Qm.../agent.json');
255
+ * ```
256
+ */
257
+ async setAgentURI(agentId, uri) {
258
+ this.ensureWalletClient();
259
+ this.logger.info(`Setting agentURI for ERC-8004 agent ${agentId}: ${uri}`);
260
+ try {
261
+ const hash = await this.walletClient.writeContract({
262
+ address: this.identityRegistry,
263
+ abi: ERC8004Identity_1.ERC8004_IDENTITY_ABI,
264
+ functionName: 'setAgentURI',
265
+ args: [BigInt(agentId), uri],
266
+ });
267
+ await this.publicClient.waitForTransactionReceipt({ hash });
268
+ this.logger.info(`AgentURI set for agent ${agentId}`);
269
+ }
270
+ catch (error) {
271
+ throw new errors_1.ERC8004RegistryError(this.identityRegistry, 'setAgentURI', error instanceof Error ? error.message : String(error));
272
+ }
273
+ }
274
+ /**
275
+ * Get metadata for an ERC-8004 identity.
276
+ *
277
+ * @param agentId - The ERC-8004 agentId.
278
+ * @param key - The metadata key to read.
279
+ * @returns The metadata value (empty string if not set).
280
+ */
281
+ async getMetadata(agentId, key) {
282
+ try {
283
+ return await this.publicClient.readContract({
284
+ address: this.identityRegistry,
285
+ abi: ERC8004Identity_1.ERC8004_IDENTITY_ABI,
286
+ functionName: 'getMetadata',
287
+ args: [BigInt(agentId), key],
288
+ });
289
+ }
290
+ catch {
291
+ return '';
292
+ }
293
+ }
294
+ /**
295
+ * Set metadata on an ERC-8004 identity.
296
+ *
297
+ * Use this to store Q00bs-specific data on the ERC-8004 identity,
298
+ * making it discoverable by other platforms.
299
+ *
300
+ * @param agentId - The ERC-8004 agentId.
301
+ * @param key - The metadata key (cannot be "agentWallet" — use setAgentWallet).
302
+ * @param value - The metadata value.
303
+ *
304
+ * @example
305
+ * ```ts
306
+ * await erc8004.setMetadata(42, 'q00bs_agent_id', '7');
307
+ * await erc8004.setMetadata(42, 'q00bs_trust_score', '8500');
308
+ * await erc8004.setMetadata(42, 'capabilities', 'data_analysis,web_scraping');
309
+ * ```
310
+ */
311
+ async setMetadata(agentId, key, value) {
312
+ this.ensureWalletClient();
313
+ if (key === 'agentWallet') {
314
+ throw new errors_1.ERC8004Error('The "agentWallet" metadata key is reserved. Use setAgentWallet() instead.');
315
+ }
316
+ this.logger.info(`Setting metadata for ERC-8004 agent ${agentId}: ${key}=${value}`);
317
+ try {
318
+ const hash = await this.walletClient.writeContract({
319
+ address: this.identityRegistry,
320
+ abi: ERC8004Identity_1.ERC8004_IDENTITY_ABI,
321
+ functionName: 'setMetadata',
322
+ args: [BigInt(agentId), key, value],
323
+ });
324
+ await this.publicClient.waitForTransactionReceipt({ hash });
325
+ this.logger.info(`Metadata set for agent ${agentId}: ${key}`);
326
+ }
327
+ catch (error) {
328
+ throw new errors_1.ERC8004RegistryError(this.identityRegistry, 'setMetadata', error instanceof Error ? error.message : String(error));
329
+ }
330
+ }
331
+ /**
332
+ * Get the agent wallet address for an ERC-8004 identity.
333
+ *
334
+ * @param agentId - The ERC-8004 agentId.
335
+ * @returns The wallet address, or null if not set.
336
+ */
337
+ async getAgentWallet(agentId) {
338
+ try {
339
+ const wallet = await this.publicClient.readContract({
340
+ address: this.identityRegistry,
341
+ abi: ERC8004Identity_1.ERC8004_IDENTITY_ABI,
342
+ functionName: 'getAgentWallet',
343
+ args: [BigInt(agentId)],
344
+ });
345
+ if (wallet === '0x0000000000000000000000000000000000000000') {
346
+ return null;
347
+ }
348
+ return wallet;
349
+ }
350
+ catch {
351
+ return null;
352
+ }
353
+ }
354
+ /**
355
+ * Set the agent wallet for an ERC-8004 identity with EIP-712/ERC-1271 proof.
356
+ *
357
+ * The proof ensures the wallet owner has consented to being linked
358
+ * to this identity. In practice, this means the agent wallet signs
359
+ * a typed-data message proving ownership.
360
+ *
361
+ * @param agentId - The ERC-8004 agentId.
362
+ * @param wallet - The wallet address to bind.
363
+ * @param proof - The EIP-712 or ERC-1271 proof bytes.
364
+ */
365
+ async setAgentWallet(agentId, wallet, proof) {
366
+ this.ensureWalletClient();
367
+ this.logger.info(`Setting agentWallet for ERC-8004 agent ${agentId}: ${wallet}`);
368
+ try {
369
+ const hash = await this.walletClient.writeContract({
370
+ address: this.identityRegistry,
371
+ abi: ERC8004Identity_1.ERC8004_IDENTITY_ABI,
372
+ functionName: 'setAgentWallet',
373
+ args: [BigInt(agentId), wallet, proof],
374
+ });
375
+ await this.publicClient.waitForTransactionReceipt({ hash });
376
+ this.logger.info(`AgentWallet set for agent ${agentId}: ${wallet}`);
377
+ }
378
+ catch (error) {
379
+ throw new errors_1.ERC8004RegistryError(this.identityRegistry, 'setAgentWallet', error instanceof Error ? error.message : String(error));
380
+ }
381
+ }
382
+ /**
383
+ * Get the total number of ERC-8004 identities registered.
384
+ */
385
+ async getIdentityCount() {
386
+ try {
387
+ const total = await this.publicClient.readContract({
388
+ address: this.identityRegistry,
389
+ abi: ERC8004Identity_1.ERC8004_IDENTITY_ABI,
390
+ functionName: 'totalSupply',
391
+ });
392
+ return Number(total);
393
+ }
394
+ catch {
395
+ return 0;
396
+ }
397
+ }
398
+ // ─────────────────────────────────────────────────────────────
399
+ // REPUTATION REGISTRY
400
+ // ─────────────────────────────────────────────────────────────
401
+ /**
402
+ * Give feedback to another agent via the ERC-8004 ReputationRegistry.
403
+ *
404
+ * Feedback is a signed fixed-point number (e.g. 4.5 → value=450, decimals=2).
405
+ * Self-feedback is prevented at the contract level.
406
+ *
407
+ * @param params - Feedback parameters (subject, value, decimals).
408
+ * @param fromAgentId - The ERC-8004 agentId of the feedback giver (your agent).
409
+ * @param fromIdentityRegistry - Override sender's identity registry (default: this one).
410
+ * @returns The feedback index.
411
+ *
412
+ * @example
413
+ * ```ts
414
+ * const index = await erc8004.giveFeedback({
415
+ * subjectAgentId: 7,
416
+ * value: 4.5,
417
+ * decimals: 2,
418
+ * }, myERC8004AgentId);
419
+ * ```
420
+ */
421
+ async giveFeedback(params, fromAgentId, fromIdentityRegistry) {
422
+ this.ensureWalletClient();
423
+ // Prevent self-feedback at SDK level
424
+ if (params.subjectAgentId === fromAgentId &&
425
+ (!params.subjectIdentityRegistry ||
426
+ params.subjectIdentityRegistry.toLowerCase() === this.identityRegistry.toLowerCase())) {
427
+ throw new errors_1.ERC8004SelfFeedbackError();
428
+ }
429
+ const decimals = params.decimals ?? 2;
430
+ const scaledValue = Math.round(params.value * Math.pow(10, decimals));
431
+ this.logger.info(`Giving feedback: agent ${fromAgentId} → agent ${params.subjectAgentId} ` +
432
+ `(value: ${params.value}, scaled: ${scaledValue}, decimals: ${decimals})`);
433
+ const subjectRegistry = (params.subjectIdentityRegistry || this.identityRegistry);
434
+ const senderRegistry = (fromIdentityRegistry || this.identityRegistry);
435
+ try {
436
+ const hash = await this.walletClient.writeContract({
437
+ address: this.reputationRegistry,
438
+ abi: ERC8004Reputation_1.ERC8004_REPUTATION_ABI,
439
+ functionName: 'giveFeedback',
440
+ args: [
441
+ subjectRegistry,
442
+ BigInt(params.subjectAgentId),
443
+ senderRegistry,
444
+ BigInt(fromAgentId),
445
+ BigInt(scaledValue),
446
+ decimals,
447
+ ],
448
+ });
449
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
450
+ this.logger.info(`Feedback given in block ${receipt.blockNumber}`);
451
+ // Parse feedback index from FeedbackGiven event
452
+ for (const log of receipt.logs) {
453
+ if (log.address?.toLowerCase() === this.reputationRegistry.toLowerCase()) {
454
+ // Try to get feedbackIndex from event data
455
+ if (log.data && log.data.length > 2) {
456
+ // feedbackIndex is typically the last uint256 in the event data
457
+ const dataHex = log.data.slice(2); // remove 0x prefix
458
+ // Each uint256 is 64 hex chars; feedbackIndex is the last one
459
+ if (dataHex.length >= 64) {
460
+ const lastWord = dataHex.slice(-64);
461
+ return Number(BigInt('0x' + lastWord));
462
+ }
463
+ }
464
+ }
465
+ }
466
+ // Fallback: use getLastIndex
467
+ return await this.getLastFeedbackIndex(params.subjectAgentId, subjectRegistry);
468
+ }
469
+ catch (error) {
470
+ if (error instanceof errors_1.ERC8004SelfFeedbackError)
471
+ throw error;
472
+ throw new errors_1.ERC8004RegistryError(this.reputationRegistry, 'giveFeedback', error instanceof Error ? error.message : String(error));
473
+ }
474
+ }
475
+ /**
476
+ * Revoke previously given feedback.
477
+ *
478
+ * @param subjectAgentId - The agent that received the feedback.
479
+ * @param fromAgentId - Your agent's ERC-8004 ID.
480
+ * @param feedbackIndex - The index of the feedback to revoke.
481
+ * @param subjectIdentityRegistry - Override subject's registry.
482
+ * @param fromIdentityRegistry - Override sender's registry.
483
+ */
484
+ async revokeFeedback(subjectAgentId, fromAgentId, feedbackIndex, subjectIdentityRegistry, fromIdentityRegistry) {
485
+ this.ensureWalletClient();
486
+ this.logger.info(`Revoking feedback index ${feedbackIndex} on agent ${subjectAgentId}`);
487
+ const subjectRegistry = (subjectIdentityRegistry || this.identityRegistry);
488
+ const senderRegistry = (fromIdentityRegistry || this.identityRegistry);
489
+ try {
490
+ const hash = await this.walletClient.writeContract({
491
+ address: this.reputationRegistry,
492
+ abi: ERC8004Reputation_1.ERC8004_REPUTATION_ABI,
493
+ functionName: 'revokeFeedback',
494
+ args: [
495
+ subjectRegistry,
496
+ BigInt(subjectAgentId),
497
+ senderRegistry,
498
+ BigInt(fromAgentId),
499
+ BigInt(feedbackIndex),
500
+ ],
501
+ });
502
+ await this.publicClient.waitForTransactionReceipt({ hash });
503
+ this.logger.info(`Feedback ${feedbackIndex} revoked for agent ${subjectAgentId}`);
504
+ }
505
+ catch (error) {
506
+ throw new errors_1.ERC8004RegistryError(this.reputationRegistry, 'revokeFeedback', error instanceof Error ? error.message : String(error));
507
+ }
508
+ }
509
+ /**
510
+ * Append a response to feedback your agent received.
511
+ *
512
+ * @param agentId - Your agent's ERC-8004 ID.
513
+ * @param fromAgentId - The feedback giver's ERC-8004 ID.
514
+ * @param feedbackIndex - The index of the feedback to respond to.
515
+ * @param response - The response text.
516
+ * @param fromIdentityRegistry - Override feedback giver's registry.
517
+ */
518
+ async respondToFeedback(agentId, fromAgentId, feedbackIndex, response, fromIdentityRegistry) {
519
+ this.ensureWalletClient();
520
+ this.logger.info(`Responding to feedback ${feedbackIndex} on agent ${agentId}`);
521
+ const senderRegistry = (fromIdentityRegistry || this.identityRegistry);
522
+ try {
523
+ const hash = await this.walletClient.writeContract({
524
+ address: this.reputationRegistry,
525
+ abi: ERC8004Reputation_1.ERC8004_REPUTATION_ABI,
526
+ functionName: 'appendResponse',
527
+ args: [
528
+ this.identityRegistry,
529
+ BigInt(agentId),
530
+ senderRegistry,
531
+ BigInt(fromAgentId),
532
+ BigInt(feedbackIndex),
533
+ response,
534
+ ],
535
+ });
536
+ await this.publicClient.waitForTransactionReceipt({ hash });
537
+ this.logger.info(`Response appended to feedback ${feedbackIndex}`);
538
+ }
539
+ catch (error) {
540
+ throw new errors_1.ERC8004RegistryError(this.reputationRegistry, 'appendResponse', error instanceof Error ? error.message : String(error));
541
+ }
542
+ }
543
+ /**
544
+ * Read a specific feedback entry.
545
+ *
546
+ * @param agentId - The agent's ERC-8004 ID.
547
+ * @param index - The feedback index.
548
+ * @param identityRegistry - Override identity registry.
549
+ * @returns The feedback entry.
550
+ */
551
+ async readFeedback(agentId, index, identityRegistry) {
552
+ const registry = (identityRegistry || this.identityRegistry);
553
+ try {
554
+ const raw = await this.publicClient.readContract({
555
+ address: this.reputationRegistry,
556
+ abi: ERC8004Reputation_1.ERC8004_REPUTATION_ABI,
557
+ functionName: 'readFeedback',
558
+ args: [registry, BigInt(agentId), BigInt(index)],
559
+ });
560
+ return {
561
+ fromIdentityRegistry: raw.fromIdentityRegistry,
562
+ fromAgentId: Number(raw.fromAgentId),
563
+ value: Number(raw.value),
564
+ valueDecimals: Number(raw.valueDecimals),
565
+ timestamp: Number(raw.timestamp),
566
+ revoked: raw.revoked,
567
+ response: raw.response,
568
+ };
569
+ }
570
+ catch (error) {
571
+ throw new errors_1.ERC8004RegistryError(this.reputationRegistry, 'readFeedback', error instanceof Error ? error.message : String(error));
572
+ }
573
+ }
574
+ /**
575
+ * Read all feedback entries for an agent.
576
+ *
577
+ * @param agentId - The agent's ERC-8004 ID.
578
+ * @param identityRegistry - Override identity registry.
579
+ * @returns Array of all feedback entries.
580
+ */
581
+ async readAllFeedback(agentId, identityRegistry) {
582
+ const registry = (identityRegistry || this.identityRegistry);
583
+ try {
584
+ const rawArray = await this.publicClient.readContract({
585
+ address: this.reputationRegistry,
586
+ abi: ERC8004Reputation_1.ERC8004_REPUTATION_ABI,
587
+ functionName: 'readAllFeedback',
588
+ args: [registry, BigInt(agentId)],
589
+ });
590
+ return rawArray.map((raw) => ({
591
+ fromIdentityRegistry: raw.fromIdentityRegistry,
592
+ fromAgentId: Number(raw.fromAgentId),
593
+ value: Number(raw.value),
594
+ valueDecimals: Number(raw.valueDecimals),
595
+ timestamp: Number(raw.timestamp),
596
+ revoked: raw.revoked,
597
+ response: raw.response,
598
+ }));
599
+ }
600
+ catch (error) {
601
+ throw new errors_1.ERC8004RegistryError(this.reputationRegistry, 'readAllFeedback', error instanceof Error ? error.message : String(error));
602
+ }
603
+ }
604
+ /**
605
+ * Get the reputation summary for an agent.
606
+ *
607
+ * @param agentId - The agent's ERC-8004 ID.
608
+ * @param identityRegistry - Override identity registry.
609
+ * @returns Aggregate reputation summary.
610
+ *
611
+ * @example
612
+ * ```ts
613
+ * const rep = await erc8004.getReputationSummary(42);
614
+ * console.log(`${rep.count} ratings, average: ${rep.average.toFixed(2)}`);
615
+ * ```
616
+ */
617
+ async getReputationSummary(agentId, identityRegistry) {
618
+ const registry = (identityRegistry || this.identityRegistry);
619
+ try {
620
+ const [count, sum, decimals] = await this.publicClient.readContract({
621
+ address: this.reputationRegistry,
622
+ abi: ERC8004Reputation_1.ERC8004_REPUTATION_ABI,
623
+ functionName: 'getSummary',
624
+ args: [registry, BigInt(agentId)],
625
+ });
626
+ const countNum = Number(count);
627
+ const sumNum = Number(sum);
628
+ const decNum = Number(decimals);
629
+ return {
630
+ count: countNum,
631
+ sum: sumNum,
632
+ decimals: decNum,
633
+ average: countNum > 0
634
+ ? sumNum / Math.pow(10, decNum) / countNum
635
+ : 0,
636
+ };
637
+ }
638
+ catch (error) {
639
+ throw new errors_1.ERC8004RegistryError(this.reputationRegistry, 'getSummary', error instanceof Error ? error.message : String(error));
640
+ }
641
+ }
642
+ /**
643
+ * Get the last feedback index for an agent.
644
+ */
645
+ async getLastFeedbackIndex(agentId, identityRegistry) {
646
+ const registry = (identityRegistry || this.identityRegistry);
647
+ try {
648
+ const index = await this.publicClient.readContract({
649
+ address: this.reputationRegistry,
650
+ abi: ERC8004Reputation_1.ERC8004_REPUTATION_ABI,
651
+ functionName: 'getLastIndex',
652
+ args: [registry, BigInt(agentId)],
653
+ });
654
+ return Number(index);
655
+ }
656
+ catch {
657
+ return 0;
658
+ }
659
+ }
660
+ // ─────────────────────────────────────────────────────────────
661
+ // VALIDATION REGISTRY
662
+ // ─────────────────────────────────────────────────────────────
663
+ /**
664
+ * Request validation from a validator contract.
665
+ *
666
+ * @param agentId - The agent's ERC-8004 ID.
667
+ * @param validatorContract - The validator contract address.
668
+ * @returns The validation request ID.
669
+ */
670
+ async requestValidation(agentId, validatorContract) {
671
+ this.ensureWalletClient();
672
+ this.ensureValidationRegistry();
673
+ this.logger.info(`Requesting validation for agent ${agentId} from validator ${validatorContract}`);
674
+ try {
675
+ const hash = await this.walletClient.writeContract({
676
+ address: this.validationRegistry,
677
+ abi: ERC8004Validation_1.ERC8004_VALIDATION_ABI,
678
+ functionName: 'validationRequest',
679
+ args: [
680
+ this.identityRegistry,
681
+ BigInt(agentId),
682
+ validatorContract,
683
+ ],
684
+ });
685
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
686
+ this.logger.info(`Validation request sent in block ${receipt.blockNumber}`);
687
+ // Parse requestId from event
688
+ for (const log of receipt.logs) {
689
+ if (log.data && log.data.length > 2) {
690
+ const dataHex = log.data.slice(2);
691
+ if (dataHex.length >= 64) {
692
+ return Number(BigInt('0x' + dataHex.slice(0, 64)));
693
+ }
694
+ }
695
+ }
696
+ return 0;
697
+ }
698
+ catch (error) {
699
+ throw new errors_1.ERC8004RegistryError(this.validationRegistry, 'validationRequest', error instanceof Error ? error.message : String(error));
700
+ }
701
+ }
702
+ /**
703
+ * Get the status of a validation request.
704
+ *
705
+ * @param agentId - The agent's ERC-8004 ID.
706
+ * @param requestId - The validation request ID.
707
+ * @returns The validation result.
708
+ */
709
+ async getValidationStatus(agentId, requestId) {
710
+ this.ensureValidationRegistry();
711
+ try {
712
+ const raw = await this.publicClient.readContract({
713
+ address: this.validationRegistry,
714
+ abi: ERC8004Validation_1.ERC8004_VALIDATION_ABI,
715
+ functionName: 'getValidationStatus',
716
+ args: [this.identityRegistry, BigInt(agentId), BigInt(requestId)],
717
+ });
718
+ return {
719
+ validatorContract: raw.validatorContract,
720
+ requestedAt: Number(raw.requestedAt),
721
+ respondedAt: Number(raw.respondedAt),
722
+ responded: raw.responded,
723
+ passed: raw.passed,
724
+ details: raw.details,
725
+ };
726
+ }
727
+ catch (error) {
728
+ throw new errors_1.ERC8004RegistryError(this.validationRegistry, 'getValidationStatus', error instanceof Error ? error.message : String(error));
729
+ }
730
+ }
731
+ /**
732
+ * Get the validation summary for an agent.
733
+ *
734
+ * @param agentId - The agent's ERC-8004 ID.
735
+ * @returns Validation summary with counts.
736
+ */
737
+ async getValidationSummary(agentId) {
738
+ this.ensureValidationRegistry();
739
+ try {
740
+ const [totalRequests, totalPassed, totalFailed, totalPending] = await this.publicClient.readContract({
741
+ address: this.validationRegistry,
742
+ abi: ERC8004Validation_1.ERC8004_VALIDATION_ABI,
743
+ functionName: 'getSummary',
744
+ args: [this.identityRegistry, BigInt(agentId)],
745
+ });
746
+ return {
747
+ totalRequests: Number(totalRequests),
748
+ totalPassed: Number(totalPassed),
749
+ totalFailed: Number(totalFailed),
750
+ totalPending: Number(totalPending),
751
+ };
752
+ }
753
+ catch (error) {
754
+ throw new errors_1.ERC8004RegistryError(this.validationRegistry, 'getSummary', error instanceof Error ? error.message : String(error));
755
+ }
756
+ }
757
+ // ─────────────────────────────────────────────────────────────
758
+ // Q00BS ↔ ERC-8004 BRIDGE UTILITIES
759
+ // ─────────────────────────────────────────────────────────────
760
+ /**
761
+ * Sync a Q00bs agent's trust score to ERC-8004 metadata.
762
+ *
763
+ * This writes the Q00bs trust score as metadata on the ERC-8004 identity,
764
+ * making it visible to other agent platforms that read ERC-8004.
765
+ *
766
+ * @param erc8004AgentId - The agent's ERC-8004 ID.
767
+ * @param q00bsAgentId - The agent's Q00bs AgentRegistry ID.
768
+ * @param trustScore - The Q00bs trust score (0-10000).
769
+ */
770
+ async syncTrustToMetadata(erc8004AgentId, q00bsAgentId, trustScore) {
771
+ this.ensureWalletClient();
772
+ this.logger.info(`Syncing Q00bs trust to ERC-8004: agent ${erc8004AgentId} ← Q00bs #${q00bsAgentId} (trust: ${trustScore})`);
773
+ // Write Q00bs-specific metadata keys
774
+ await this.setMetadata(erc8004AgentId, 'q00bs_agent_id', String(q00bsAgentId));
775
+ await this.setMetadata(erc8004AgentId, 'q00bs_trust_score', String(trustScore));
776
+ await this.setMetadata(erc8004AgentId, 'q00bs_trust_percent', (trustScore / 100).toFixed(2) + '%');
777
+ this.logger.info(`Trust metadata synced: q00bs_agent_id=${q00bsAgentId}, q00bs_trust_score=${trustScore}`);
778
+ }
779
+ /**
780
+ * Build the full ERC-8004 agent identifier string.
781
+ *
782
+ * Format: {namespace}:{chainId}:{identityRegistry}:{agentId}
783
+ */
784
+ buildIdentifier(agentId) {
785
+ return `${constants_1.ERC8004_NAMESPACE}:${constants_1.BASE_CHAIN_ID}:${this.identityRegistry}:${agentId}`;
786
+ }
787
+ /**
788
+ * Parse an ERC-8004 agent identifier string.
789
+ *
790
+ * @param identifier - The identifier string.
791
+ * @returns Parsed components.
792
+ */
793
+ static parseIdentifier(identifier) {
794
+ const parts = identifier.split(':');
795
+ if (parts.length !== 4) {
796
+ throw new errors_1.ERC8004Error(`Invalid ERC-8004 identifier format: "${identifier}". ` +
797
+ 'Expected: {namespace}:{chainId}:{identityRegistry}:{agentId}');
798
+ }
799
+ return {
800
+ namespace: parts[0],
801
+ chainId: parseInt(parts[1], 10),
802
+ identityRegistry: parts[2],
803
+ agentId: parseInt(parts[3], 10),
804
+ };
805
+ }
806
+ // ─────────────────────────────────────────────────────────────
807
+ // PRIVATE GUARDS
808
+ // ─────────────────────────────────────────────────────────────
809
+ ensureWalletClient() {
810
+ if (!this.walletClient) {
811
+ throw new errors_1.ERC8004Error('Write operations require a walletClient (Mode 1 — privateKey). ' +
812
+ 'In Privy mode (Mode 2), use the API server endpoints for ERC-8004 operations.');
813
+ }
814
+ }
815
+ ensureValidationRegistry() {
816
+ if (this.validationRegistry === '0x0000000000000000000000000000000000000000') {
817
+ throw new errors_1.ERC8004Error('ValidationRegistry is not configured. The ERC-8004 ValidationRegistry ' +
818
+ 'spec is still evolving. Set validationRegistryAddress in ERC8004Config ' +
819
+ 'once the canonical deployment is confirmed.');
820
+ }
821
+ }
822
+ }
823
+ exports.ERC8004Manager = ERC8004Manager;
824
+ //# sourceMappingURL=erc8004.js.map