@aixyz/erc-8004 0.20.0 → 0.22.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aixyz/erc-8004",
3
- "version": "0.20.0",
3
+ "version": "0.22.0",
4
4
  "description": "Payment-native SDK for AI Agent",
5
5
  "keywords": [
6
6
  "ai",
@@ -2,18 +2,17 @@ import { describe, expect, test } from "bun:test";
2
2
  import {
3
3
  ERC8004_REGISTRATION_TYPE,
4
4
  AgentRegistrationFileSchema,
5
- StrictAgentRegistrationFileSchema,
6
5
  TrustMechanismSchema,
7
6
  ServiceSchema,
8
7
  RegistrationEntrySchema,
9
- getServices,
10
- hasX402Support,
11
8
  } from "./registration";
12
9
 
13
10
  const minimalValid = {
11
+ type: ERC8004_REGISTRATION_TYPE,
14
12
  name: "Agently Price Feed",
15
13
  description: "Real-time cryptocurrency price feed agent with x402 payment support",
16
14
  image: "ipfs://QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG",
15
+ services: [{ name: "mcp-server", endpoint: "https://mcp.acme-agents.com/v1/price-feed" }],
17
16
  };
18
17
 
19
18
  const fullValid = {
@@ -170,24 +169,9 @@ describe("RawAgentRegistrationFileSchema", () => {
170
169
  expect(result.did).toBe("did:pkh:eip155:11155111:0x1234567890abcdef1234567890abcdef12345678");
171
170
  });
172
171
 
173
- test("type field is optional", () => {
174
- const result = AgentRegistrationFileSchema.parse(minimalValid);
175
- expect(result.type).toBeUndefined();
176
- });
177
-
178
- test("accepts endpoints as legacy field", () => {
179
- const result = AgentRegistrationFileSchema.parse({
180
- ...minimalValid,
181
- endpoints: [{ name: "legacy-mcp", endpoint: "https://mcp.acme-agents.com/v0/translate" }],
182
- });
183
- expect(result.endpoints).toHaveLength(1);
184
- });
185
-
186
- test("accepts both x402support casings", () => {
187
- const r1 = AgentRegistrationFileSchema.parse({ ...minimalValid, x402support: true });
188
- const r2 = AgentRegistrationFileSchema.parse({ ...minimalValid, x402Support: true });
189
- expect(r1.x402support).toBe(true);
190
- expect(r2.x402Support).toBe(true);
172
+ test("accepts x402support", () => {
173
+ const result = AgentRegistrationFileSchema.parse({ ...minimalValid, x402support: true });
174
+ expect(result.x402support).toBe(true);
191
175
  });
192
176
 
193
177
  test("rejects missing name", () => {
@@ -209,58 +193,6 @@ describe("RawAgentRegistrationFileSchema", () => {
209
193
  });
210
194
  });
211
195
 
212
- describe("StrictAgentRegistrationFileSchema", () => {
213
- const strictValid = {
214
- ...minimalValid,
215
- type: ERC8004_REGISTRATION_TYPE,
216
- services: [{ name: "mcp-server", endpoint: "https://mcp.acme-agents.com/v1/price-feed" }],
217
- };
218
-
219
- test("accepts valid strict file", () => {
220
- const result = StrictAgentRegistrationFileSchema.parse(strictValid);
221
- expect(result.type).toBe(ERC8004_REGISTRATION_TYPE);
222
- expect(result.services).toHaveLength(1);
223
- });
224
-
225
- test("rejects missing type", () => {
226
- expect(() =>
227
- StrictAgentRegistrationFileSchema.parse({
228
- ...minimalValid,
229
- services: [{ name: "mcp-server", endpoint: "https://mcp.acme-agents.com/v1/price-feed" }],
230
- }),
231
- ).toThrow();
232
- });
233
-
234
- test("rejects wrong type literal", () => {
235
- expect(() =>
236
- StrictAgentRegistrationFileSchema.parse({
237
- ...minimalValid,
238
- type: "wrong-type",
239
- services: [{ name: "mcp-server", endpoint: "https://mcp.acme-agents.com/v1/price-feed" }],
240
- }),
241
- ).toThrow();
242
- });
243
-
244
- test("rejects empty services array", () => {
245
- expect(() =>
246
- StrictAgentRegistrationFileSchema.parse({
247
- ...minimalValid,
248
- type: ERC8004_REGISTRATION_TYPE,
249
- services: [],
250
- }),
251
- ).toThrow();
252
- });
253
-
254
- test("rejects missing services", () => {
255
- expect(() =>
256
- StrictAgentRegistrationFileSchema.parse({
257
- ...minimalValid,
258
- type: ERC8004_REGISTRATION_TYPE,
259
- }),
260
- ).toThrow();
261
- });
262
- });
263
-
264
196
  describe("AgentRegistrationFileSchema.safeParse", () => {
265
197
  test("returns success for valid data", () => {
266
198
  const result = AgentRegistrationFileSchema.safeParse(minimalValid);
@@ -277,80 +209,3 @@ describe("AgentRegistrationFileSchema.safeParse", () => {
277
209
  expect(result.success).toBe(false);
278
210
  });
279
211
  });
280
-
281
- describe("StrictAgentRegistrationFileSchema.safeParse", () => {
282
- test("returns success for strict-valid data", () => {
283
- const result = StrictAgentRegistrationFileSchema.safeParse({
284
- ...minimalValid,
285
- type: ERC8004_REGISTRATION_TYPE,
286
- services: [{ name: "mcp-server", endpoint: "https://mcp.acme-agents.com/v1/price-feed" }],
287
- });
288
- expect(result.success).toBe(true);
289
- });
290
-
291
- test("returns failure when type is missing", () => {
292
- const result = StrictAgentRegistrationFileSchema.safeParse({
293
- ...minimalValid,
294
- services: [{ name: "mcp-server", endpoint: "https://mcp.acme-agents.com/v1/price-feed" }],
295
- });
296
- expect(result.success).toBe(false);
297
- });
298
-
299
- test("returns failure when services is empty", () => {
300
- const result = StrictAgentRegistrationFileSchema.safeParse({
301
- ...minimalValid,
302
- type: ERC8004_REGISTRATION_TYPE,
303
- services: [],
304
- });
305
- expect(result.success).toBe(false);
306
- });
307
- });
308
-
309
- describe("getServices", () => {
310
- test("returns services when present", () => {
311
- const file = {
312
- ...minimalValid,
313
- services: [{ name: "mcp-server", endpoint: "https://mcp.acme-agents.com/v1/translate" }],
314
- };
315
- expect(getServices(file)).toEqual([{ name: "mcp-server", endpoint: "https://mcp.acme-agents.com/v1/translate" }]);
316
- });
317
-
318
- test("falls back to endpoints", () => {
319
- const file = {
320
- ...minimalValid,
321
- endpoints: [{ name: "legacy-mcp", endpoint: "https://mcp.acme-agents.com/v0/translate" }],
322
- };
323
- expect(getServices(file)).toEqual([{ name: "legacy-mcp", endpoint: "https://mcp.acme-agents.com/v0/translate" }]);
324
- });
325
-
326
- test("prefers services over endpoints", () => {
327
- const file = {
328
- ...minimalValid,
329
- services: [{ name: "mcp-server", endpoint: "https://mcp.acme-agents.com/v1/translate" }],
330
- endpoints: [{ name: "legacy-mcp", endpoint: "https://mcp.acme-agents.com/v0/translate" }],
331
- };
332
- expect(getServices(file)).toEqual([{ name: "mcp-server", endpoint: "https://mcp.acme-agents.com/v1/translate" }]);
333
- });
334
-
335
- test("returns empty array when neither present", () => {
336
- expect(getServices(minimalValid as any)).toEqual([]);
337
- });
338
- });
339
-
340
- describe("hasX402Support", () => {
341
- test("returns true for x402support: true", () => {
342
- expect(hasX402Support({ ...minimalValid, x402support: true })).toBe(true);
343
- });
344
-
345
- test("returns true for x402Support: true", () => {
346
- expect(hasX402Support({ ...minimalValid, x402Support: true })).toBe(true);
347
- });
348
-
349
- test("returns false when both are false", () => {
350
- expect(hasX402Support({ ...minimalValid, x402support: false, x402Support: false })).toBe(false);
351
- });
352
-
353
- test("returns false when neither is set", () => {
354
- expect(hasX402Support(minimalValid as any)).toBe(false);
355
- });
356
- });
@@ -1,12 +1,5 @@
1
1
  import { z } from "zod";
2
2
 
3
- /**
4
- * ERC-8004 Raw Agent Registration File Schema
5
- * For parsing raw registration files fetched from IPFS/URIs
6
- *
7
- * Based on: https://github.com/erc-8004/erc-8004-contracts/blob/093d7b91eb9c22048d411896ed397d695742a5f8/ERC8004SPEC.md#agent-uri-and-agent-registration-file
8
- */
9
-
10
3
  export const ERC8004_REGISTRATION_TYPE = "https://eips.ethereum.org/EIPS/eip-8004#registration-v1";
11
4
 
12
5
  /**
@@ -50,12 +43,14 @@ export const RegistrationEntrySchema = z.object({
50
43
  });
51
44
 
52
45
  /**
53
- * Raw Agent Registration File Schema
54
- * For parsing registration files fetched from IPFS/URIs
46
+ * ERC-8004 Raw Agent Registration File Schema
47
+ * For parsing raw registration files fetched from IPFS/URIs
48
+ *
49
+ * Based on: https://github.com/erc-8004/erc-8004-contracts/blob/093d7b91eb9c22048d411896ed397d695742a5f8/ERC8004SPEC.md#agent-uri-and-agent-registration-file
55
50
  */
56
51
  export const AgentRegistrationFileSchema = z.object({
57
52
  // Schema identifiers
58
- type: z.string().optional(),
53
+ type: z.literal(ERC8004_REGISTRATION_TYPE),
59
54
  $schema: z.string().optional(),
60
55
 
61
56
  // ERC-721 metadata compatibility (required)
@@ -64,13 +59,11 @@ export const AgentRegistrationFileSchema = z.object({
64
59
  image: z.string(),
65
60
 
66
61
  // Service endpoints
67
- services: z.array(ServiceSchema).optional(),
68
- endpoints: z.array(ServiceSchema).optional(), // Legacy field name
62
+ services: z.array(ServiceSchema).min(1, "at least one service endpoint is required"),
69
63
 
70
64
  // Agent configuration
71
65
  active: z.boolean().optional(),
72
66
  x402support: z.boolean().optional(),
73
- x402Support: z.boolean().optional(), // Alternative casing
74
67
 
75
68
  // Cross-chain & identity
76
69
  registrations: z.array(RegistrationEntrySchema).optional(),
@@ -79,35 +72,7 @@ export const AgentRegistrationFileSchema = z.object({
79
72
  did: z.string().optional(),
80
73
  });
81
74
 
82
- /**
83
- * Strict Schema - for creating new registration files
84
- * Requires correct type literal and at least one service
85
- */
86
- export const StrictAgentRegistrationFileSchema = AgentRegistrationFileSchema.extend({
87
- type: z.literal(ERC8004_REGISTRATION_TYPE),
88
- services: z.array(ServiceSchema).min(1, "At least one service endpoint is required"),
89
- });
90
-
91
75
  export type TrustMechanism = z.infer<typeof TrustMechanismSchema>;
92
76
  export type Service = z.infer<typeof ServiceSchema>;
93
77
  export type RegistrationEntry = z.infer<typeof RegistrationEntrySchema>;
94
78
  export type AgentRegistrationFile = z.infer<typeof AgentRegistrationFileSchema>;
95
- export type StrictAgentRegistrationFile = z.infer<typeof StrictAgentRegistrationFileSchema>;
96
-
97
- /**
98
- * Get services from a registration file
99
- * Handles both `services` (new) and `endpoints` (legacy) field names
100
- * @default TODO: parse and merge both fields
101
- */
102
- export function getServices(file: AgentRegistrationFile | StrictAgentRegistrationFile): Service[] {
103
- return file.services ?? file.endpoints ?? [];
104
- }
105
-
106
- /**
107
- * Check if agent supports x402 payment protocol
108
- * Handles both `x402support` and `x402Support` casing variants
109
- * @deprecated TODO: parse and merge both fields
110
- */
111
- export function hasX402Support(file: AgentRegistrationFile | StrictAgentRegistrationFile): boolean {
112
- return file.x402support === true || file.x402Support === true;
113
- }