@ens-node-metadata/agent 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +126 -0
  3. package/SKILL.md +104 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +29 -0
  7. package/dist/commands/metadata/set.d.ts +21 -0
  8. package/dist/commands/metadata/set.d.ts.map +1 -0
  9. package/dist/commands/metadata/set.js +75 -0
  10. package/dist/commands/metadata/template.d.ts +4 -0
  11. package/dist/commands/metadata/template.d.ts.map +1 -0
  12. package/dist/commands/metadata/template.js +7 -0
  13. package/dist/commands/metadata/validate.d.ts +10 -0
  14. package/dist/commands/metadata/validate.d.ts.map +1 -0
  15. package/dist/commands/metadata/validate.js +44 -0
  16. package/dist/commands/register.d.ts +21 -0
  17. package/dist/commands/register.d.ts.map +1 -0
  18. package/dist/commands/register.js +76 -0
  19. package/dist/commands/registration-file/publish.d.ts +10 -0
  20. package/dist/commands/registration-file/publish.d.ts.map +1 -0
  21. package/dist/commands/registration-file/publish.js +79 -0
  22. package/dist/commands/registration-file/template.d.ts +3 -0
  23. package/dist/commands/registration-file/template.d.ts.map +1 -0
  24. package/dist/commands/registration-file/template.js +48 -0
  25. package/dist/commands/registration-file/validate.d.ts +10 -0
  26. package/dist/commands/registration-file/validate.d.ts.map +1 -0
  27. package/dist/commands/registration-file/validate.js +35 -0
  28. package/dist/commands/registry/identity.d.ts +18 -0
  29. package/dist/commands/registry/identity.d.ts.map +1 -0
  30. package/dist/commands/registry/identity.js +115 -0
  31. package/dist/commands/skill.d.ts +16 -0
  32. package/dist/commands/skill.d.ts.map +1 -0
  33. package/dist/commands/skill.js +53 -0
  34. package/dist/commands/update.d.ts +21 -0
  35. package/dist/commands/update.d.ts.map +1 -0
  36. package/dist/commands/update.js +76 -0
  37. package/dist/index.d.ts +82 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +5 -0
  40. package/dist/lib/ens-write.d.ts +6 -0
  41. package/dist/lib/ens-write.d.ts.map +1 -0
  42. package/dist/lib/ens-write.js +23 -0
  43. package/dist/lib/ui.d.ts +6 -0
  44. package/dist/lib/ui.d.ts.map +1 -0
  45. package/dist/lib/ui.js +14 -0
  46. package/dist/types.d.ts +181 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +84 -0
  49. package/package.json +44 -0
  50. package/src/index.ts +8 -0
package/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # @ens-node-metadata/agent
2
+
3
+ CLI for registering AI agents on ENS using [ERC-8004](https://best-practices.8004scan.io/docs/01-agent-metadata-standard.html) (v2.0).
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ pnpm dlx @ens-node-metadata/agent --help
9
+ ```
10
+
11
+ ## Commands
12
+
13
+ ```sh
14
+ agent skill [--install]
15
+ Print SKILL.md. With --install, copy it to the current directory.
16
+
17
+ agent registration-file template
18
+ Print an empty ERC-8004 v2.0 registration JSON to stdout.
19
+
20
+ agent registration-file validate <registration-file.json>
21
+ Validate against Zod schema. Prints ✅ or errors ❌.
22
+ Emits WA031 deprecation warning if the legacy `endpoints` field is used.
23
+
24
+ agent registration-file publish <registration-file.json>
25
+ Publish to IPFS via @web3-storage/w3up-client. Prints the ipfs:// URI.
26
+ Requires: W3_PRINCIPAL, W3_PROOF env vars (see below).
27
+
28
+ agent registry identity --chain-name <chain> <agent-uri>
29
+ Read the ERC-8004 Identity Registry for the given chain.
30
+ Supported chains: base, mainnet.
31
+ Requires: ERC8004_REGISTRY_<CHAIN> env var.
32
+
33
+ agent metadata template
34
+ Print a starter ENS metadata payload JSON (the text records to set).
35
+
36
+ agent metadata validate <payload.json>
37
+ Validate ENS metadata payload against the agent schema.
38
+
39
+ agent register <ENS> <payload.json> --private-key <key> [--broadcast]
40
+ Build ENS setTextRecords transaction. Dry run by default; --broadcast submits it.
41
+ Uses viem + @ensdomains/ensjs.
42
+
43
+ agent update <ENS> <payload.json> --private-key <key> [--broadcast]
44
+ Same as register — for updating existing records.
45
+ ```
46
+
47
+ ## Environment Variables
48
+
49
+ Optional
50
+
51
+ * PINATA_API_KEY
52
+ * PINATA_API_SECRET
53
+ * PINATA_JWT
54
+
55
+ ## ERC-8004 v2.0 Registration File
56
+
57
+ The registration file is a JSON document published to IPFS or HTTPS. Its `ipfs://` URI is stored as the `agent-uri` ENS text record.
58
+
59
+ ```json
60
+ {
61
+ "type": "Agent",
62
+ "name": "My Agent",
63
+ "description": "Does useful things on-chain.",
64
+ "services": [
65
+ { "name": "MCP", "endpoint": "https://myagent.example.com/mcp", "version": "1.0" },
66
+ { "name": "A2A", "endpoint": "https://myagent.example.com/a2a", "version": "0.3" }
67
+ ],
68
+ "x402Support": false,
69
+ "active": true,
70
+ "registrations": [],
71
+ "supportedTrust": ["reputation"]
72
+ }
73
+ ```
74
+
75
+ > ⚠️ **v2.0 migration:** The field name changed from `endpoints` → `services` (Jan 2026).
76
+ > The CLI accepts `endpoints` for backward compatibility with a WA031 deprecation warning.
77
+
78
+ ## Registration Flow
79
+
80
+ 1. `agent registration-file template > registration.json` — create the file
81
+ 2. Edit `registration.json`
82
+ 3. `agent registration-file validate registration.json` — validate
83
+ 4. `agent registration-file publish registration.json` — publish to IPFS → get `ipfs://` URI
84
+ 5. `agent metadata template > payload.json` — create the ENS record payload
85
+ 6. Set `agent-uri` to the `ipfs://` URI in `payload.json`
86
+ 7. `agent metadata validate payload.json` — validate
87
+ 8. `agent register myagent.eth payload.json --private-key $PK --broadcast` — register
88
+
89
+ See [SKILL.md](./SKILL.md) for the full step-by-step guide.
90
+
91
+ ## TypeScript API
92
+
93
+ ```ts
94
+ import {
95
+ buildRegistrationFile,
96
+ validateRegistrationFile,
97
+ AgentRegistrationFileSchema,
98
+ } from "@ens-node-metadata/agent";
99
+
100
+ // Build a registration file
101
+ const file = buildRegistrationFile({
102
+ name: "My AI Agent",
103
+ description: "Does useful things on-chain.",
104
+ services: [
105
+ { name: "MCP", endpoint: "https://myagent.example.com/mcp", version: "1.0" },
106
+ ],
107
+ active: true,
108
+ supportedTrust: ["reputation"],
109
+ });
110
+
111
+ // Validate an untrusted payload
112
+ const raw = JSON.parse(maybeInvalidJson);
113
+ const result = validateRegistrationFile(raw);
114
+ if (result.success) {
115
+ console.log(result.data.name);
116
+ // Check for legacy `endpoints` field usage
117
+ if (result.data._legacyEndpoints) {
118
+ console.warn("WA031: migrate from `endpoints` to `services`");
119
+ }
120
+ }
121
+ ```
122
+
123
+ ## Related Packages
124
+
125
+ * [`@ens-node-metadata/schemas`](../schemas) — JSON schemas for all ENS node types
126
+ * [`@ens-node-metadata/sdk`](../sdk) — ENS metadata read SDK
package/SKILL.md ADDED
@@ -0,0 +1,104 @@
1
+ ---
2
+ name: ens-agent-registration
3
+ description: Register an AI agent on ENS using ERC-8004.
4
+ allowed-tools: Bash(node:*), Bash(ipfs:*), Bash(cast:*)
5
+ ---
6
+
7
+ # Agents
8
+
9
+ A skill to help manage your agents metadata on ENS along with ERC-8004 management.
10
+
11
+ ## Bootstrap
12
+
13
+ * Ask your human, what is their agents ens name is?
14
+ * Hereby referred to as AGENT_ENS_NAME
15
+
16
+ ## Command overview
17
+
18
+ Run `agent --help` or `agent <command> --help` for full usage.
19
+
20
+ ```sh
21
+ agent registration-file template # prints example JSON
22
+ agent registration-file validate <file> # validates SCHEMA_8004_V2
23
+ agent registration-file publish <file> # upload to IPFS via Pinata
24
+ # => Returns <agent-uri>
25
+
26
+ # Register agent with canonical 8004 registries
27
+ agent registry identity --chain-name <chain> <agent-uri> --private-key <0x...> [--broadcast]
28
+
29
+ agent metadata template # starter ENS text-record payload
30
+ agent metadata validate <payload> # validates metadata JSON schema
31
+ agent metadata set <AGENT_ENS_NAME> <payload> --private-key <0x...> [--broadcast]
32
+
33
+ agent skill [--install] # Installs
34
+ ```
35
+
36
+ ## Workflows
37
+
38
+ ### ERC-8004 operations
39
+
40
+ #### Building a registration file
41
+
42
+ A registration file is required to register your Agent's identity.
43
+
44
+ ```sh
45
+ # edit with your details
46
+ agent registration-file template > registration.json`
47
+
48
+ # validate
49
+ agent registration-file validate registration.json`
50
+ ```
51
+
52
+ #### Publishing a registration file
53
+
54
+ We publish to IPFS using <https://pinata.cloud>.
55
+
56
+ The following variables should be in your environment to use this command.
57
+
58
+ * `PINATA_JWT`, `PINATA_API_KEY`, `PINATA_API_SECRET`
59
+
60
+ ```sh
61
+ # Publish to IPFS
62
+ agent registration-file publish registration.json`
63
+ # Returns => ipfs://CID henceforth referred to as <agent-uri>
64
+ ```
65
+
66
+ #### Register your Agent
67
+
68
+ We publish to the cannonical registries <https://github.com/erc-8004/erc-8004-contracts>
69
+
70
+ ```sh
71
+ agent registry identity --chain-name <chain> <agent-uri> --private-key <0x...> [--broadcast]
72
+ # Returns => <agent-id>
73
+ ```
74
+
75
+ ### ENS operations
76
+
77
+ #### Preparing a metadata payload
78
+
79
+ A metadata payload descrbes which text records to set.
80
+
81
+ ```sh
82
+ # Agent metadata expressed as JSON schema
83
+ agent metadata template > payload.json
84
+
85
+ # Validator
86
+ agent metadata validate payload.json
87
+ ```
88
+
89
+ #### Updating metadata on ENS
90
+
91
+ * Use this command to set Agent metadata against your ENS name.
92
+ * Consider updating your metadata when key information about your skills, identity or capabilities change.
93
+ * Remember to also update your `<agent-uri>`.
94
+
95
+ ```sh
96
+ agent metadata set <AGENT_ENS_NAME> payload.json --private-key 0x<KEY> --broadcast`
97
+ ```
98
+
99
+ ## References
100
+
101
+ * Agent Metadata (ERC-8004) used for registration-file command
102
+ * <https://best-practices.8004scan.io/docs/01-agent-metadata-standard.html>
103
+ * ENS Metadata - Agent schema, used for metadata command
104
+ * <https://ens-metadata-docs.vercel.app/schemas/agent>
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ import Pastel from 'pastel';
3
+ const args = process.argv.slice(2);
4
+ const isRootHelp = args.length === 0 || (args.length === 1 && (args[0] === '--help' || args[0] === '-h'));
5
+ if (isRootHelp) {
6
+ console.log(`
7
+ CLI for registering AI agents on ENS using ERC-8004 (v2.0).
8
+
9
+ Usage:
10
+ agent skill [--install]
11
+
12
+ agent registration-file template
13
+ agent registration-file validate <file.json>
14
+ agent registration-file publish <file.json>
15
+
16
+ agent registry identity --chain-name <chain> <agent-uri>
17
+
18
+ agent metadata template
19
+ agent metadata validate <payload.json>
20
+ agent metadata set <ens-node> <payload.json> --private-key <key> [--broadcast]
21
+
22
+ Run \`agent <command> --help\` for details on a specific command.
23
+ `);
24
+ process.exit(0);
25
+ }
26
+ const app = new Pastel({
27
+ importMeta: import.meta,
28
+ });
29
+ await app.run();
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import { z } from 'zod';
3
+ export declare const description = "Set ENS metadata text records from a payload file";
4
+ export declare const args: z.ZodTuple<[z.ZodString, z.ZodString], null>;
5
+ export declare const options: z.ZodObject<{
6
+ privateKey: z.ZodString;
7
+ broadcast: z.ZodDefault<z.ZodBoolean>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ privateKey: string;
10
+ broadcast: boolean;
11
+ }, {
12
+ privateKey: string;
13
+ broadcast?: boolean | undefined;
14
+ }>;
15
+ type Props = {
16
+ args: z.infer<typeof args>;
17
+ options: z.infer<typeof options>;
18
+ };
19
+ export default function Set({ args: [ensName, payloadFile], options }: Props): React.JSX.Element;
20
+ export {};
21
+ //# sourceMappingURL=set.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../../src/commands/metadata/set.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,eAAO,MAAM,WAAW,sDAAsD,CAAA;AAE9E,eAAO,MAAM,IAAI,8CAGf,CAAA;AAEF,eAAO,MAAM,OAAO;;;;;;;;;EAMlB,CAAA;AAEF,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAA;IAC1B,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,CAAA;CACjC,CAAA;AAQD,MAAM,CAAC,OAAO,UAAU,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,qBA4D3E"}
@@ -0,0 +1,75 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { Box, Text, useApp } from 'ink';
3
+ import React from 'react';
4
+ import { z } from 'zod';
5
+ import { SCHEMA_MAP } from '@ens-node-metadata/schemas';
6
+ import { validateMetadataSchema } from '@ens-node-metadata/sdk';
7
+ import { setEnsTextRecords } from '../../lib/ens-write.js';
8
+ export const description = 'Set ENS metadata text records from a payload file';
9
+ export const args = z.tuple([
10
+ z.string().describe('ENS name (e.g. myagent.eth)'),
11
+ z.string().describe('payload.json'),
12
+ ]);
13
+ export const options = z.object({
14
+ privateKey: z.string().describe('Private key for signing (hex, prefixed with 0x)'),
15
+ broadcast: z
16
+ .boolean()
17
+ .default(false)
18
+ .describe('Broadcast the transaction on-chain (default: dry run)'),
19
+ });
20
+ export default function Set({ args: [ensName, payloadFile], options }) {
21
+ const { exit } = useApp();
22
+ const [state, setState] = React.useState({ status: 'idle' });
23
+ React.useEffect(() => {
24
+ async function run() {
25
+ let payload;
26
+ try {
27
+ const raw = JSON.parse(readFileSync(payloadFile, 'utf8'));
28
+ const result = validateMetadataSchema(raw, SCHEMA_MAP.Agent);
29
+ if (!result.success) {
30
+ const issues = result.errors.map((e) => `[${e.key}] ${e.message}`).join('\n');
31
+ setState({ status: 'error', message: `Invalid payload:\n${issues}` });
32
+ exit(new Error('validation failed'));
33
+ return;
34
+ }
35
+ payload = result.data;
36
+ }
37
+ catch (err) {
38
+ setState({ status: 'error', message: `Error reading payload: ${err.message}` });
39
+ exit(new Error('read error'));
40
+ return;
41
+ }
42
+ const texts = Object.entries(payload).map(([key, value]) => ({ key, value }));
43
+ if (!options.broadcast) {
44
+ const lines = [
45
+ `Dry run — would set ${texts.length} text records on ${ensName}:`,
46
+ '',
47
+ ...texts.map((t) => ` setText("${t.key}", "${t.value}")`),
48
+ '',
49
+ 'Run with --broadcast to submit on-chain.',
50
+ ];
51
+ setState({ status: 'done', message: lines.join('\n') });
52
+ exit();
53
+ return;
54
+ }
55
+ setState({ status: 'working', message: `Setting ${texts.length} text records on ${ensName}…` });
56
+ try {
57
+ const hash = await setEnsTextRecords(ensName, texts, options.privateKey);
58
+ setState({ status: 'done', message: `✅ Transaction submitted: ${hash}` });
59
+ exit();
60
+ }
61
+ catch (err) {
62
+ setState({ status: 'error', message: `Transaction failed: ${err.message}` });
63
+ exit(new Error('tx failed'));
64
+ }
65
+ }
66
+ run();
67
+ }, [exit, ensName, payloadFile, options]);
68
+ return (React.createElement(Box, { flexDirection: "column" },
69
+ state.status === 'idle' && React.createElement(Text, { color: "gray" }, "Preparing\u2026"),
70
+ state.status === 'working' && React.createElement(Text, { color: "cyan" }, state.message),
71
+ state.status === 'done' && React.createElement(Text, { color: "green" }, state.message),
72
+ state.status === 'error' && React.createElement(Text, { color: "red" },
73
+ "\u274C ",
74
+ state.message)));
75
+ }
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare const description = "Generate starter ENS metadata payload template";
3
+ export default function MetadataTemplate(): React.JSX.Element;
4
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../../src/commands/metadata/template.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,eAAO,MAAM,WAAW,mDAAmD,CAAA;AAE3E,MAAM,CAAC,OAAO,UAAU,gBAAgB,sBAMvC"}
@@ -0,0 +1,7 @@
1
+ import { Text } from 'ink';
2
+ import React from 'react';
3
+ import { SCHEMA_MAP } from '@ens-node-metadata/schemas';
4
+ export const description = 'Generate starter ENS metadata payload template';
5
+ export default function MetadataTemplate() {
6
+ return (React.createElement(Text, null, JSON.stringify(SCHEMA_MAP.Agent, null, 2)));
7
+ }
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { z } from 'zod';
3
+ export declare const description = "Validate ENS metadata payload against agent schema";
4
+ export declare const args: z.ZodTuple<[z.ZodString], null>;
5
+ type Props = {
6
+ args: z.infer<typeof args>;
7
+ };
8
+ export default function MetadataValidate({ args: [file] }: Props): React.JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/commands/metadata/validate.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,WAAW,uDAAuD,CAAA;AAE/E,eAAO,MAAM,IAAI,iCAAiD,CAAA;AAElE,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAA;CAC3B,CAAA;AAED,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,qBAwC/D"}
@@ -0,0 +1,44 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { Box, Text, useApp } from 'ink';
3
+ import React from 'react';
4
+ import { z } from 'zod';
5
+ import { SCHEMA_MAP } from '@ens-node-metadata/schemas';
6
+ import { validateMetadataSchema } from '@ens-node-metadata/sdk';
7
+ export const description = 'Validate ENS metadata payload against agent schema';
8
+ export const args = z.tuple([z.string().describe('payload.json')]);
9
+ export default function MetadataValidate({ args: [file] }) {
10
+ const { exit } = useApp();
11
+ let fileError = null;
12
+ let result = null;
13
+ try {
14
+ const raw = JSON.parse(readFileSync(file, 'utf8'));
15
+ result = validateMetadataSchema(raw, SCHEMA_MAP.Agent);
16
+ }
17
+ catch (err) {
18
+ fileError = err.message;
19
+ }
20
+ React.useEffect(() => {
21
+ exit(fileError || (result && !result.success) ? new Error('validation failed') : undefined);
22
+ }, [exit, fileError, result]);
23
+ if (fileError) {
24
+ return React.createElement(Text, { color: "red" },
25
+ "\u274C Error reading file: ",
26
+ fileError);
27
+ }
28
+ if (result.success) {
29
+ return (React.createElement(Box, { flexDirection: "column" },
30
+ React.createElement(Text, { color: "green" }, "\u2705 Valid ENS agent metadata payload"),
31
+ React.createElement(Text, { color: "gray" },
32
+ " ",
33
+ Object.keys(result.data).length,
34
+ " text records")));
35
+ }
36
+ return (React.createElement(Box, { flexDirection: "column" },
37
+ React.createElement(Text, { color: "red" }, "\u274C Invalid agent metadata payload"),
38
+ result.errors.map(({ key, message }) => (React.createElement(Text, { key: key, color: "red" },
39
+ ' ',
40
+ "[",
41
+ key,
42
+ "] ",
43
+ message)))));
44
+ }
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import { z } from 'zod';
3
+ export declare const description = "Register agent on ENS with metadata payload";
4
+ export declare const args: z.ZodTuple<[z.ZodString, z.ZodString], null>;
5
+ export declare const options: z.ZodObject<{
6
+ privateKey: z.ZodString;
7
+ broadcast: z.ZodDefault<z.ZodBoolean>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ privateKey: string;
10
+ broadcast: boolean;
11
+ }, {
12
+ privateKey: string;
13
+ broadcast?: boolean | undefined;
14
+ }>;
15
+ type Props = {
16
+ args: z.infer<typeof args>;
17
+ options: z.infer<typeof options>;
18
+ };
19
+ export default function Register({ args: [ensName, payloadFile], options }: Props): React.JSX.Element;
20
+ export {};
21
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/commands/register.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,WAAW,gDAAgD,CAAA;AAExE,eAAO,MAAM,IAAI,8CAGf,CAAA;AAEF,eAAO,MAAM,OAAO;;;;;;;;;EAMlB,CAAA;AAEF,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAA;IAC1B,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,CAAA;CACjC,CAAA;AAQD,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,qBA8DhF"}
@@ -0,0 +1,76 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { Box, Text, useApp } from 'ink';
3
+ import React from 'react';
4
+ import { z } from 'zod';
5
+ import { AgentMetadataPayloadSchema } from '../index.js';
6
+ import { setEnsTextRecords } from '../lib/ens-write.js';
7
+ export const description = 'Register agent on ENS with metadata payload';
8
+ export const args = z.tuple([
9
+ z.string().describe('EnsNode'),
10
+ z.string().describe('payload.json'),
11
+ ]);
12
+ export const options = z.object({
13
+ privateKey: z.string().describe('Private key for signing (hex, prefixed with 0x)'),
14
+ broadcast: z
15
+ .boolean()
16
+ .default(false)
17
+ .describe('Broadcast the transaction on-chain (default: dry run)'),
18
+ });
19
+ export default function Register({ args: [ensName, payloadFile], options }) {
20
+ const { exit } = useApp();
21
+ const [state, setState] = React.useState({ status: 'idle' });
22
+ React.useEffect(() => {
23
+ async function run() {
24
+ let payload;
25
+ try {
26
+ const raw = JSON.parse(readFileSync(payloadFile, 'utf8'));
27
+ const result = AgentMetadataPayloadSchema.safeParse(raw);
28
+ if (!result.success) {
29
+ const issues = result.error.issues
30
+ .map((i) => `[${i.path.join('.') || 'root'}] ${i.message}`)
31
+ .join('\n');
32
+ setState({ status: 'error', message: `Invalid payload:\n${issues}` });
33
+ exit(new Error('validation failed'));
34
+ return;
35
+ }
36
+ payload = result.data;
37
+ }
38
+ catch (err) {
39
+ setState({ status: 'error', message: `Error reading payload: ${err.message}` });
40
+ exit(new Error('read error'));
41
+ return;
42
+ }
43
+ const texts = Object.entries(payload).map(([key, value]) => ({ key, value }));
44
+ if (!options.broadcast) {
45
+ const lines = [
46
+ `Dry run — would set ${texts.length} text records on ${ensName}:`,
47
+ '',
48
+ ...texts.map((t) => ` setText("${t.key}", "${t.value}")`),
49
+ '',
50
+ 'Run with --broadcast to submit on-chain.',
51
+ ];
52
+ setState({ status: 'done', message: lines.join('\n') });
53
+ exit();
54
+ return;
55
+ }
56
+ setState({ status: 'working', message: `Setting ${texts.length} text records on ${ensName}…` });
57
+ try {
58
+ const hash = await setEnsTextRecords(ensName, texts, options.privateKey);
59
+ setState({ status: 'done', message: `✅ Transaction submitted: ${hash}` });
60
+ exit();
61
+ }
62
+ catch (err) {
63
+ setState({ status: 'error', message: `Transaction failed: ${err.message}` });
64
+ exit(new Error('tx failed'));
65
+ }
66
+ }
67
+ run();
68
+ }, [exit, ensName, payloadFile, options]);
69
+ return (React.createElement(Box, { flexDirection: "column" },
70
+ state.status === 'idle' && React.createElement(Text, { color: "gray" }, "Preparing\u2026"),
71
+ state.status === 'working' && React.createElement(Text, { color: "cyan" }, state.message),
72
+ state.status === 'done' && React.createElement(Text, { color: "green" }, state.message),
73
+ state.status === 'error' && React.createElement(Text, { color: "red" },
74
+ "\u274C ",
75
+ state.message)));
76
+ }
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { z } from 'zod';
3
+ export declare const description = "Publish registration file to IPFS via Pinata";
4
+ export declare const args: z.ZodTuple<[z.ZodString], null>;
5
+ type Props = {
6
+ args: z.infer<typeof args>;
7
+ };
8
+ export default function RegistrationFilePublish({ args: [file] }: Props): React.JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=publish.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../../src/commands/registration-file/publish.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,WAAW,iDAAiD,CAAA;AAEzE,eAAO,MAAM,IAAI,iCAA2D,CAAA;AAE5E,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAA;CAC3B,CAAA;AASD,MAAM,CAAC,OAAO,UAAU,uBAAuB,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,qBAkFtE"}
@@ -0,0 +1,79 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { Box, Text, useApp } from 'ink';
3
+ import React from 'react';
4
+ import { z } from 'zod';
5
+ import { validateRegistrationFile } from '../../index.js';
6
+ import { publishFile } from '@ens-node-metadata/shared';
7
+ export const description = 'Publish registration file to IPFS via Pinata';
8
+ export const args = z.tuple([z.string().describe('registration-file.json')]);
9
+ export default function RegistrationFilePublish({ args: [file] }) {
10
+ const { exit } = useApp();
11
+ const [state, setState] = React.useState({ status: 'idle' });
12
+ React.useEffect(() => {
13
+ async function run() {
14
+ // 1. Check env vars
15
+ const pinataJwt = process.env.PINATA_JWT;
16
+ const pinataKey = process.env.PINATA_API_KEY;
17
+ const pinataSecret = process.env.PINATA_API_SECRET;
18
+ if (!pinataJwt && !(pinataKey && pinataSecret)) {
19
+ setState({
20
+ status: 'error',
21
+ message: 'Missing Pinata credentials. Set PINATA_JWT or both PINATA_API_KEY and PINATA_API_SECRET.',
22
+ });
23
+ exit(new Error('missing env vars'));
24
+ return;
25
+ }
26
+ // 2. Validate registration file
27
+ setState({ status: 'validating' });
28
+ let raw;
29
+ try {
30
+ raw = JSON.parse(readFileSync(file, 'utf8'));
31
+ }
32
+ catch (err) {
33
+ setState({ status: 'error', message: `Error reading file: ${err.message}` });
34
+ exit(new Error('read error'));
35
+ return;
36
+ }
37
+ const result = validateRegistrationFile(raw);
38
+ if (!result.success) {
39
+ const issues = result.error.issues
40
+ .map((i) => `[${i.path.join('.') || 'root'}] ${i.message}`)
41
+ .join('\n');
42
+ setState({ status: 'error', message: `Invalid registration file:\n${issues}` });
43
+ exit(new Error('validation failed'));
44
+ return;
45
+ }
46
+ // 3. Upload to IPFS via Pinata
47
+ setState({ status: 'uploading' });
48
+ try {
49
+ const { cid } = await publishFile({
50
+ provider: 'pinata',
51
+ filePath: file,
52
+ pinataJwt,
53
+ pinataKey,
54
+ pinataSecret,
55
+ schemaId: result.data.name,
56
+ version: '1.0.0',
57
+ });
58
+ setState({ status: 'done', uri: `ipfs://${cid}` });
59
+ exit();
60
+ }
61
+ catch (err) {
62
+ setState({ status: 'error', message: `Upload failed: ${err.message}` });
63
+ exit(new Error('upload failed'));
64
+ }
65
+ }
66
+ run();
67
+ }, [exit, file]);
68
+ return (React.createElement(Box, { flexDirection: "column" },
69
+ state.status === 'idle' && React.createElement(Text, { color: "gray" }, "Preparing\u2026"),
70
+ state.status === 'validating' && React.createElement(Text, { color: "cyan" }, "Validating registration file\u2026"),
71
+ state.status === 'uploading' && React.createElement(Text, { color: "cyan" }, "Uploading to IPFS via Pinata\u2026"),
72
+ state.status === 'done' && (React.createElement(Box, { flexDirection: "column" },
73
+ React.createElement(Text, { color: "green" }, "\u2705 Published to IPFS"),
74
+ React.createElement(Text, null, state.uri))),
75
+ state.status === 'error' && (React.createElement(Box, { flexDirection: "column" },
76
+ React.createElement(Text, { color: "red" },
77
+ "\u274C ",
78
+ state.message)))));
79
+ }
@@ -0,0 +1,3 @@
1
+ export declare const description = "Generate empty ERC-8004 v2.0 registration file template";
2
+ export default function RegistrationFileTemplate(): null;
3
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../../src/commands/registration-file/template.tsx"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,4DAA4D,CAAA;AAwCpF,MAAM,CAAC,OAAO,UAAU,wBAAwB,SAQ/C"}