@aixyz/erc-8004 0.8.0 → 0.9.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/README.md CHANGED
@@ -87,26 +87,43 @@ import { ValidationRegistryUpgradeable } from "@aixyz/erc-8004/contracts/Validat
87
87
 
88
88
  **Mainnets:**
89
89
 
90
- | Chain | Chain ID | Constant |
91
- | ------- | -------- | ------------------ |
92
- | Mainnet | `1` | `CHAIN_ID.MAINNET` |
93
- | Base | `8453` | `CHAIN_ID.BASE` |
94
- | Polygon | `137` | `CHAIN_ID.POLYGON` |
95
- | Scroll | `534352` | `CHAIN_ID.SCROLL` |
96
- | Monad | `143` | `CHAIN_ID.MONAD` |
97
- | BSC | `56` | `CHAIN_ID.BSC` |
98
- | Gnosis | `100` | `CHAIN_ID.GNOSIS` |
90
+ | Chain | Chain ID | Constant |
91
+ | --------- | -------- | -------------------- |
92
+ | Abstract | `2741` | `CHAIN_ID.ABSTRACT` |
93
+ | Arbitrum | `42161` | `CHAIN_ID.ARBITRUM` |
94
+ | Avalanche | `43114` | `CHAIN_ID.AVALANCHE` |
95
+ | Base | `8453` | `CHAIN_ID.BASE` |
96
+ | BSC | `56` | `CHAIN_ID.BSC` |
97
+ | Celo | `42220` | `CHAIN_ID.CELO` |
98
+ | Gnosis | `100` | `CHAIN_ID.GNOSIS` |
99
+ | Linea | `59144` | `CHAIN_ID.LINEA` |
100
+ | Mainnet | `1` | `CHAIN_ID.MAINNET` |
101
+ | Mantle | `5000` | `CHAIN_ID.MANTLE` |
102
+ | MegaETH | `4326` | `CHAIN_ID.MEGAETH` |
103
+ | Monad | `143` | `CHAIN_ID.MONAD` |
104
+ | Optimism | `10` | `CHAIN_ID.OPTIMISM` |
105
+ | Polygon | `137` | `CHAIN_ID.POLYGON` |
106
+ | Scroll | `534352` | `CHAIN_ID.SCROLL` |
107
+ | Taiko | `167000` | `CHAIN_ID.TAIKO` |
99
108
 
100
109
  **Testnets:**
101
110
 
102
- | Chain | Chain ID | Constant |
103
- | -------------- | ---------- | ------------------------- |
104
- | Sepolia | `11155111` | `CHAIN_ID.SEPOLIA` |
105
- | Base Sepolia | `84532` | `CHAIN_ID.BASE_SEPOLIA` |
106
- | Polygon Amoy | `80002` | `CHAIN_ID.POLYGON_AMOY` |
107
- | Scroll Sepolia | `534351` | `CHAIN_ID.SCROLL_SEPOLIA` |
108
- | Monad Testnet | `10143` | `CHAIN_ID.MONAD_TESTNET` |
109
- | BSC Testnet | `97` | `CHAIN_ID.BSC_TESTNET` |
111
+ | Chain | Chain ID | Constant |
112
+ | ---------------- | ---------- | --------------------------- |
113
+ | Abstract Testnet | `11124` | `CHAIN_ID.ABSTRACT_TESTNET` |
114
+ | Arbitrum Sepolia | `421614` | `CHAIN_ID.ARBITRUM_SEPOLIA` |
115
+ | Avalanche Fuji | `43113` | `CHAIN_ID.AVALANCHE_FUJI` |
116
+ | Base Sepolia | `84532` | `CHAIN_ID.BASE_SEPOLIA` |
117
+ | BSC Testnet | `97` | `CHAIN_ID.BSC_TESTNET` |
118
+ | Celo Sepolia | `11142220` | `CHAIN_ID.CELO_SEPOLIA` |
119
+ | Linea Sepolia | `59141` | `CHAIN_ID.LINEA_SEPOLIA` |
120
+ | Mantle Sepolia | `5003` | `CHAIN_ID.MANTLE_SEPOLIA` |
121
+ | MegaETH Testnet | `6342` | `CHAIN_ID.MEGAETH_TESTNET` |
122
+ | Monad Testnet | `10143` | `CHAIN_ID.MONAD_TESTNET` |
123
+ | Optimism Sepolia | `11155420` | `CHAIN_ID.OPTIMISM_SEPOLIA` |
124
+ | Polygon Amoy | `80002` | `CHAIN_ID.POLYGON_AMOY` |
125
+ | Scroll Sepolia | `534351` | `CHAIN_ID.SCROLL_SEPOLIA` |
126
+ | Sepolia | `11155111` | `CHAIN_ID.SEPOLIA` |
110
127
 
111
128
  ## ABIs
112
129
 
@@ -122,7 +139,7 @@ Versioned ABIs (e.g. `IdentityRegistryAbi_V1`, `ReputationRegistryAbi_V3`) are a
122
139
 
123
140
  All contracts use UUPS proxies. Addresses are consistent across all chains within each environment.
124
141
 
125
- **Mainnets** (Ethereum, Base, Polygon, Scroll, Monad, BSC, Gnosis):
142
+ **Mainnets** (Abstract, Arbitrum, Avalanche, Base, BSC, Celo, Gnosis, Linea, Ethereum, Mantle, MegaETH, Monad, Optimism, Polygon, Scroll, Taiko):
126
143
 
127
144
  | Contract | Address |
128
145
  | -------------------- | -------------------------------------------- |
@@ -130,7 +147,7 @@ All contracts use UUPS proxies. Addresses are consistent across all chains withi
130
147
  | `reputationRegistry` | `0x8004BAa17C55a88189AE136b182e5fdA19dE9b63` |
131
148
  | `validationRegistry` | `0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58` |
132
149
 
133
- **Testnets** (Sepolia, Base Sepolia, Polygon Amoy, Scroll Sepolia, Monad Testnet, BSC Testnet):
150
+ **Testnets** (Abstract Testnet, Arbitrum Sepolia, Avalanche Fuji, Base Sepolia, BSC Testnet, Celo Sepolia, Linea Sepolia, Mantle Sepolia, MegaETH Testnet, Monad Testnet, Optimism Sepolia, Polygon Amoy, Scroll Sepolia, Sepolia):
134
151
 
135
152
  | Contract | Address |
136
153
  | -------------------- | -------------------------------------------- |
package/index.ts CHANGED
@@ -28,20 +28,37 @@ export { ValidationRegistryAbi_V1 as ValidationRegistryAbi } from "./abis/Valida
28
28
  // Chain ID constants
29
29
  export const CHAIN_ID = {
30
30
  // Mainnets
31
- MAINNET: 1,
31
+ ABSTRACT: 2741,
32
+ ARBITRUM: 42161,
33
+ AVALANCHE: 43114,
32
34
  BASE: 8453,
33
- POLYGON: 137,
34
- SCROLL: 534352,
35
- MONAD: 143,
36
35
  BSC: 56,
36
+ CELO: 42220,
37
37
  GNOSIS: 100,
38
+ LINEA: 59144,
39
+ MAINNET: 1,
40
+ MANTLE: 5000,
41
+ MEGAETH: 4326,
42
+ MONAD: 143,
43
+ OPTIMISM: 10,
44
+ POLYGON: 137,
45
+ SCROLL: 534352,
46
+ TAIKO: 167000,
38
47
  // Testnets
39
- SEPOLIA: 11155111,
48
+ ABSTRACT_TESTNET: 11124,
49
+ ARBITRUM_SEPOLIA: 421614,
50
+ AVALANCHE_FUJI: 43113,
40
51
  BASE_SEPOLIA: 84532,
52
+ BSC_TESTNET: 97,
53
+ CELO_SEPOLIA: 11142220,
54
+ LINEA_SEPOLIA: 59141,
55
+ MANTLE_SEPOLIA: 5003,
56
+ MEGAETH_TESTNET: 6342,
57
+ MONAD_TESTNET: 10143,
58
+ OPTIMISM_SEPOLIA: 11155420,
41
59
  POLYGON_AMOY: 80002,
42
60
  SCROLL_SEPOLIA: 534351,
43
- MONAD_TESTNET: 10143,
44
- BSC_TESTNET: 97,
61
+ SEPOLIA: 11155111,
45
62
  } as const;
46
63
 
47
64
  export type SupportedChainId = (typeof CHAIN_ID)[keyof typeof CHAIN_ID];
@@ -51,7 +68,19 @@ export const ADDRESSES = {
51
68
  // =============================================================================
52
69
  // Mainnets
53
70
  // =============================================================================
54
- [CHAIN_ID.MAINNET]: {
71
+ [CHAIN_ID.ABSTRACT]: {
72
+ identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
73
+ reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
74
+ // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
75
+ validationRegistry: "0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58",
76
+ },
77
+ [CHAIN_ID.ARBITRUM]: {
78
+ identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
79
+ reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
80
+ // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
81
+ validationRegistry: "0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58",
82
+ },
83
+ [CHAIN_ID.AVALANCHE]: {
55
84
  identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
56
85
  reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
57
86
  // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
@@ -63,13 +92,43 @@ export const ADDRESSES = {
63
92
  // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
64
93
  validationRegistry: "0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58",
65
94
  },
66
- [CHAIN_ID.POLYGON]: {
95
+ [CHAIN_ID.BSC]: {
67
96
  identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
68
97
  reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
69
98
  // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
70
99
  validationRegistry: "0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58",
71
100
  },
72
- [CHAIN_ID.SCROLL]: {
101
+ [CHAIN_ID.CELO]: {
102
+ identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
103
+ reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
104
+ // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
105
+ validationRegistry: "0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58",
106
+ },
107
+ [CHAIN_ID.GNOSIS]: {
108
+ identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
109
+ reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
110
+ // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
111
+ validationRegistry: "0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58",
112
+ },
113
+ [CHAIN_ID.LINEA]: {
114
+ identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
115
+ reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
116
+ // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
117
+ validationRegistry: "0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58",
118
+ },
119
+ [CHAIN_ID.MAINNET]: {
120
+ identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
121
+ reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
122
+ // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
123
+ validationRegistry: "0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58",
124
+ },
125
+ [CHAIN_ID.MANTLE]: {
126
+ identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
127
+ reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
128
+ // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
129
+ validationRegistry: "0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58",
130
+ },
131
+ [CHAIN_ID.MEGAETH]: {
73
132
  identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
74
133
  reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
75
134
  // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
@@ -81,13 +140,25 @@ export const ADDRESSES = {
81
140
  // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
82
141
  validationRegistry: "0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58",
83
142
  },
84
- [CHAIN_ID.BSC]: {
143
+ [CHAIN_ID.OPTIMISM]: {
85
144
  identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
86
145
  reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
87
146
  // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
88
147
  validationRegistry: "0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58",
89
148
  },
90
- [CHAIN_ID.GNOSIS]: {
149
+ [CHAIN_ID.POLYGON]: {
150
+ identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
151
+ reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
152
+ // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
153
+ validationRegistry: "0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58",
154
+ },
155
+ [CHAIN_ID.SCROLL]: {
156
+ identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
157
+ reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
158
+ // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
159
+ validationRegistry: "0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58",
160
+ },
161
+ [CHAIN_ID.TAIKO]: {
91
162
  identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
92
163
  reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
93
164
  // TODO: this contract address is not officially announced (found through deployment by same owner as the rest)
@@ -96,7 +167,17 @@ export const ADDRESSES = {
96
167
  // =============================================================================
97
168
  // Testnets
98
169
  // =============================================================================
99
- [CHAIN_ID.SEPOLIA]: {
170
+ [CHAIN_ID.ABSTRACT_TESTNET]: {
171
+ identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
172
+ reputationRegistry: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
173
+ validationRegistry: "0x8004Cb1BF31DAf7788923b405b754f57acEB4272",
174
+ },
175
+ [CHAIN_ID.ARBITRUM_SEPOLIA]: {
176
+ identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
177
+ reputationRegistry: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
178
+ validationRegistry: "0x8004Cb1BF31DAf7788923b405b754f57acEB4272",
179
+ },
180
+ [CHAIN_ID.AVALANCHE_FUJI]: {
100
181
  identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
101
182
  reputationRegistry: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
102
183
  validationRegistry: "0x8004Cb1BF31DAf7788923b405b754f57acEB4272",
@@ -106,12 +187,27 @@ export const ADDRESSES = {
106
187
  reputationRegistry: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
107
188
  validationRegistry: "0x8004Cb1BF31DAf7788923b405b754f57acEB4272",
108
189
  },
109
- [CHAIN_ID.POLYGON_AMOY]: {
190
+ [CHAIN_ID.BSC_TESTNET]: {
110
191
  identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
111
192
  reputationRegistry: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
112
193
  validationRegistry: "0x8004Cb1BF31DAf7788923b405b754f57acEB4272",
113
194
  },
114
- [CHAIN_ID.SCROLL_SEPOLIA]: {
195
+ [CHAIN_ID.CELO_SEPOLIA]: {
196
+ identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
197
+ reputationRegistry: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
198
+ validationRegistry: "0x8004Cb1BF31DAf7788923b405b754f57acEB4272",
199
+ },
200
+ [CHAIN_ID.LINEA_SEPOLIA]: {
201
+ identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
202
+ reputationRegistry: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
203
+ validationRegistry: "0x8004Cb1BF31DAf7788923b405b754f57acEB4272",
204
+ },
205
+ [CHAIN_ID.MANTLE_SEPOLIA]: {
206
+ identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
207
+ reputationRegistry: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
208
+ validationRegistry: "0x8004Cb1BF31DAf7788923b405b754f57acEB4272",
209
+ },
210
+ [CHAIN_ID.MEGAETH_TESTNET]: {
115
211
  identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
116
212
  reputationRegistry: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
117
213
  validationRegistry: "0x8004Cb1BF31DAf7788923b405b754f57acEB4272",
@@ -121,7 +217,22 @@ export const ADDRESSES = {
121
217
  reputationRegistry: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
122
218
  validationRegistry: "0x8004Cb1BF31DAf7788923b405b754f57acEB4272",
123
219
  },
124
- [CHAIN_ID.BSC_TESTNET]: {
220
+ [CHAIN_ID.OPTIMISM_SEPOLIA]: {
221
+ identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
222
+ reputationRegistry: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
223
+ validationRegistry: "0x8004Cb1BF31DAf7788923b405b754f57acEB4272",
224
+ },
225
+ [CHAIN_ID.POLYGON_AMOY]: {
226
+ identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
227
+ reputationRegistry: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
228
+ validationRegistry: "0x8004Cb1BF31DAf7788923b405b754f57acEB4272",
229
+ },
230
+ [CHAIN_ID.SCROLL_SEPOLIA]: {
231
+ identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
232
+ reputationRegistry: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
233
+ validationRegistry: "0x8004Cb1BF31DAf7788923b405b754f57acEB4272",
234
+ },
235
+ [CHAIN_ID.SEPOLIA]: {
125
236
  identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
126
237
  reputationRegistry: "0x8004B663056A597Dffe9eCcC1965A193B7388713",
127
238
  validationRegistry: "0x8004Cb1BF31DAf7788923b405b754f57acEB4272",
@@ -163,13 +274,22 @@ export function isMainnetChain(chainId: number): boolean {
163
274
  }
164
275
 
165
276
  switch (chainId) {
166
- case CHAIN_ID.MAINNET:
277
+ case CHAIN_ID.ABSTRACT:
278
+ case CHAIN_ID.ARBITRUM:
279
+ case CHAIN_ID.AVALANCHE:
167
280
  case CHAIN_ID.BASE:
168
- case CHAIN_ID.POLYGON:
169
- case CHAIN_ID.SCROLL:
170
- case CHAIN_ID.MONAD:
171
281
  case CHAIN_ID.BSC:
282
+ case CHAIN_ID.CELO:
172
283
  case CHAIN_ID.GNOSIS:
284
+ case CHAIN_ID.LINEA:
285
+ case CHAIN_ID.MAINNET:
286
+ case CHAIN_ID.MANTLE:
287
+ case CHAIN_ID.MEGAETH:
288
+ case CHAIN_ID.MONAD:
289
+ case CHAIN_ID.OPTIMISM:
290
+ case CHAIN_ID.POLYGON:
291
+ case CHAIN_ID.SCROLL:
292
+ case CHAIN_ID.TAIKO:
173
293
  return true;
174
294
  default:
175
295
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aixyz/erc-8004",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Payment-native SDK for AI Agent",
5
5
  "keywords": [
6
6
  "ai",
@@ -1,21 +1,15 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
  import {
3
3
  ERC8004_REGISTRATION_TYPE,
4
- RawAgentRegistrationFileSchema,
4
+ AgentRegistrationFileSchema,
5
5
  StrictAgentRegistrationFileSchema,
6
6
  TrustMechanismSchema,
7
7
  ServiceSchema,
8
8
  RegistrationEntrySchema,
9
- parseRawRegistrationFile,
10
- validateRegistrationFile,
11
9
  getServices,
12
10
  hasX402Support,
13
11
  } from "./registration";
14
12
 
15
- // =============================================================================
16
- // Fixtures
17
- // =============================================================================
18
-
19
13
  const minimalValid = {
20
14
  name: "Agently Price Feed",
21
15
  description: "Real-time cryptocurrency price feed agent with x402 payment support",
@@ -52,10 +46,6 @@ const fullValid = {
52
46
  did: "did:pkh:eip155:11155111:0x1234567890abcdef1234567890abcdef12345678",
53
47
  };
54
48
 
55
- // =============================================================================
56
- // TrustMechanismSchema
57
- // =============================================================================
58
-
59
49
  describe("TrustMechanismSchema", () => {
60
50
  test.each(["reputation", "crypto-economic", "tee-attestation", "social", "governance"])("accepts '%s'", (value) => {
61
51
  expect(TrustMechanismSchema.parse(value)).toBe(value);
@@ -66,10 +56,6 @@ describe("TrustMechanismSchema", () => {
66
56
  });
67
57
  });
68
58
 
69
- // =============================================================================
70
- // ServiceSchema
71
- // =============================================================================
72
-
73
59
  describe("ServiceSchema", () => {
74
60
  test("accepts minimal service", () => {
75
61
  const result = ServiceSchema.parse({ name: "mcp-server", endpoint: "https://mcp.acme-agents.com/v1/translate" });
@@ -102,10 +88,6 @@ describe("ServiceSchema", () => {
102
88
  });
103
89
  });
104
90
 
105
- // =============================================================================
106
- // RegistrationEntrySchema
107
- // =============================================================================
108
-
109
91
  describe("RegistrationEntrySchema", () => {
110
92
  test("accepts string agentId and transforms to number", () => {
111
93
  const result = RegistrationEntrySchema.parse({
@@ -173,18 +155,14 @@ describe("RegistrationEntrySchema", () => {
173
155
  });
174
156
  });
175
157
 
176
- // =============================================================================
177
- // RawAgentRegistrationFileSchema
178
- // =============================================================================
179
-
180
158
  describe("RawAgentRegistrationFileSchema", () => {
181
159
  test("accepts minimal valid file", () => {
182
- const result = RawAgentRegistrationFileSchema.parse(minimalValid);
160
+ const result = AgentRegistrationFileSchema.parse(minimalValid);
183
161
  expect(result.name).toBe("Agently Price Feed");
184
162
  });
185
163
 
186
164
  test("accepts fully specified file", () => {
187
- const result = RawAgentRegistrationFileSchema.parse(fullValid);
165
+ const result = AgentRegistrationFileSchema.parse(fullValid);
188
166
  expect(result.services).toHaveLength(2);
189
167
  expect(result.registrations).toHaveLength(1);
190
168
  expect(result.active).toBe(true);
@@ -193,12 +171,12 @@ describe("RawAgentRegistrationFileSchema", () => {
193
171
  });
194
172
 
195
173
  test("type field is optional", () => {
196
- const result = RawAgentRegistrationFileSchema.parse(minimalValid);
174
+ const result = AgentRegistrationFileSchema.parse(minimalValid);
197
175
  expect(result.type).toBeUndefined();
198
176
  });
199
177
 
200
178
  test("accepts endpoints as legacy field", () => {
201
- const result = RawAgentRegistrationFileSchema.parse({
179
+ const result = AgentRegistrationFileSchema.parse({
202
180
  ...minimalValid,
203
181
  endpoints: [{ name: "legacy-mcp", endpoint: "https://mcp.acme-agents.com/v0/translate" }],
204
182
  });
@@ -206,35 +184,31 @@ describe("RawAgentRegistrationFileSchema", () => {
206
184
  });
207
185
 
208
186
  test("accepts both x402support casings", () => {
209
- const r1 = RawAgentRegistrationFileSchema.parse({ ...minimalValid, x402support: true });
210
- const r2 = RawAgentRegistrationFileSchema.parse({ ...minimalValid, x402Support: true });
187
+ const r1 = AgentRegistrationFileSchema.parse({ ...minimalValid, x402support: true });
188
+ const r2 = AgentRegistrationFileSchema.parse({ ...minimalValid, x402Support: true });
211
189
  expect(r1.x402support).toBe(true);
212
190
  expect(r2.x402Support).toBe(true);
213
191
  });
214
192
 
215
193
  test("rejects missing name", () => {
216
- expect(() => RawAgentRegistrationFileSchema.parse({ description: "x", image: "x" })).toThrow();
194
+ expect(() => AgentRegistrationFileSchema.parse({ description: "x", image: "x" })).toThrow();
217
195
  });
218
196
 
219
197
  test("rejects missing description", () => {
220
- expect(() => RawAgentRegistrationFileSchema.parse({ name: "x", image: "x" })).toThrow();
198
+ expect(() => AgentRegistrationFileSchema.parse({ name: "x", image: "x" })).toThrow();
221
199
  });
222
200
 
223
201
  test("rejects missing image", () => {
224
- expect(() => RawAgentRegistrationFileSchema.parse({ name: "x", description: "x" })).toThrow();
202
+ expect(() => AgentRegistrationFileSchema.parse({ name: "x", description: "x" })).toThrow();
225
203
  });
226
204
 
227
205
  test("rejects non-object input", () => {
228
- expect(() => RawAgentRegistrationFileSchema.parse("string")).toThrow();
229
- expect(() => RawAgentRegistrationFileSchema.parse(null)).toThrow();
230
- expect(() => RawAgentRegistrationFileSchema.parse(42)).toThrow();
206
+ expect(() => AgentRegistrationFileSchema.parse("string")).toThrow();
207
+ expect(() => AgentRegistrationFileSchema.parse(null)).toThrow();
208
+ expect(() => AgentRegistrationFileSchema.parse(42)).toThrow();
231
209
  });
232
210
  });
233
211
 
234
- // =============================================================================
235
- // StrictAgentRegistrationFileSchema
236
- // =============================================================================
237
-
238
212
  describe("StrictAgentRegistrationFileSchema", () => {
239
213
  const strictValid = {
240
214
  ...minimalValid,
@@ -287,34 +261,26 @@ describe("StrictAgentRegistrationFileSchema", () => {
287
261
  });
288
262
  });
289
263
 
290
- // =============================================================================
291
- // parseRawRegistrationFile
292
- // =============================================================================
293
-
294
- describe("parseRawRegistrationFile", () => {
264
+ describe("AgentRegistrationFileSchema.safeParse", () => {
295
265
  test("returns success for valid data", () => {
296
- const result = parseRawRegistrationFile(minimalValid);
266
+ const result = AgentRegistrationFileSchema.safeParse(minimalValid);
297
267
  expect(result.success).toBe(true);
298
268
  });
299
269
 
300
270
  test("returns failure for invalid data (does not throw)", () => {
301
- const result = parseRawRegistrationFile({ bad: "data" });
271
+ const result = AgentRegistrationFileSchema.safeParse({ bad: "data" });
302
272
  expect(result.success).toBe(false);
303
273
  });
304
274
 
305
275
  test("returns failure for null", () => {
306
- const result = parseRawRegistrationFile(null);
276
+ const result = AgentRegistrationFileSchema.safeParse(null);
307
277
  expect(result.success).toBe(false);
308
278
  });
309
279
  });
310
280
 
311
- // =============================================================================
312
- // validateRegistrationFile
313
- // =============================================================================
314
-
315
- describe("validateRegistrationFile", () => {
281
+ describe("StrictAgentRegistrationFileSchema.safeParse", () => {
316
282
  test("returns success for strict-valid data", () => {
317
- const result = validateRegistrationFile({
283
+ const result = StrictAgentRegistrationFileSchema.safeParse({
318
284
  ...minimalValid,
319
285
  type: ERC8004_REGISTRATION_TYPE,
320
286
  services: [{ name: "mcp-server", endpoint: "https://mcp.acme-agents.com/v1/price-feed" }],
@@ -323,7 +289,7 @@ describe("validateRegistrationFile", () => {
323
289
  });
324
290
 
325
291
  test("returns failure when type is missing", () => {
326
- const result = validateRegistrationFile({
292
+ const result = StrictAgentRegistrationFileSchema.safeParse({
327
293
  ...minimalValid,
328
294
  services: [{ name: "mcp-server", endpoint: "https://mcp.acme-agents.com/v1/price-feed" }],
329
295
  });
@@ -331,7 +297,7 @@ describe("validateRegistrationFile", () => {
331
297
  });
332
298
 
333
299
  test("returns failure when services is empty", () => {
334
- const result = validateRegistrationFile({
300
+ const result = StrictAgentRegistrationFileSchema.safeParse({
335
301
  ...minimalValid,
336
302
  type: ERC8004_REGISTRATION_TYPE,
337
303
  services: [],
@@ -340,10 +306,6 @@ describe("validateRegistrationFile", () => {
340
306
  });
341
307
  });
342
308
 
343
- // =============================================================================
344
- // getServices
345
- // =============================================================================
346
-
347
309
  describe("getServices", () => {
348
310
  test("returns services when present", () => {
349
311
  const file = {
@@ -375,10 +337,6 @@ describe("getServices", () => {
375
337
  });
376
338
  });
377
339
 
378
- // =============================================================================
379
- // hasX402Support
380
- // =============================================================================
381
-
382
340
  describe("hasX402Support", () => {
383
341
  test("returns true for x402support: true", () => {
384
342
  expect(hasX402Support({ ...minimalValid, x402support: true })).toBe(true);
@@ -7,16 +7,8 @@ import { z } from "zod";
7
7
  * Based on: https://github.com/erc-8004/erc-8004-contracts/blob/093d7b91eb9c22048d411896ed397d695742a5f8/ERC8004SPEC.md#agent-uri-and-agent-registration-file
8
8
  */
9
9
 
10
- // =============================================================================
11
- // Constants
12
- // =============================================================================
13
-
14
10
  export const ERC8004_REGISTRATION_TYPE = "https://eips.ethereum.org/EIPS/eip-8004#registration-v1";
15
11
 
16
- // =============================================================================
17
- // Building Block Schemas
18
- // =============================================================================
19
-
20
12
  /**
21
13
  * Supported trust mechanisms for agent validation
22
14
  */
@@ -57,15 +49,11 @@ export const RegistrationEntrySchema = z.object({
57
49
  agentRegistry: z.string(),
58
50
  });
59
51
 
60
- // =============================================================================
61
- // Main Schemas
62
- // =============================================================================
63
-
64
52
  /**
65
53
  * Raw Agent Registration File Schema
66
54
  * For parsing registration files fetched from IPFS/URIs
67
55
  */
68
- export const RawAgentRegistrationFileSchema = z.object({
56
+ export const AgentRegistrationFileSchema = z.object({
69
57
  // Schema identifiers
70
58
  type: z.string().optional(),
71
59
  $schema: z.string().optional(),
@@ -95,53 +83,31 @@ export const RawAgentRegistrationFileSchema = z.object({
95
83
  * Strict Schema - for creating new registration files
96
84
  * Requires correct type literal and at least one service
97
85
  */
98
- export const StrictAgentRegistrationFileSchema = RawAgentRegistrationFileSchema.extend({
86
+ export const StrictAgentRegistrationFileSchema = AgentRegistrationFileSchema.extend({
99
87
  type: z.literal(ERC8004_REGISTRATION_TYPE),
100
88
  services: z.array(ServiceSchema).min(1, "At least one service endpoint is required"),
101
89
  });
102
90
 
103
- // =============================================================================
104
- // Types
105
- // =============================================================================
106
-
107
91
  export type TrustMechanism = z.infer<typeof TrustMechanismSchema>;
108
92
  export type Service = z.infer<typeof ServiceSchema>;
109
93
  export type RegistrationEntry = z.infer<typeof RegistrationEntrySchema>;
110
- export type RawAgentRegistrationFile = z.infer<typeof RawAgentRegistrationFileSchema>;
94
+ export type AgentRegistrationFile = z.infer<typeof AgentRegistrationFileSchema>;
111
95
  export type StrictAgentRegistrationFile = z.infer<typeof StrictAgentRegistrationFileSchema>;
112
96
 
113
- // =============================================================================
114
- // Helper Functions
115
- // =============================================================================
116
-
117
- /**
118
- * Parse a raw registration file
119
- * Use for existing/untrusted data fetched from IPFS/URIs - won't throw on malformed input
120
- */
121
- export function parseRawRegistrationFile(data: unknown) {
122
- return RawAgentRegistrationFileSchema.safeParse(data);
123
- }
124
-
125
- /**
126
- * Validate a registration file with strict validation
127
- * Use when creating or submitting new registration files
128
- */
129
- export function validateRegistrationFile(data: unknown) {
130
- return StrictAgentRegistrationFileSchema.safeParse(data);
131
- }
132
-
133
97
  /**
134
98
  * Get services from a registration file
135
99
  * Handles both `services` (new) and `endpoints` (legacy) field names
100
+ * @default TODO: parse and merge both fields
136
101
  */
137
- export function getServices(file: RawAgentRegistrationFile | StrictAgentRegistrationFile): Service[] {
102
+ export function getServices(file: AgentRegistrationFile | StrictAgentRegistrationFile): Service[] {
138
103
  return file.services ?? file.endpoints ?? [];
139
104
  }
140
105
 
141
106
  /**
142
107
  * Check if agent supports x402 payment protocol
143
108
  * Handles both `x402support` and `x402Support` casing variants
109
+ * @deprecated TODO: parse and merge both fields
144
110
  */
145
- export function hasX402Support(file: RawAgentRegistrationFile | StrictAgentRegistrationFile): boolean {
111
+ export function hasX402Support(file: AgentRegistrationFile | StrictAgentRegistrationFile): boolean {
146
112
  return file.x402support === true || file.x402Support === true;
147
113
  }