agent0-sdk 0.31.0 → 1.0.2
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.
- package/README.md +40 -60
- package/dist/core/agent.d.ts +32 -2
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +246 -25
- package/dist/core/agent.js.map +1 -1
- package/dist/core/contracts.d.ts +335 -60
- package/dist/core/contracts.d.ts.map +1 -1
- package/dist/core/contracts.js +174 -59
- package/dist/core/contracts.js.map +1 -1
- package/dist/core/endpoint-crawler.d.ts +7 -0
- package/dist/core/endpoint-crawler.d.ts.map +1 -1
- package/dist/core/endpoint-crawler.js +43 -4
- package/dist/core/endpoint-crawler.js.map +1 -1
- package/dist/core/feedback-manager.d.ts +9 -29
- package/dist/core/feedback-manager.d.ts.map +1 -1
- package/dist/core/feedback-manager.js +140 -223
- package/dist/core/feedback-manager.js.map +1 -1
- package/dist/core/indexer.d.ts.map +1 -1
- package/dist/core/indexer.js +4 -2
- package/dist/core/indexer.js.map +1 -1
- package/dist/core/ipfs-client.d.ts +3 -3
- package/dist/core/ipfs-client.d.ts.map +1 -1
- package/dist/core/ipfs-client.js +31 -14
- package/dist/core/ipfs-client.js.map +1 -1
- package/dist/core/oasf-validator.js +2 -2
- package/dist/core/oasf-validator.js.map +1 -1
- package/dist/core/sdk.d.ts +9 -11
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +37 -37
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/subgraph-client.d.ts +1 -1
- package/dist/core/subgraph-client.d.ts.map +1 -1
- package/dist/core/subgraph-client.js +74 -14
- package/dist/core/subgraph-client.js.map +1 -1
- package/dist/core/web3-client.d.ts +98 -6
- package/dist/core/web3-client.d.ts.map +1 -1
- package/dist/core/web3-client.js +119 -11
- package/dist/core/web3-client.js.map +1 -1
- package/dist/models/generated/subgraph-types.d.ts +11 -3
- package/dist/models/generated/subgraph-types.d.ts.map +1 -1
- package/dist/models/interfaces.d.ts +65 -0
- package/dist/models/interfaces.d.ts.map +1 -1
- package/dist/taxonomies/generated/all_domains.d.ts +9 -0
- package/dist/taxonomies/generated/all_domains.d.ts.map +1 -0
- package/dist/taxonomies/{all_domains.json → generated/all_domains.js} +11 -2
- package/dist/taxonomies/generated/all_domains.js.map +1 -0
- package/dist/taxonomies/generated/all_skills.d.ts +9 -0
- package/dist/taxonomies/generated/all_skills.d.ts.map +1 -0
- package/dist/taxonomies/{all_skills.json → generated/all_skills.js} +11 -2
- package/dist/taxonomies/generated/all_skills.js.map +1 -0
- package/package.json +7 -4
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
|
|
7
|
+
Agent0 SDK v1.0.2 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
|
|
@@ -16,15 +16,17 @@ Agent0 SDK v0.31 enables you to:
|
|
|
16
16
|
|
|
17
17
|
## ⚠️ Alpha Release
|
|
18
18
|
|
|
19
|
-
Agent0 SDK
|
|
19
|
+
Agent0 SDK v1.0.2 is in **alpha** with bugs and is not production ready. We're actively testing and improving it.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
For breaking changes and migration notes, see `release_notes/RELEASE_NOTES_1.0.2.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
|
|
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)
|
|
@@ -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
|
-
//
|
|
96
|
-
|
|
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
|
-
|
|
178
|
-
|
|
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
|
-
//
|
|
206
|
-
const feedbackFile = sdk.
|
|
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
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
'
|
|
212
|
-
|
|
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
|
-
|
|
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'); //
|
|
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
|
-
|
|
314
|
-
|
|
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
|
-
|
|
331
|
-
|
|
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
|
|
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
|
|
package/dist/core/agent.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
92
|
+
setAgentURI(agentURI: string): Promise<void>;
|
|
63
93
|
/**
|
|
64
94
|
* Transfer agent ownership
|
|
65
95
|
*/
|
package/dist/core/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/core/agent.js
CHANGED
|
@@ -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
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
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
|
|
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(), '
|
|
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
|
|
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(), '
|
|
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.
|
|
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
|
|
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(), '
|
|
419
|
-
this.registrationFile.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.
|
|
513
|
-
const txHash = await this.sdk.web3Client.transactContract(identityRegistry, 'setMetadata', {}, BigInt(tokenId), entry.
|
|
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
|
-
//
|
|
528
|
-
|
|
529
|
-
|
|
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,
|
|
768
|
+
entries.push({ metadataKey: key, metadataValue: valueBytes });
|
|
548
769
|
}
|
|
549
770
|
return entries;
|
|
550
771
|
}
|