agent0-sdk 0.31.0 → 1.0.3

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 (51) hide show
  1. package/README.md +42 -62
  2. package/dist/core/agent.d.ts +32 -2
  3. package/dist/core/agent.d.ts.map +1 -1
  4. package/dist/core/agent.js +246 -25
  5. package/dist/core/agent.js.map +1 -1
  6. package/dist/core/contracts.d.ts +335 -60
  7. package/dist/core/contracts.d.ts.map +1 -1
  8. package/dist/core/contracts.js +174 -59
  9. package/dist/core/contracts.js.map +1 -1
  10. package/dist/core/endpoint-crawler.d.ts +7 -0
  11. package/dist/core/endpoint-crawler.d.ts.map +1 -1
  12. package/dist/core/endpoint-crawler.js +43 -4
  13. package/dist/core/endpoint-crawler.js.map +1 -1
  14. package/dist/core/feedback-manager.d.ts +9 -29
  15. package/dist/core/feedback-manager.d.ts.map +1 -1
  16. package/dist/core/feedback-manager.js +140 -223
  17. package/dist/core/feedback-manager.js.map +1 -1
  18. package/dist/core/indexer.d.ts.map +1 -1
  19. package/dist/core/indexer.js +4 -2
  20. package/dist/core/indexer.js.map +1 -1
  21. package/dist/core/ipfs-client.d.ts +3 -3
  22. package/dist/core/ipfs-client.d.ts.map +1 -1
  23. package/dist/core/ipfs-client.js +31 -14
  24. package/dist/core/ipfs-client.js.map +1 -1
  25. package/dist/core/oasf-validator.js +2 -2
  26. package/dist/core/oasf-validator.js.map +1 -1
  27. package/dist/core/sdk.d.ts +9 -11
  28. package/dist/core/sdk.d.ts.map +1 -1
  29. package/dist/core/sdk.js +37 -37
  30. package/dist/core/sdk.js.map +1 -1
  31. package/dist/core/subgraph-client.d.ts +1 -1
  32. package/dist/core/subgraph-client.d.ts.map +1 -1
  33. package/dist/core/subgraph-client.js +74 -14
  34. package/dist/core/subgraph-client.js.map +1 -1
  35. package/dist/core/web3-client.d.ts +98 -6
  36. package/dist/core/web3-client.d.ts.map +1 -1
  37. package/dist/core/web3-client.js +119 -11
  38. package/dist/core/web3-client.js.map +1 -1
  39. package/dist/models/generated/subgraph-types.d.ts +11 -3
  40. package/dist/models/generated/subgraph-types.d.ts.map +1 -1
  41. package/dist/models/interfaces.d.ts +65 -0
  42. package/dist/models/interfaces.d.ts.map +1 -1
  43. package/dist/taxonomies/generated/all_domains.d.ts +9 -0
  44. package/dist/taxonomies/generated/all_domains.d.ts.map +1 -0
  45. package/dist/taxonomies/generated/all_domains.js +1574 -0
  46. package/dist/taxonomies/generated/all_domains.js.map +1 -0
  47. package/dist/taxonomies/generated/all_skills.d.ts +9 -0
  48. package/dist/taxonomies/generated/all_skills.d.ts.map +1 -0
  49. package/dist/taxonomies/generated/all_skills.js +1039 -0
  50. package/dist/taxonomies/generated/all_skills.js.map +1 -0
  51. package/package.json +8 -5
package/README.md CHANGED
@@ -4,7 +4,7 @@ Agent0 is the TypeScript SDK for agentic economies. It enables agents to registe
4
4
 
5
5
  ## What Does Agent0 SDK Do?
6
6
 
7
- Agent0 SDK v0.31 enables you to:
7
+ Agent0 SDK v1.0.3 enables you to:
8
8
 
9
9
  - **Create and manage agent identities** - Register your AI agent on-chain with a unique identity, configure presentation fields (name, description, image), set wallet addresses, and manage trust models with x402 support
10
10
  - **Advertise agent capabilities** - Publish MCP and A2A endpoints, with automated extraction of MCP tools and A2A skills from endpoints
@@ -14,17 +14,19 @@ Agent0 SDK v0.31 enables you to:
14
14
  - **Cross-chain registration** - One-line registration with IPFS nodes, Pinata, Filecoin, or HTTP URIs
15
15
  - **Public indexing** - Subgraph indexing both on-chain and IPFS data for fast search and retrieval
16
16
 
17
- ## ⚠️ Alpha Release
17
+ ## ⚠️ Beta Release
18
18
 
19
- Agent0 SDK v0.31 is in **alpha** with bugs and is not production ready. We're actively testing and improving it.
19
+ Agent0 SDK v1.0.3 is beta. We're actively testing and improving it.
20
20
 
21
- **Bug reports & feedback:** GitHub: [Report issues](https://github.com/agent0lab/agent0-ts/issues) | Telegram: [@marcoderossi](https://t.me/marcoderossi) | Email: marco.derossi@consensys.net
21
+ For breaking changes and migration notes, see `release_notes/RELEASE_NOTES_1.0.3.md`.
22
+
23
+ **Bug reports & feedback:** GitHub: [Report issues](https://github.com/agent0lab/agent0-ts/issues) | Telegram: [Agent0 channel](https://t.me/agent0kitchen) | Email: team@ag0.xyz
22
24
 
23
25
  ## Installation
24
26
 
25
27
  ### Prerequisites
26
28
 
27
- - Node.js 18 or higher
29
+ - Node.js 22 or higher
28
30
  - npm or yarn package manager
29
31
  - Private key for signing transactions (or run in read-only mode)
30
32
  - Access to an Ethereum RPC endpoint (e.g., Alchemy, Infura)
@@ -51,7 +53,7 @@ npm install
51
53
  npm run build
52
54
  ```
53
55
 
54
- **Note:** The generated TypeScript types are created automatically during `npm install` (via `postinstall` hook) or manually with `npm run codegen`. Always use `npm run build` instead of running `tsc` directly.
56
+ **Note:** The generated TypeScript types are created as part of `npm run build` (or manually with `npm run codegen`). Always use `npm run build` instead of running `tsc` directly.
55
57
 
56
58
  ## Quick Start
57
59
 
@@ -64,7 +66,7 @@ import { SDK } from 'agent0-sdk';
64
66
  const sdk = new SDK({
65
67
  chainId: 11155111, // Ethereum Sepolia testnet
66
68
  rpcUrl: process.env.RPC_URL!,
67
- signer: process.env.PRIVATE_KEY, // Optional: for write operations
69
+ signer: process.env.PRIVATE_KEY ?? process.env.AGENT_PRIVATE_KEY, // Optional: for write operations
68
70
  ipfs: 'pinata', // Options: 'pinata', 'filecoinPin', 'node'
69
71
  pinataJwt: process.env.PINATA_JWT // For Pinata
70
72
  // Subgraph URL auto-defaults from DEFAULT_SUBGRAPH_URLS
@@ -88,12 +90,13 @@ agent.setENS('myagent.eth');
88
90
 
89
91
  // Add OASF skills and domains (standardized taxonomies)
90
92
  agent.addSkill('data_engineering/data_transformation_pipeline', true);
91
- agent.addSkill('natural_language_processing/summarization', true);
93
+ agent.addSkill('natural_language_processing/natural_language_generation/summarization', true);
92
94
  agent.addDomain('finance_and_business/investment_services', true);
93
- agent.addDomain('technology/data_science', true);
95
+ agent.addDomain('technology/data_science/data_science', true);
94
96
 
95
- // Configure wallet and trust
96
- agent.setAgentWallet('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', 11155111);
97
+ // Optionally set a dedicated agent wallet on-chain (requires new wallet signature).
98
+ // If you want agentWallet = owner wallet, you can skip this (contract sets initial value to owner).
99
+ // await agent.setAgentWallet('0x...', { newWalletSigner: process.env.NEW_WALLET_PRIVATE_KEY });
97
100
  agent.setTrust(true, true, false); // reputation, cryptoEconomic, teeAttestation
98
101
 
99
102
  // Add metadata and set status
@@ -174,26 +177,15 @@ const allResults = await sdk.searchAgents({
174
177
 
175
178
  // Search agents by reputation across chains
176
179
  const reputationResults = await sdk.searchAgentsByReputation(
177
- undefined, // agents
178
- undefined, // tags
179
- undefined, // reviewers
180
- undefined, // capabilities
181
- undefined, // skills
182
- undefined, // tasks
183
- undefined, // names
184
- 80, // minAverageScore
185
- false, // includeRevoked
186
- 20, // pageSize
187
- undefined, // cursor
188
- undefined, // sort
189
- [11155111, 84532] // chains
180
+ { minAverageScore: 80 },
181
+ { includeRevoked: false, pageSize: 20, chains: [11155111, 84532] }
190
182
  );
191
183
 
192
184
  // Get agent from specific chain
193
185
  const agent = await sdk.getAgent('84532:123'); // Base Sepolia
194
186
 
195
187
  // Search feedback for agent on specific chain
196
- const feedbacks = await sdk.searchFeedback('84532:123'); // Base Sepolia
188
+ const feedbacks = await sdk.searchFeedback({ agentId: '84532:123' }); // Base Sepolia
197
189
 
198
190
  // Get reputation summary for agent on specific chain
199
191
  const summary = await sdk.getReputationSummary('84532:123'); // Base Sepolia
@@ -202,28 +194,28 @@ const summary = await sdk.getReputationSummary('84532:123'); // Base Sepolia
202
194
  ### 5. Give and Retrieve Feedback
203
195
 
204
196
  ```typescript
205
- // Prepare feedback (only score is mandatory)
206
- const feedbackFile = sdk.prepareFeedback(
197
+ // Optional: prepare an OFF-CHAIN feedback file (only needed for rich fields)
198
+ const feedbackFile = sdk.prepareFeedbackFile({
199
+ capability: 'tools',
200
+ name: 'code_generation',
201
+ skill: 'python',
202
+ context: { sessionId: 'abc' },
203
+ });
204
+
205
+ // Give feedback (on-chain fields are passed directly)
206
+ const feedback = await sdk.giveFeedback(
207
207
  '11155111:123',
208
- 85, // 0-100 (mandatory)
209
- ['data_analyst', 'finance'], // Optional: tags
210
- undefined, // Optional: text
211
- 'tools', // Optional: capability (MCP capability)
212
- 'code_generation', // Optional: name (MCP tool name)
213
- 'python' // Optional: skill (A2A skill)
208
+ 85, // score (0-100)
209
+ 'data_analyst', // tag1 (optional)
210
+ 'finance', // tag2 (optional)
211
+ 'https://api.example.com/feedback', // endpoint (optional on-chain)
212
+ feedbackFile // optional off-chain file
214
213
  );
215
214
 
216
- // Give feedback
217
- const feedback = await sdk.giveFeedback('11155111:123', feedbackFile);
218
-
219
215
  // Search feedback
220
216
  const feedbackResults = await sdk.searchFeedback(
221
- '11155111:123',
222
- undefined, // tags
223
- ['tools'], // capabilities
224
- undefined, // skills
225
- 80, // minScore
226
- 100 // maxScore
217
+ { agentId: '11155111:123', capabilities: ['tools'] },
218
+ { minScore: 80, maxScore: 100 }
227
219
  );
228
220
 
229
221
  // Get reputation summary
@@ -283,8 +275,8 @@ Use `chainId:agentId` format to specify which chain an agent is on:
283
275
  const agent = await sdk.getAgent('84532:1234'); // Base Sepolia
284
276
 
285
277
  // Search feedback for agent on specific chain
286
- const feedbacks = await sdk.searchFeedback('84532:1234'); // Base Sepolia
287
- const feedbacksDefault = await sdk.searchFeedback('1234'); // Uses default chain
278
+ const feedbacks = await sdk.searchFeedback({ agentId: '84532:1234' }); // Base Sepolia
279
+ const feedbacksDefault = await sdk.searchFeedback({ agentId: '11155111:1234' }); // Default chain
288
280
 
289
281
  // Get reputation summary for agent on specific chain
290
282
  const summary = await sdk.getReputationSummary('84532:1234'); // Base Sepolia
@@ -310,26 +302,14 @@ const allChainsResult = await sdk.searchAgents({
310
302
 
311
303
  // Multi-chain reputation search
312
304
  const reputationResult = await sdk.searchAgentsByReputation(
313
- undefined, // agents
314
- undefined, // tags
315
- undefined, // reviewers
316
- undefined, // capabilities
317
- undefined, // skills
318
- undefined, // tasks
319
- undefined, // names
320
- 80, // minAverageScore
321
- false, // includeRevoked
322
- 20, // pageSize
323
- undefined, // cursor
324
- undefined, // sort
325
- [11155111, 84532] // Multiple chains
305
+ { minAverageScore: 80 },
306
+ { includeRevoked: false, pageSize: 20, chains: [11155111, 84532] }
326
307
  );
327
308
 
328
309
  // Search all chains for agents with reputation
329
310
  const allChainsReputation = await sdk.searchAgentsByReputation(
330
- undefined, undefined, undefined, undefined, undefined, undefined, undefined,
331
- 80, false, 20, undefined, undefined,
332
- 'all' // All configured chains
311
+ { minAverageScore: 80 },
312
+ { includeRevoked: false, pageSize: 20, chains: 'all' }
333
313
  );
334
314
 
335
315
  // Access metadata about queried chains
@@ -396,7 +376,7 @@ OASF skills and domains appear in your agent's registration file:
396
376
  ],
397
377
  "domains": [
398
378
  "finance_and_business/investment_services",
399
- "technology/data_science"
379
+ "technology/data_science/data_science"
400
380
  ]
401
381
  }
402
382
  ]
@@ -409,7 +389,7 @@ The SDK includes complete OASF v0.8.0 taxonomy files:
409
389
  - **Skills**: `src/taxonomies/all_skills.json` (136 skills)
410
390
  - **Domains**: `src/taxonomies/all_domains.json` (204 domains)
411
391
 
412
- Browse these files to find appropriate skill and domain slugs. For more information, see the [OASF specification](https://github.com/agntcy/oasf) and [Release Notes v0.31](RELEASE_NOTES_0.31.md).
392
+ Browse these files to find appropriate skill and domain slugs. For more information, see the [OASF specification](https://github.com/agntcy/oasf) and `release_notes/RELEASE_NOTES_0.31.md`.
413
393
 
414
394
  ## 🚀 Coming Soon
415
395
 
@@ -1,8 +1,10 @@
1
1
  /**
2
2
  * Agent class for managing individual agents
3
3
  */
4
+ import { ethers } from 'ethers';
4
5
  import type { RegistrationFile } from '../models/interfaces.js';
5
6
  import type { AgentId, Address, URI } from '../models/types.js';
7
+ import { EndpointType } from '../models/enums.js';
6
8
  import type { SDK } from './sdk.js';
7
9
  /**
8
10
  * Agent class for managing individual agents
@@ -31,12 +33,40 @@ export declare class Agent {
31
33
  setMCP(endpoint: string, version?: string, autoFetch?: boolean): Promise<this>;
32
34
  setA2A(agentcard: string, version?: string, autoFetch?: boolean): Promise<this>;
33
35
  setENS(name: string, version?: string): this;
36
+ /**
37
+ * Remove endpoint(s) with wildcard semantics (parity with Python SDK).
38
+ *
39
+ * - If no args are provided, removes all endpoints.
40
+ * - If only `type` is provided, removes all endpoints of that type.
41
+ * - If only `value` is provided, removes all endpoints with that value.
42
+ * - If both are provided, removes endpoints that match both.
43
+ */
44
+ removeEndpoint(): this;
45
+ removeEndpoint(opts: {
46
+ type?: EndpointType;
47
+ value?: string;
48
+ }): this;
49
+ removeEndpoint(type?: EndpointType, value?: string): this;
50
+ /**
51
+ * Remove all endpoints.
52
+ */
53
+ removeEndpoints(): this;
34
54
  private _getOrCreateOasfEndpoint;
35
55
  addSkill(slug: string, validateOASF?: boolean): this;
36
56
  removeSkill(slug: string): this;
37
57
  addDomain(slug: string, validateOASF?: boolean): this;
38
58
  removeDomain(slug: string): this;
39
- setAgentWallet(address: Address, chainId: number): this;
59
+ /**
60
+ * Set agent wallet on-chain with EIP-712 signature verification (ERC-8004 Jan 2026).
61
+ *
62
+ * This is a clean breaking API: it is on-chain only.
63
+ * If the agent is not registered yet, this throws.
64
+ */
65
+ setAgentWallet(newWallet: Address, opts?: {
66
+ deadline?: number;
67
+ newWalletSigner?: string | ethers.Signer;
68
+ signature?: string | Uint8Array;
69
+ }): Promise<string>;
40
70
  setActive(active: boolean): this;
41
71
  setX402Support(x402Support: boolean): this;
42
72
  setTrust(reputation?: boolean, cryptoEconomic?: boolean, teeAttestation?: boolean): this;
@@ -59,7 +89,7 @@ export declare class Agent {
59
89
  /**
60
90
  * Set agent URI (for updates)
61
91
  */
62
- setAgentUri(agentUri: string): Promise<void>;
92
+ setAgentURI(agentURI: string): Promise<void>;
63
93
  /**
64
94
  * Transfer agent ownership
65
95
  */
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"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"}
@@ -139,6 +139,31 @@ export class Agent {
139
139
  this.registrationFile.updatedAt = Math.floor(Date.now() / 1000);
140
140
  return this;
141
141
  }
142
+ removeEndpoint(arg1, arg2) {
143
+ const { type, value } = arg1 && typeof arg1 === 'object'
144
+ ? { type: arg1.type, value: arg1.value }
145
+ : { type: arg1, value: arg2 };
146
+ if (type === undefined && value === undefined) {
147
+ // Remove all endpoints
148
+ this.registrationFile.endpoints = [];
149
+ }
150
+ else {
151
+ // Remove matching endpoints (wildcard semantics)
152
+ this.registrationFile.endpoints = this.registrationFile.endpoints.filter((ep) => {
153
+ const typeMatches = type === undefined || ep.type === type;
154
+ const valueMatches = value === undefined || ep.value === value;
155
+ return !(typeMatches && valueMatches);
156
+ });
157
+ }
158
+ this.registrationFile.updatedAt = Math.floor(Date.now() / 1000);
159
+ return this;
160
+ }
161
+ /**
162
+ * Remove all endpoints.
163
+ */
164
+ removeEndpoints() {
165
+ return this.removeEndpoint();
166
+ }
142
167
  // OASF endpoint management
143
168
  _getOrCreateOasfEndpoint() {
144
169
  // Find existing OASF endpoint
@@ -255,15 +280,212 @@ export class Agent {
255
280
  }
256
281
  return this;
257
282
  }
258
- setAgentWallet(address, chainId) {
259
- this.registrationFile.walletAddress = address;
260
- this.registrationFile.walletChainId = chainId;
261
- // Check if wallet changed
262
- if (address !== this._lastRegisteredWallet) {
263
- this._dirtyMetadata.add('agentWallet');
283
+ /**
284
+ * Set agent wallet on-chain with EIP-712 signature verification (ERC-8004 Jan 2026).
285
+ *
286
+ * This is a clean breaking API: it is on-chain only.
287
+ * If the agent is not registered yet, this throws.
288
+ */
289
+ async setAgentWallet(newWallet, opts) {
290
+ if (!this.registrationFile.agentId) {
291
+ throw new Error('Agent must be registered before setting agentWallet on-chain. ' +
292
+ 'Register the agent first, then call setAgentWallet().');
293
+ }
294
+ if (!this.sdk.web3Client.signer) {
295
+ throw new Error('No SDK signer available to submit setAgentWallet transaction');
296
+ }
297
+ // Validate newWallet address
298
+ if (!this.sdk.web3Client.isAddress(newWallet)) {
299
+ throw new Error(`Invalid newWallet address: ${newWallet}`);
300
+ }
301
+ const { tokenId } = parseAgentId(this.registrationFile.agentId);
302
+ const identityRegistry = this.sdk.getIdentityRegistry();
303
+ // Optional short-circuit if already set
304
+ try {
305
+ const currentWallet = await this.sdk.web3Client.callContract(identityRegistry, 'getAgentWallet', BigInt(tokenId));
306
+ if (typeof currentWallet === 'string' &&
307
+ currentWallet.toLowerCase() === newWallet.toLowerCase()) {
308
+ const chainId = await this.sdk.chainId();
309
+ this.registrationFile.walletAddress = newWallet;
310
+ this.registrationFile.walletChainId = chainId;
311
+ this.registrationFile.updatedAt = Math.floor(Date.now() / 1000);
312
+ return '';
313
+ }
314
+ }
315
+ catch {
316
+ // ignore and proceed
317
+ }
318
+ // Deadline: contract enforces a short window. Use chain time (latest block timestamp)
319
+ // rather than local system time to avoid clock skew causing reverts.
320
+ const latestBlock = await this.sdk.web3Client.provider.getBlock('latest');
321
+ const chainNow = latestBlock?.timestamp ?? Math.floor(Date.now() / 1000);
322
+ const deadlineValue = opts?.deadline ?? chainNow + 60;
323
+ if (deadlineValue < chainNow) {
324
+ throw new Error(`Invalid deadline: ${deadlineValue} is in the past (chain time: ${chainNow})`);
325
+ }
326
+ if (deadlineValue > chainNow + 300) {
327
+ throw new Error(`Invalid deadline: ${deadlineValue} is too far in the future. ` +
328
+ `ERC-8004 setAgentWallet requires a short deadline (<= chainTime + 300s). ` +
329
+ `(chain time: ${chainNow})`);
330
+ }
331
+ const chainId = await this.sdk.chainId();
332
+ const verifyingContract = await identityRegistry.getAddress();
333
+ const owner = await this.sdk.web3Client.callContract(identityRegistry, 'ownerOf', BigInt(tokenId));
334
+ // Prefer reading the actual EIP-712 domain from the contract (if supported)
335
+ // to avoid any future divergence in name/version.
336
+ let domainName;
337
+ let domainVersion;
338
+ try {
339
+ const domainInfo = await this.sdk.web3Client.callContract(identityRegistry, 'eip712Domain');
340
+ // eip712Domain() returns: (fields, name, version, chainId, verifyingContract, salt, extensions)
341
+ // In ethers v6 this is typically a Result array-like object.
342
+ domainName = domainInfo?.name ?? domainInfo?.[1];
343
+ domainVersion = domainInfo?.version ?? domainInfo?.[2];
344
+ }
345
+ catch {
346
+ // ignore and use defaults
347
+ }
348
+ // If the contract exposes a domain separator, try to select a matching (name, version)
349
+ // deterministically from common candidates.
350
+ let domainSeparatorOnChain;
351
+ try {
352
+ domainSeparatorOnChain = await this.sdk.web3Client.callContract(identityRegistry, 'DOMAIN_SEPARATOR');
353
+ }
354
+ catch {
355
+ // ignore
356
+ }
357
+ // Preflight estimateGas to catch signature/domain/type mismatches early.
358
+ const estimateSetAgentWallet = async (sig) => {
359
+ const fn = identityRegistry.getFunction
360
+ ? identityRegistry.getFunction('setAgentWallet')
361
+ : null;
362
+ if (fn?.estimateGas) {
363
+ await fn.estimateGas(BigInt(tokenId), newWallet, BigInt(deadlineValue), sig);
364
+ }
365
+ else if (identityRegistry.estimateGas?.setAgentWallet) {
366
+ await identityRegistry.estimateGas.setAgentWallet(BigInt(tokenId), newWallet, BigInt(deadlineValue), sig);
367
+ }
368
+ };
369
+ // Determine signature
370
+ let signature;
371
+ if (opts?.signature) {
372
+ signature =
373
+ typeof opts.signature === 'string' ? opts.signature : ethers.hexlify(opts.signature);
374
+ if (!signature.startsWith('0x')) {
375
+ signature = `0x${signature}`;
376
+ }
264
377
  }
378
+ else {
379
+ // The new wallet MUST sign (EOA path). Support a few domain/type variants to match deployed registries.
380
+ const signerForNewWallet = opts?.newWalletSigner;
381
+ const sdkSignerAddress = await this.sdk.web3Client.getAddress();
382
+ // If no explicit signer was provided, allow the one-wallet case (SDK signer == newWallet)
383
+ if (!signerForNewWallet) {
384
+ if (!sdkSignerAddress || sdkSignerAddress.toLowerCase() !== newWallet.toLowerCase()) {
385
+ throw new Error(`The new wallet must sign the EIP-712 message. ` +
386
+ `Pass opts.newWalletSigner (private key or Signer) or opts.signature. ` +
387
+ `SDK signer is ${sdkSignerAddress || 'unknown'}, newWallet is ${newWallet}.`);
388
+ }
389
+ }
390
+ else {
391
+ const signerAddress = await this.sdk.web3Client.addressOf(signerForNewWallet);
392
+ if (signerAddress.toLowerCase() !== newWallet.toLowerCase()) {
393
+ throw new Error(`newWalletSigner address (${signerAddress}) does not match newWallet (${newWallet}).`);
394
+ }
395
+ }
396
+ const domainNames = [];
397
+ if (domainName)
398
+ domainNames.push(domainName);
399
+ // Common known names across deployments/spec revisions
400
+ domainNames.push('ERC8004IdentityRegistry', 'IdentityRegistry', 'ERC8004IdentityRegistryUpgradeable', 'IdentityRegistryUpgradeable');
401
+ const domainVersions = [domainVersion || '1', '1'];
402
+ // If we have a domain separator, prefer the (name, version) that matches it.
403
+ if (domainSeparatorOnChain) {
404
+ const match = domainNames.flatMap((dn) => domainVersions.map((dv) => ({ dn, dv }))).find(({ dn, dv }) => {
405
+ try {
406
+ const computed = ethers.TypedDataEncoder.hashDomain({
407
+ name: dn,
408
+ version: dv,
409
+ chainId,
410
+ verifyingContract,
411
+ });
412
+ return computed.toLowerCase() === String(domainSeparatorOnChain).toLowerCase();
413
+ }
414
+ catch {
415
+ return false;
416
+ }
417
+ });
418
+ if (match) {
419
+ domainNames.unshift(match.dn);
420
+ domainVersions.unshift(match.dv);
421
+ }
422
+ }
423
+ // Try (with owner) first, then (no owner) legacy; and try each domain name.
424
+ const variants = [];
425
+ for (const dn of domainNames) {
426
+ for (const dv of domainVersions) {
427
+ variants.push(this.sdk.web3Client.buildAgentWalletSetTypedData({
428
+ agentId: BigInt(tokenId),
429
+ newWallet,
430
+ owner,
431
+ deadline: BigInt(deadlineValue),
432
+ chainId,
433
+ verifyingContract,
434
+ domainName: dn,
435
+ domainVersion: dv,
436
+ }));
437
+ variants.push(this.sdk.web3Client.buildAgentWalletSetTypedDataNoOwner({
438
+ agentId: BigInt(tokenId),
439
+ newWallet,
440
+ deadline: BigInt(deadlineValue),
441
+ chainId,
442
+ verifyingContract,
443
+ domainName: dn,
444
+ domainVersion: dv,
445
+ }));
446
+ }
447
+ }
448
+ let lastError;
449
+ const trySignAndEstimate = async (signerMode) => {
450
+ for (const v of variants) {
451
+ try {
452
+ const sig = signerMode === 'newWallet'
453
+ ? signerForNewWallet
454
+ ? await this.sdk.web3Client.signTypedDataWith(signerForNewWallet, v.domain, v.types, v.message)
455
+ : await this.sdk.web3Client.signTypedData(v.domain, v.types, v.message)
456
+ : await this.sdk.web3Client.signTypedData(v.domain, v.types, v.message);
457
+ const recovered = this.sdk.web3Client.recoverTypedDataSigner(v.domain, v.types, v.message, sig);
458
+ const expected = signerMode === 'newWallet' ? newWallet.toLowerCase() : (sdkSignerAddress || '').toLowerCase();
459
+ if (!expected || recovered.toLowerCase() !== expected) {
460
+ throw new Error(`EIP-712 signature recovery mismatch (${signerMode} signing): recovered ${recovered} but expected ${expected || 'unknown'}`);
461
+ }
462
+ await estimateSetAgentWallet(sig);
463
+ signature = sig;
464
+ return;
465
+ }
466
+ catch (e) {
467
+ lastError = e;
468
+ }
469
+ }
470
+ };
471
+ // Preferred: newWallet signs (spec-aligned)
472
+ await trySignAndEstimate('newWallet');
473
+ // Fallback: some legacy deployments may require the agent owner (tx sender) to sign instead.
474
+ if (!signature && sdkSignerAddress) {
475
+ await trySignAndEstimate('owner');
476
+ }
477
+ if (!signature) {
478
+ const msg = lastError instanceof Error ? lastError.message : String(lastError);
479
+ throw new Error(`Failed to produce a valid setAgentWallet signature for this registry: ${msg}`);
480
+ }
481
+ }
482
+ // Call contract function (tx sender is SDK signer: owner/operator)
483
+ const txHash = await this.sdk.web3Client.transactContract(identityRegistry, 'setAgentWallet', {}, BigInt(tokenId), newWallet, BigInt(deadlineValue), signature);
484
+ // Update local registration file
485
+ this.registrationFile.walletAddress = newWallet;
486
+ this.registrationFile.walletChainId = chainId;
265
487
  this.registrationFile.updatedAt = Math.floor(Date.now() / 1000);
266
- return this;
488
+ return txHash;
267
489
  }
268
490
  setActive(active) {
269
491
  this.registrationFile.active = active;
@@ -352,13 +574,13 @@ export class Agent {
352
574
  }
353
575
  // Update agent URI on-chain
354
576
  const { tokenId } = parseAgentId(this.registrationFile.agentId);
355
- const txHash = await this.sdk.web3Client.transactContract(this.sdk.getIdentityRegistry(), 'setAgentUri', {}, BigInt(tokenId), `ipfs://${ipfsCid}`);
577
+ const txHash = await this.sdk.web3Client.transactContract(this.sdk.getIdentityRegistry(), 'setAgentURI', {}, BigInt(tokenId), `ipfs://${ipfsCid}`);
356
578
  // Wait for transaction to be confirmed (30 second timeout like Python)
357
579
  // If timeout, continue - transaction was sent and will eventually confirm
358
580
  try {
359
581
  await this.sdk.web3Client.waitForTransaction(txHash, TIMEOUTS.TRANSACTION_WAIT);
360
582
  }
361
- catch (error) {
583
+ catch {
362
584
  // Transaction was sent and will eventually confirm - continue silently
363
585
  }
364
586
  // Clear dirty flags
@@ -378,7 +600,7 @@ export class Agent {
378
600
  const ipfsCid = await this.sdk.ipfsClient.addRegistrationFile(this.registrationFile, chainId, identityRegistryAddress);
379
601
  // Step 3: Set agent URI on-chain
380
602
  const { tokenId } = parseAgentId(this.registrationFile.agentId);
381
- const txHash = await this.sdk.web3Client.transactContract(this.sdk.getIdentityRegistry(), 'setAgentUri', {}, BigInt(tokenId), `ipfs://${ipfsCid}`);
603
+ const txHash = await this.sdk.web3Client.transactContract(this.sdk.getIdentityRegistry(), 'setAgentURI', {}, BigInt(tokenId), `ipfs://${ipfsCid}`);
382
604
  // Wait for transaction to be confirmed
383
605
  await this.sdk.web3Client.waitForTransaction(txHash);
384
606
  // Clear dirty flags
@@ -399,7 +621,7 @@ export class Agent {
399
621
  }
400
622
  if (this.registrationFile.agentId) {
401
623
  // Agent already registered - update agent URI
402
- await this.setAgentUri(agentUri);
624
+ await this.setAgentURI(agentUri);
403
625
  return this.registrationFile;
404
626
  }
405
627
  else {
@@ -410,13 +632,13 @@ export class Agent {
410
632
  /**
411
633
  * Set agent URI (for updates)
412
634
  */
413
- async setAgentUri(agentUri) {
635
+ async setAgentURI(agentURI) {
414
636
  if (!this.registrationFile.agentId) {
415
637
  throw new Error('Agent must be registered before setting URI');
416
638
  }
417
639
  const { tokenId } = parseAgentId(this.registrationFile.agentId);
418
- await this.sdk.web3Client.transactContract(this.sdk.getIdentityRegistry(), 'setAgentUri', {}, BigInt(tokenId), agentUri);
419
- this.registrationFile.agentURI = agentUri;
640
+ await this.sdk.web3Client.transactContract(this.sdk.getIdentityRegistry(), 'setAgentURI', {}, BigInt(tokenId), agentURI);
641
+ this.registrationFile.agentURI = agentURI;
420
642
  this.registrationFile.updatedAt = Math.floor(Date.now() / 1000);
421
643
  }
422
644
  /**
@@ -509,8 +731,8 @@ export class Agent {
509
731
  // Update metadata one by one (like Python SDK)
510
732
  // Only send transactions for dirty (changed) metadata keys
511
733
  for (const entry of metadataEntries) {
512
- if (this._dirtyMetadata.has(entry.key)) {
513
- const txHash = await this.sdk.web3Client.transactContract(identityRegistry, 'setMetadata', {}, BigInt(tokenId), entry.key, entry.value);
734
+ if (this._dirtyMetadata.has(entry.metadataKey)) {
735
+ const txHash = await this.sdk.web3Client.transactContract(identityRegistry, 'setMetadata', {}, BigInt(tokenId), entry.metadataKey, entry.metadataValue);
514
736
  // Wait with 30 second timeout (like Python SDK)
515
737
  // If timeout, log warning but continue - transaction was sent and will eventually confirm
516
738
  try {
@@ -524,16 +746,15 @@ export class Agent {
524
746
  }
525
747
  _collectMetadataForRegistration() {
526
748
  const entries = [];
527
- // Collect wallet address if set
528
- if (this.registrationFile.walletAddress && this.registrationFile.walletChainId) {
529
- const walletValue = `eip155:${this.registrationFile.walletChainId}:${this.registrationFile.walletAddress}`;
530
- entries.push({
531
- key: 'agentWallet',
532
- value: new TextEncoder().encode(walletValue),
533
- });
534
- }
749
+ // Note: agentWallet is now a reserved metadata key that cannot be set via setMetadata()
750
+ // It must be set using setAgentWallet() with EIP-712 signature verification
751
+ // We do not include it in metadata entries here
535
752
  // Collect custom metadata
536
753
  for (const [key, value] of Object.entries(this.registrationFile.metadata)) {
754
+ // Skip agentWallet if it somehow got into metadata
755
+ if (key === 'agentWallet') {
756
+ continue;
757
+ }
537
758
  let valueBytes;
538
759
  if (typeof value === 'string') {
539
760
  valueBytes = new TextEncoder().encode(value);
@@ -544,7 +765,7 @@ export class Agent {
544
765
  else {
545
766
  valueBytes = new TextEncoder().encode(JSON.stringify(value));
546
767
  }
547
- entries.push({ key, value: valueBytes });
768
+ entries.push({ metadataKey: key, metadataValue: valueBytes });
548
769
  }
549
770
  return entries;
550
771
  }