@beclab/olaresid 0.1.1 → 0.1.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.
Files changed (87) hide show
  1. package/CLI.md +1300 -0
  2. package/README.md +37 -31
  3. package/TAG.md +589 -0
  4. package/dist/abi/RootResolver2ABI.d.ts +54 -0
  5. package/dist/abi/RootResolver2ABI.d.ts.map +1 -0
  6. package/dist/abi/RootResolver2ABI.js +240 -0
  7. package/dist/abi/RootResolver2ABI.js.map +1 -0
  8. package/dist/business/index.d.ts +302 -0
  9. package/dist/business/index.d.ts.map +1 -0
  10. package/dist/business/index.js +1209 -0
  11. package/dist/business/index.js.map +1 -0
  12. package/dist/business/tag-context.d.ts +219 -0
  13. package/dist/business/tag-context.d.ts.map +1 -0
  14. package/dist/business/tag-context.js +537 -0
  15. package/dist/business/tag-context.js.map +1 -0
  16. package/dist/cli.js +2085 -39
  17. package/dist/cli.js.map +1 -1
  18. package/dist/debug.d.ts.map +1 -1
  19. package/dist/debug.js +14 -2
  20. package/dist/debug.js.map +1 -1
  21. package/dist/index.d.ts +50 -2
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +229 -9
  24. package/dist/index.js.map +1 -1
  25. package/dist/utils/crypto-utils.d.ts +130 -0
  26. package/dist/utils/crypto-utils.d.ts.map +1 -0
  27. package/dist/utils/crypto-utils.js +402 -0
  28. package/dist/utils/crypto-utils.js.map +1 -0
  29. package/dist/utils/error-parser.d.ts +35 -0
  30. package/dist/utils/error-parser.d.ts.map +1 -0
  31. package/dist/utils/error-parser.js +202 -0
  32. package/dist/utils/error-parser.js.map +1 -0
  33. package/dist/utils/tag-abi-codec.d.ts +69 -0
  34. package/dist/utils/tag-abi-codec.d.ts.map +1 -0
  35. package/dist/utils/tag-abi-codec.js +144 -0
  36. package/dist/utils/tag-abi-codec.js.map +1 -0
  37. package/dist/utils/tag-type-builder.d.ts +158 -0
  38. package/dist/utils/tag-type-builder.d.ts.map +1 -0
  39. package/dist/utils/tag-type-builder.js +410 -0
  40. package/dist/utils/tag-type-builder.js.map +1 -0
  41. package/examples/crypto-utilities.ts +140 -0
  42. package/examples/domain-context.ts +80 -0
  43. package/examples/generate-mnemonic.ts +149 -0
  44. package/examples/index.ts +1 -1
  45. package/examples/ip.ts +171 -0
  46. package/examples/legacy.ts +10 -10
  47. package/examples/list-wallets.ts +81 -0
  48. package/examples/quasar-demo/.eslintrc.js +23 -0
  49. package/examples/quasar-demo/.quasar/app.js +43 -0
  50. package/examples/quasar-demo/.quasar/client-entry.js +38 -0
  51. package/examples/quasar-demo/.quasar/client-prefetch.js +130 -0
  52. package/examples/quasar-demo/.quasar/quasar-user-options.js +16 -0
  53. package/examples/quasar-demo/README.md +49 -0
  54. package/examples/quasar-demo/index.html +11 -0
  55. package/examples/quasar-demo/package-lock.json +6407 -0
  56. package/examples/quasar-demo/package.json +36 -0
  57. package/examples/quasar-demo/quasar.config.js +73 -0
  58. package/examples/quasar-demo/src/App.vue +13 -0
  59. package/examples/quasar-demo/src/css/app.scss +1 -0
  60. package/examples/quasar-demo/src/layouts/MainLayout.vue +21 -0
  61. package/examples/quasar-demo/src/pages/IndexPage.vue +905 -0
  62. package/examples/quasar-demo/src/router/index.ts +25 -0
  63. package/examples/quasar-demo/src/router/routes.ts +11 -0
  64. package/examples/quasar-demo/tsconfig.json +28 -0
  65. package/examples/register-subdomain.ts +152 -0
  66. package/examples/rsa-keypair.ts +148 -0
  67. package/examples/tag-builder.ts +235 -0
  68. package/examples/tag-management.ts +534 -0
  69. package/examples/tag-nested-tuple.ts +190 -0
  70. package/examples/tag-simple.ts +149 -0
  71. package/examples/tag-tagger.ts +217 -0
  72. package/examples/test-nested-tuple-conversion.ts +143 -0
  73. package/examples/test-type-bytes-parser.ts +70 -0
  74. package/examples/transfer-domain.ts +197 -0
  75. package/examples/wallet-management.ts +196 -0
  76. package/package.json +24 -15
  77. package/src/abi/RootResolver2ABI.ts +237 -0
  78. package/src/business/index.ts +1490 -0
  79. package/src/business/tag-context.ts +713 -0
  80. package/src/cli.ts +2755 -39
  81. package/src/debug.ts +17 -2
  82. package/src/index.ts +300 -14
  83. package/src/utils/crypto-utils.ts +459 -0
  84. package/src/utils/error-parser.ts +225 -0
  85. package/src/utils/tag-abi-codec.ts +158 -0
  86. package/src/utils/tag-type-builder.ts +469 -0
  87. package/tsconfig.json +1 -1
package/dist/cli.js CHANGED
@@ -1,24 +1,63 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
6
36
  Object.defineProperty(exports, "__esModule", { value: true });
7
- const index_1 = __importDefault(require("./index"));
37
+ const index_1 = __importStar(require("./index"));
8
38
  const debug_1 = require("./debug");
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ // CLI Version - read from package.json
42
+ const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf-8'));
43
+ const CLI_VERSION = packageJson.version;
9
44
  // 预设的网络配置
10
45
  const NETWORKS = {
11
46
  sepolia: {
12
47
  rpc: 'https://sepolia.optimism.io',
13
48
  contractDid: '0xe2D7c3a9013960E04d4E9F5F9B63fff37eEd97A8',
14
49
  contractRootResolver: '0xeF727cb066Fee98F88Db84555830063b4A24ddfc',
15
- contractAbiType: '0x7386fCBae6Ad4CCE1499d9153D99bc950B589718'
50
+ contractAbiType: '0x7386fCBae6Ad4CCE1499d9153D99bc950B589718',
51
+ contractRootResolver2: '0xcbC02aa08c77a374eC0D5A0403E108b7573d96e8',
52
+ supportSvcUrl: 'https://api-test.olares.com/did/support'
16
53
  },
17
54
  mainnet: {
18
55
  rpc: 'https://optimism-rpc.publicnode.com',
19
56
  contractDid: '0x5DA4Fa8E567d86e52Ef8Da860de1be8f54cae97D',
20
57
  contractRootResolver: '0xE2EABA0979277A90511F8873ae1e8cA26B54E740',
21
- contractAbiType: '0x9ae3F16bD99294Af1784beB1a0A5C84bf2636365'
58
+ contractAbiType: '0x9ae3F16bD99294Af1784beB1a0A5C84bf2636365',
59
+ contractRootResolver2: '0x7e7961aB771cA942CE4DB6e79579e016a33Dc95B',
60
+ supportSvcUrl: 'https://api.olares.com/did/support'
22
61
  }
23
62
  };
24
63
  function parseArgs() {
@@ -32,14 +71,25 @@ function parseArgs() {
32
71
  help: false
33
72
  };
34
73
  let command = '';
74
+ let subCommand;
35
75
  let domain;
76
+ let value;
77
+ // Commands that don't have subcommands - next arg is domain directly
78
+ const commandsWithoutSubcommand = [
79
+ 'info',
80
+ 'owner',
81
+ 'is-owner',
82
+ 'transfer',
83
+ 'fetch',
84
+ 'fetch-domain'
85
+ ];
36
86
  for (let i = 0; i < args.length; i++) {
37
87
  const arg = args[i];
38
88
  if (arg === '--help' || arg === '-h') {
39
89
  options.help = true;
40
90
  }
41
91
  else if (arg === '--version' || arg === '-V') {
42
- console.log('0.1.0');
92
+ console.log(CLI_VERSION);
43
93
  process.exit(0);
44
94
  }
45
95
  else if (arg === '--network' || arg === '-n') {
@@ -57,6 +107,21 @@ function parseArgs() {
57
107
  else if (arg === '--contract-abi') {
58
108
  options.contractAbi = args[++i];
59
109
  }
110
+ else if (arg === '--contract-resolver2') {
111
+ options.contractRootResolver2 = args[++i];
112
+ }
113
+ else if (arg === '--support-svc-url') {
114
+ options.supportSvcUrl = args[++i];
115
+ }
116
+ else if (arg === '--output' || arg === '-o') {
117
+ options.output = args[++i];
118
+ }
119
+ else if (arg === '--key-length') {
120
+ options.keyLength = parseInt(args[++i], 10);
121
+ }
122
+ else if (arg === '--words' || arg === '-w') {
123
+ options.words = parseInt(args[++i], 10);
124
+ }
60
125
  else if (arg === '--json' || arg === '-j') {
61
126
  options.json = true;
62
127
  }
@@ -72,28 +137,107 @@ function parseArgs() {
72
137
  else if (!command) {
73
138
  command = arg;
74
139
  }
75
- else if (!domain &&
76
- (command === 'fetch' || command === 'fetch-domain')) {
140
+ else if (!subCommand &&
141
+ !commandsWithoutSubcommand.includes(command)) {
142
+ // Only set subCommand if the command requires one
143
+ subCommand = arg;
144
+ }
145
+ else if (!domain) {
77
146
  domain = arg;
78
147
  }
148
+ else if (!value) {
149
+ value = arg;
150
+ }
79
151
  }
80
- return { command, domain, options };
152
+ return { command, subCommand, domain, value, options };
81
153
  }
82
154
  function showHelp() {
83
155
  console.log(`
84
- DID CLI Tool v0.1.0
156
+ DID CLI Tool v${CLI_VERSION}
85
157
 
86
158
  USAGE:
87
- did-cli <command> [arguments] [options]
159
+ did-cli <command> [subcommand] [arguments] [options]
88
160
 
89
161
  COMMANDS:
90
- fetch <domain> Fetch domain information (alias: fetch-domain)
91
- fetch-all Fetch all domains from contract
92
- config Show network configurations
93
- help Show this help message
94
-
95
- ARGUMENTS:
96
- <domain> Domain name to fetch (e.g., example.olares.com)
162
+ Query Commands:
163
+ info <domain> Get domain metadata
164
+ owner <domain> Get domain owner address
165
+ is-owner <domain> Check if you are the domain owner (requires PRIVATE_KEY_OR_MNEMONIC)
166
+
167
+ RSA Key Commands:
168
+ rsa generate Generate a new RSA key pair
169
+ rsa get <domain> Get RSA public key for domain
170
+ rsa set <domain> <file> Set RSA public key from PEM file (requires PRIVATE_KEY_OR_MNEMONIC)
171
+ rsa remove <domain> Remove RSA public key (requires PRIVATE_KEY_OR_MNEMONIC)
172
+
173
+ IP Commands:
174
+ ip get <domain> Get DNS A record (IPv4)
175
+ ip set <domain> <ip> Set DNS A record (requires PRIVATE_KEY_OR_MNEMONIC)
176
+ ip remove <domain> Remove DNS A record (requires PRIVATE_KEY_OR_MNEMONIC)
177
+
178
+ Subdomain Commands:
179
+ subdomain register <parent> <label>
180
+ Register a new subdomain (requires PRIVATE_KEY_OR_MNEMONIC)
181
+ Use MNEMONIC env var for subdomain owner or auto-generates one
182
+
183
+ Transfer Commands:
184
+ transfer <domain> Transfer domain ownership to a new owner (requires PRIVATE_KEY_OR_MNEMONIC)
185
+ Use MNEMONIC env var for new owner or auto-generates one
186
+
187
+ Wallet Management Commands:
188
+ wallet evm add <domain> Add EVM wallet to domain (requires PRIVATE_KEY_OR_MNEMONIC & EVM_PRIVATE_KEY)
189
+ wallet evm remove <domain> Remove EVM wallet from domain (requires PRIVATE_KEY_OR_MNEMONIC & EVM_PRIVATE_KEY)
190
+ wallet evm list <domain> List all EVM wallets for domain
191
+ wallet solana add <domain> Add Solana wallet to domain (requires PRIVATE_KEY_OR_MNEMONIC & SOLANA_PRIVATE_KEY)
192
+ wallet solana remove <domain>
193
+ Remove Solana wallet from domain (requires PRIVATE_KEY_OR_MNEMONIC & SOLANA_PRIVATE_KEY)
194
+ wallet solana list <domain>
195
+ List all Solana wallets for domain
196
+
197
+ Tag Management Commands:
198
+ tag define <domain> <tag-name> <type>
199
+ Define a new tag type (requires PRIVATE_KEY_OR_MNEMONIC)
200
+ Supported types: string, uint8, uint256, int8, int256, bool, address, bytes, bytes32
201
+ Array types: string[], uint8[], etc.
202
+ tag set <domain> <tag-name> <value>
203
+ Set tag value (requires PRIVATE_KEY_OR_MNEMONIC)
204
+ Value can be a string or JSON for arrays/objects
205
+ tag get <domain> <tag-name>
206
+ Get tag value (read-only)
207
+ tag remove <domain> <tag-name>
208
+ Remove tag value (requires PRIVATE_KEY_OR_MNEMONIC)
209
+ tag list <domain> List all tags with values for domain (read-only)
210
+ tag list-defined <domain> List all defined tag types for domain (read-only)
211
+ tag set-tagger <domain> <tag-name> <address>
212
+ Set tagger address for a tag (requires PRIVATE_KEY_OR_MNEMONIC)
213
+ tag get-tagger <domain> <tag-name>
214
+ Get tagger address for a tag (read-only)
215
+
216
+ Operator Commands:
217
+ operator get Get current operator address
218
+ operator set <address> Set operator address (requires PRIVATE_KEY_OR_MNEMONIC)
219
+
220
+ Crypto Utility Commands:
221
+ crypto generate Generate a new mnemonic phrase (--words option)
222
+ Saves to file, use --output to specify file path
223
+ crypto address Get Ethereum address from mnemonic (requires MNEMONIC env var)
224
+ crypto did Get DID from mnemonic (requires MNEMONIC env var)
225
+ crypto privatekey Get EVM private key from mnemonic (requires MNEMONIC env var)
226
+ Saves to file, use --output to specify file path
227
+ crypto derive Derive all keys from mnemonic (requires MNEMONIC env var)
228
+ Saves to file, use --output to specify file path
229
+
230
+ Utility Commands:
231
+ convert pem-to-der <file> Convert PEM file to DER hex
232
+ convert der-to-pem <hex> Convert DER hex to PEM
233
+ convert ip-to-bytes <ip> Convert IPv4 to bytes4
234
+ convert bytes-to-ip <hex> Convert bytes4 to IPv4
235
+
236
+ Legacy Commands:
237
+ fetch <domain> Fetch domain information (alias: fetch-domain)
238
+ fetch-all Fetch all domains from contract
239
+ config Show network configurations
240
+ help Show this help message
97
241
 
98
242
  OPTIONS:
99
243
  -n, --network <network> Network to use (sepolia|mainnet) [default: sepolia]
@@ -101,6 +245,12 @@ OPTIONS:
101
245
  --contract-did <address> Custom DID contract address
102
246
  --contract-resolver <address> Custom RootResolver contract address
103
247
  --contract-abi <address> Custom ABIType contract address
248
+ --contract-resolver2 <address> Custom RootResolver2 contract address
249
+ --support-svc-url <url> Custom support service URL
250
+ -o, --output <file> Output file path (for generate commands)
251
+ --key-length <bits> RSA key length in bits [default: 2048]
252
+ -w, --words <count> Mnemonic word count: 12|15|18|21|24 [default: 12]
253
+ -j, --json Output in JSON format
104
254
  -v, --verbose Enable verbose debug output
105
255
  --debug Enable debug output
106
256
  --debug-level <level> Set debug level (debug|info|warn|error) [default: info]
@@ -108,12 +258,122 @@ OPTIONS:
108
258
  -V, --version Show version number
109
259
 
110
260
  EXAMPLES:
111
- did-cli fetch example.olares.com
112
- did-cli fetch example.olares.com --network mainnet
113
- did-cli fetch example.olares.com --json
114
- did-cli fetch example.olares.com --debug
115
- did-cli fetch-all --network sepolia
116
- did-cli config
261
+ # Query domain info
262
+ did-cli info example.olares.com --network mainnet
263
+ did-cli owner example.olares.com
264
+ export PRIVATE_KEY_OR_MNEMONIC=0xYOUR_PRIVATE_KEY
265
+ did-cli is-owner example.olares.com
266
+
267
+ # RSA key management
268
+ did-cli rsa generate --output ./my-key.pem --key-length 4096
269
+ did-cli rsa get example.olares.com
270
+ did-cli rsa set example.olares.com ./public-key.pem
271
+ did-cli rsa remove example.olares.com
272
+
273
+ # IP management
274
+ did-cli ip get example.olares.com
275
+ did-cli ip set example.olares.com 192.168.1.100
276
+ did-cli ip remove example.olares.com
277
+
278
+ # Subdomain management (auto-generate mnemonic for subdomain owner)
279
+ export PRIVATE_KEY_OR_MNEMONIC=0xYOUR_PRIVATE_KEY
280
+ did-cli subdomain register parent.com child
281
+ did-cli subdomain register parent.com child --words 24
282
+
283
+ # Subdomain management (use existing mnemonic for subdomain owner)
284
+ export MNEMONIC="your twelve word mnemonic here"
285
+ did-cli subdomain register parent.com child
286
+
287
+ # Subdomain management (JSON output)
288
+ did-cli subdomain register parent.com child --json
289
+
290
+ # Transfer domain ownership (auto-generate mnemonic for new owner)
291
+ export PRIVATE_KEY_OR_MNEMONIC=0xYOUR_PRIVATE_KEY
292
+ did-cli transfer example.com
293
+ did-cli transfer example.com --words 24
294
+
295
+ # Transfer domain ownership (use existing mnemonic for new owner)
296
+ export MNEMONIC="your twelve word mnemonic here"
297
+ did-cli transfer example.com
298
+
299
+ # Crypto utilities
300
+ did-cli crypto generate --words 12
301
+ did-cli crypto generate --words 24 --output ./custom-path.txt
302
+ export MNEMONIC="your twelve word mnemonic here"
303
+ did-cli crypto address
304
+ did-cli crypto did
305
+ did-cli crypto privatekey --output ./my-private-key.txt
306
+ did-cli crypto derive --output ./my-keys.txt
307
+
308
+ # Wallet management
309
+ export PRIVATE_KEY_OR_MNEMONIC=0xYOUR_PRIVATE_KEY
310
+
311
+ # Add EVM wallet
312
+ export EVM_PRIVATE_KEY=0xWALLET_PRIVATE_KEY
313
+ did-cli wallet evm add example.com
314
+
315
+ # Remove EVM wallet
316
+ did-cli wallet evm remove example.com
317
+
318
+ # List EVM wallets
319
+ did-cli wallet evm list example.com
320
+
321
+ # Add Solana wallet (base58 format)
322
+ export SOLANA_PRIVATE_KEY="5J7W..."
323
+ did-cli wallet solana add example.com
324
+
325
+ # Add Solana wallet (JSON array format from Phantom)
326
+ export SOLANA_PRIVATE_KEY='[1,2,3,...]'
327
+ did-cli wallet solana add example.com
328
+
329
+ # List Solana wallets
330
+ did-cli wallet solana list example.com
331
+
332
+ # Tag management
333
+ export PRIVATE_KEY_OR_MNEMONIC=0xYOUR_PRIVATE_KEY
334
+
335
+ # Define a simple tag
336
+ did-cli tag define example.com email string
337
+
338
+ # Set tagger (usually yourself)
339
+ did-cli tag set-tagger example.com email 0xYourAddress
340
+
341
+ # Set tag value
342
+ did-cli tag set example.com email "user@example.com"
343
+
344
+ # Get tag value
345
+ did-cli tag get example.com email
346
+
347
+ # List all tags
348
+ did-cli tag list example.com
349
+
350
+ # Array type (quote to prevent shell interpretation)
351
+ did-cli tag define example.com links "string[]"
352
+ did-cli tag set-tagger example.com links 0xYourAddress
353
+ did-cli tag set example.com links '["https://x.com","https://github.com"]'
354
+
355
+ # Remove tag
356
+ did-cli tag remove example.com email
357
+
358
+ # Operator management
359
+ did-cli operator get
360
+ did-cli operator set 0x1234...
361
+
362
+ # Utilities
363
+ did-cli convert pem-to-der ./public-key.pem
364
+ did-cli convert ip-to-bytes 192.168.1.1
365
+ did-cli convert bytes-to-ip 0xc0a80101
366
+
367
+ ENVIRONMENT VARIABLES:
368
+ PRIVATE_KEY_OR_MNEMONIC Private key (0x...) or mnemonic phrase for signing transactions
369
+ (required for write operations)
370
+ MNEMONIC Mnemonic phrase for generating owner identity
371
+ (used in subdomain registration, domain transfer, and crypto utilities)
372
+ EVM_PRIVATE_KEY EVM wallet private key for wallet management operations
373
+ (required for wallet evm add/remove commands)
374
+ SOLANA_PRIVATE_KEY Solana wallet private key for wallet management operations
375
+ Format: base58 string or JSON array (e.g., "[1,2,3,...]")
376
+ (required for wallet solana add/remove commands)
117
377
  `);
118
378
  }
119
379
  async function fetchDomain(domain, options) {
@@ -169,26 +429,1812 @@ async function fetchDomain(domain, options) {
169
429
  process.exit(1);
170
430
  }
171
431
  }
432
+ // ============================================================================
433
+ // Helper Functions
434
+ // ============================================================================
435
+ function getConsole(options) {
436
+ let config;
437
+ if (options.rpc &&
438
+ options.contractDid &&
439
+ options.contractResolver &&
440
+ options.contractAbi &&
441
+ options.contractRootResolver2 &&
442
+ options.supportSvcUrl) {
443
+ config = {
444
+ rpc: options.rpc,
445
+ contractDid: options.contractDid,
446
+ contractRootResolver: options.contractResolver,
447
+ contractAbiType: options.contractAbi,
448
+ contractRootResolver2: options.contractRootResolver2,
449
+ supportSvcUrl: options.supportSvcUrl
450
+ };
451
+ }
452
+ else if (NETWORKS[options.network]) {
453
+ config = NETWORKS[options.network];
454
+ }
455
+ else {
456
+ throw new Error(`Unknown network: ${options.network}`);
457
+ }
458
+ return index_1.default.createConsole(config.rpc, config.contractDid, config.contractRootResolver, config.contractAbiType, config.contractRootResolver2, config.supportSvcUrl);
459
+ }
460
+ function getPrivateKeyOrMnemonic() {
461
+ const key = process.env.PRIVATE_KEY_OR_MNEMONIC;
462
+ if (!key) {
463
+ console.error('❌ Error: Private key or mnemonic is required for this operation');
464
+ console.error('Please set PRIVATE_KEY_OR_MNEMONIC environment variable');
465
+ console.error('Example: export PRIVATE_KEY_OR_MNEMONIC=0xYOUR_PRIVATE_KEY');
466
+ console.error('Or: export PRIVATE_KEY_OR_MNEMONIC="your twelve word mnemonic phrase here"');
467
+ process.exit(1);
468
+ }
469
+ return key;
470
+ }
471
+ // ============================================================================
472
+ // Domain Info Commands
473
+ // ============================================================================
474
+ async function getDomainInfo(domain, options) {
475
+ try {
476
+ const didConsole = getConsole(options);
477
+ const domainContext = didConsole.domain(domain);
478
+ const metaInfo = await domainContext.getMetaInfo();
479
+ if (options.json) {
480
+ console.log(JSON.stringify(metaInfo, null, 2));
481
+ }
482
+ else {
483
+ console.log('📋 Domain Metadata:');
484
+ console.log(` Name: ${metaInfo.name}`);
485
+ console.log(` DID: ${metaInfo.did}`);
486
+ console.log(` Token ID: ${metaInfo.id}`);
487
+ console.log(` Note: ${metaInfo.note}`);
488
+ console.log(` Allow Subdomain: ${metaInfo.allowSubdomain}`);
489
+ }
490
+ }
491
+ catch (error) {
492
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
493
+ process.exit(1);
494
+ }
495
+ }
496
+ async function getDomainOwner(domain, options) {
497
+ try {
498
+ const didConsole = getConsole(options);
499
+ const domainContext = didConsole.domain(domain);
500
+ const owner = await domainContext.getOwner();
501
+ if (options.json) {
502
+ console.log(JSON.stringify({ owner }, null, 2));
503
+ }
504
+ else {
505
+ console.log(`👤 Owner: ${owner}`);
506
+ }
507
+ }
508
+ catch (error) {
509
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
510
+ process.exit(1);
511
+ }
512
+ }
513
+ async function checkIsOwner(domain, options) {
514
+ try {
515
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
516
+ const didConsole = getConsole(options);
517
+ await didConsole.setSigner(privateKeyOrMnemonic);
518
+ const domainContext = didConsole.domain(domain);
519
+ const isOwner = await domainContext.isOwner();
520
+ if (options.json) {
521
+ console.log(JSON.stringify({ isOwner }, null, 2));
522
+ }
523
+ else {
524
+ console.log(isOwner ? '✅ You are the owner' : '❌ You are not the owner');
525
+ }
526
+ }
527
+ catch (error) {
528
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
529
+ process.exit(1);
530
+ }
531
+ }
532
+ // ============================================================================
533
+ // RSA Key Commands
534
+ // ============================================================================
535
+ async function generateRsaKey(options) {
536
+ try {
537
+ const keyLength = options.keyLength || 2048;
538
+ const keyPair = await (0, index_1.createRsaKeyPair)(keyLength);
539
+ if (options.output) {
540
+ // Save to files
541
+ const publicKeyFile = options.output;
542
+ const privateKeyFile = options.output.replace(/\.pem$/, '-private.pem');
543
+ fs.writeFileSync(publicKeyFile, keyPair.rsaPublicKey);
544
+ fs.writeFileSync(privateKeyFile, keyPair.rsaPrivateKey);
545
+ console.log(`✅ RSA key pair generated (${keyLength} bits)`);
546
+ console.log(`📄 Public key: ${publicKeyFile}`);
547
+ console.log(`🔐 Private key: ${privateKeyFile}`);
548
+ }
549
+ else {
550
+ // When no output file is specified, still save to default files for security
551
+ const defaultPublicFile = './rsa-public.pem';
552
+ const defaultPrivateFile = './rsa-private.pem';
553
+ fs.writeFileSync(defaultPublicFile, keyPair.rsaPublicKey);
554
+ fs.writeFileSync(defaultPrivateFile, keyPair.rsaPrivateKey);
555
+ if (options.json) {
556
+ console.log(JSON.stringify({
557
+ keyLength: keyLength,
558
+ publicKeyFile: defaultPublicFile,
559
+ privateKeyFile: defaultPrivateFile
560
+ }, null, 2));
561
+ }
562
+ else {
563
+ console.log(`✅ RSA key pair generated (${keyLength} bits)`);
564
+ console.log(`📄 Public key: ${defaultPublicFile}`);
565
+ console.log(`🔐 Private key: ${defaultPrivateFile}`);
566
+ console.log('\n⚠️ SECURITY WARNING:');
567
+ console.log(' • Keep the private key secure! Never share it!');
568
+ console.log(' • Delete the file after copying to a secure location');
569
+ console.log(` • Command: rm ${defaultPrivateFile}`);
570
+ }
571
+ }
572
+ }
573
+ catch (error) {
574
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
575
+ process.exit(1);
576
+ }
577
+ }
578
+ async function getRsaKey(domain, options) {
579
+ try {
580
+ const didConsole = getConsole(options);
581
+ const domainContext = didConsole.domain(domain);
582
+ const rsaKey = await domainContext.getRSAPublicKey();
583
+ if (!rsaKey) {
584
+ console.log('❌ No RSA public key set for this domain');
585
+ process.exit(1);
586
+ }
587
+ if (options.json) {
588
+ console.log(JSON.stringify({ rsaPublicKey: rsaKey }, null, 2));
589
+ }
590
+ else {
591
+ console.log('📄 RSA Public Key:');
592
+ console.log(rsaKey);
593
+ }
594
+ }
595
+ catch (error) {
596
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
597
+ process.exit(1);
598
+ }
599
+ }
600
+ async function setRsaKey(domain, pemFile, options) {
601
+ try {
602
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
603
+ const didConsole = getConsole(options);
604
+ await didConsole.setSigner(privateKeyOrMnemonic);
605
+ // Read PEM file
606
+ if (!fs.existsSync(pemFile)) {
607
+ console.error(`❌ Error: File not found: ${pemFile}`);
608
+ process.exit(1);
609
+ }
610
+ const rsaPublicKey = fs.readFileSync(pemFile, 'utf-8');
611
+ const domainContext = didConsole.domain(domain);
612
+ const result = await domainContext.setRSAPublicKey(rsaPublicKey);
613
+ if (result.success) {
614
+ console.log('✅ RSA public key set successfully');
615
+ console.log(`📝 Transaction: ${result.transactionHash}`);
616
+ if (result.gasUsed) {
617
+ console.log(`⛽ Gas used: ${result.gasUsed.toString()}`);
618
+ }
619
+ }
620
+ else {
621
+ console.error(`❌ Failed: ${result.error}`);
622
+ process.exit(1);
623
+ }
624
+ }
625
+ catch (error) {
626
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
627
+ process.exit(1);
628
+ }
629
+ }
630
+ async function removeRsaKey(domain, options) {
631
+ try {
632
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
633
+ const didConsole = getConsole(options);
634
+ await didConsole.setSigner(privateKeyOrMnemonic);
635
+ const domainContext = didConsole.domain(domain);
636
+ const result = await domainContext.removeRSAPublicKey();
637
+ if (result.success) {
638
+ console.log('✅ RSA public key removed successfully');
639
+ console.log(`📝 Transaction: ${result.transactionHash}`);
640
+ if (result.gasUsed) {
641
+ console.log(`⛽ Gas used: ${result.gasUsed.toString()}`);
642
+ }
643
+ }
644
+ else {
645
+ console.error(`❌ Failed: ${result.error}`);
646
+ process.exit(1);
647
+ }
648
+ }
649
+ catch (error) {
650
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
651
+ process.exit(1);
652
+ }
653
+ }
654
+ // ============================================================================
655
+ // IP Commands
656
+ // ============================================================================
657
+ async function getIP(domain, options) {
658
+ try {
659
+ const didConsole = getConsole(options);
660
+ const domainContext = didConsole.domain(domain);
661
+ const ip = await domainContext.getIP();
662
+ if (!ip) {
663
+ console.log('❌ No IP address set for this domain');
664
+ process.exit(1);
665
+ }
666
+ if (options.json) {
667
+ console.log(JSON.stringify({ ip }, null, 2));
668
+ }
669
+ else {
670
+ console.log(`🌐 IP Address: ${ip}`);
671
+ }
672
+ }
673
+ catch (error) {
674
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
675
+ process.exit(1);
676
+ }
677
+ }
678
+ async function setIP(domain, ip, options) {
679
+ try {
680
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
681
+ const didConsole = getConsole(options);
682
+ await didConsole.setSigner(privateKeyOrMnemonic);
683
+ const domainContext = didConsole.domain(domain);
684
+ const result = await domainContext.setIP(ip);
685
+ if (result.success) {
686
+ console.log(`✅ IP address set to ${ip}`);
687
+ console.log(`📝 Transaction: ${result.transactionHash}`);
688
+ if (result.gasUsed) {
689
+ console.log(`⛽ Gas used: ${result.gasUsed.toString()}`);
690
+ }
691
+ }
692
+ else {
693
+ console.error(`❌ Failed: ${result.error}`);
694
+ process.exit(1);
695
+ }
696
+ }
697
+ catch (error) {
698
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
699
+ process.exit(1);
700
+ }
701
+ }
702
+ async function removeIP(domain, options) {
703
+ try {
704
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
705
+ const didConsole = getConsole(options);
706
+ await didConsole.setSigner(privateKeyOrMnemonic);
707
+ const domainContext = didConsole.domain(domain);
708
+ const result = await domainContext.removeIP();
709
+ if (result.success) {
710
+ console.log('✅ IP address removed successfully');
711
+ console.log(`📝 Transaction: ${result.transactionHash}`);
712
+ if (result.gasUsed) {
713
+ console.log(`⛽ Gas used: ${result.gasUsed.toString()}`);
714
+ }
715
+ }
716
+ else {
717
+ console.error(`❌ Failed: ${result.error}`);
718
+ process.exit(1);
719
+ }
720
+ }
721
+ catch (error) {
722
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
723
+ process.exit(1);
724
+ }
725
+ }
726
+ // ============================================================================
727
+ // Operator Commands
728
+ // ============================================================================
729
+ async function getOperator(options) {
730
+ try {
731
+ const didConsole = getConsole(options);
732
+ const operator = await didConsole.getOperator();
733
+ if (options.json) {
734
+ console.log(JSON.stringify({ operator }, null, 2));
735
+ }
736
+ else {
737
+ console.log(`👔 Operator: ${operator}`);
738
+ }
739
+ }
740
+ catch (error) {
741
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
742
+ process.exit(1);
743
+ }
744
+ }
745
+ async function setOperator(address, options) {
746
+ try {
747
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
748
+ const didConsole = getConsole(options);
749
+ await didConsole.setSigner(privateKeyOrMnemonic);
750
+ const result = await didConsole.setOperator(address);
751
+ if (result.success) {
752
+ console.log(`✅ Operator set to ${address}`);
753
+ console.log(`📝 Transaction: ${result.transactionHash}`);
754
+ if (result.gasUsed) {
755
+ console.log(`⛽ Gas used: ${result.gasUsed.toString()}`);
756
+ }
757
+ }
758
+ else {
759
+ console.error(`❌ Failed: ${result.error}`);
760
+ process.exit(1);
761
+ }
762
+ }
763
+ catch (error) {
764
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
765
+ process.exit(1);
766
+ }
767
+ }
768
+ // ============================================================================
769
+ // Conversion Utilities
770
+ // ============================================================================
771
+ function convertPemToDer(pemFile, options) {
772
+ try {
773
+ if (!fs.existsSync(pemFile)) {
774
+ console.error(`❌ Error: File not found: ${pemFile}`);
775
+ process.exit(1);
776
+ }
777
+ const pem = fs.readFileSync(pemFile, 'utf-8');
778
+ const der = (0, index_1.pemToDer)(pem);
779
+ if (options.json) {
780
+ console.log(JSON.stringify({ der }, null, 2));
781
+ }
782
+ else {
783
+ console.log('🔄 DER Hex:');
784
+ console.log(der);
785
+ }
786
+ }
787
+ catch (error) {
788
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
789
+ process.exit(1);
790
+ }
791
+ }
792
+ function convertDerToPem(derHex, options) {
793
+ try {
794
+ const pem = (0, index_1.derToPem)(derHex);
795
+ if (options.json) {
796
+ console.log(JSON.stringify({ pem }, null, 2));
797
+ }
798
+ else {
799
+ console.log('🔄 PEM:');
800
+ console.log(pem);
801
+ }
802
+ }
803
+ catch (error) {
804
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
805
+ process.exit(1);
806
+ }
807
+ }
808
+ function convertIpToBytes(ip, options) {
809
+ try {
810
+ const bytes = (0, index_1.ipv4ToBytes4)(ip);
811
+ if (options.json) {
812
+ console.log(JSON.stringify({ ip, bytes }, null, 2));
813
+ }
814
+ else {
815
+ console.log(`🔄 ${ip} → ${bytes}`);
816
+ }
817
+ }
818
+ catch (error) {
819
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
820
+ process.exit(1);
821
+ }
822
+ }
823
+ function convertBytesToIp(bytes, options) {
824
+ try {
825
+ const ip = (0, index_1.bytes4ToIpv4)(bytes);
826
+ if (options.json) {
827
+ console.log(JSON.stringify({ bytes, ip }, null, 2));
828
+ }
829
+ else {
830
+ console.log(`🔄 ${bytes} → ${ip}`);
831
+ }
832
+ }
833
+ catch (error) {
834
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
835
+ process.exit(1);
836
+ }
837
+ }
838
+ // ============================================================================
839
+ // Subdomain Commands
840
+ // ============================================================================
841
+ async function registerSubdomain(parentDomain, subdomain, options) {
842
+ try {
843
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
844
+ const didConsole = getConsole(options);
845
+ // Initialize with signer
846
+ await didConsole.setSigner(privateKeyOrMnemonic);
847
+ const domain = didConsole.domain(parentDomain);
848
+ // Get or generate mnemonic for subdomain owner
849
+ let mnemonic;
850
+ const subdomainMnemonic = process.env.MNEMONIC;
851
+ if (subdomainMnemonic) {
852
+ mnemonic = subdomainMnemonic;
853
+ console.log('📝 Using mnemonic from MNEMONIC environment variable');
854
+ }
855
+ else {
856
+ const wordCount = options.words || 12;
857
+ if (![12, 15, 18, 21, 24].includes(wordCount)) {
858
+ console.error('❌ Error: Word count must be one of: 12, 15, 18, 21, 24');
859
+ process.exit(1);
860
+ }
861
+ mnemonic = (0, index_1.generateMnemonic)(wordCount);
862
+ // Save mnemonic to file
863
+ const mnemonicFile = './subdomain-mnemonic.txt';
864
+ fs.writeFileSync(mnemonicFile, mnemonic, 'utf-8');
865
+ console.log(`🔑 Generated ${wordCount}-word mnemonic for subdomain owner`);
866
+ console.log(`📄 Mnemonic saved to: ${mnemonicFile}`);
867
+ console.log('\n⚠️ SECURITY WARNING:');
868
+ console.log(' • Keep this mnemonic secure! It controls the subdomain!');
869
+ console.log(' • Store it in a safe place (paper backup, hardware wallet, etc.)');
870
+ console.log(' • Delete the file after copying to a secure location');
871
+ console.log(` • Command: rm ${mnemonicFile}`);
872
+ console.log('\n💡 To use this mnemonic for future operations:');
873
+ console.log(` export MNEMONIC="$(cat ${mnemonicFile})"\n`);
874
+ }
875
+ // Register subdomain
876
+ console.log(`📋 Registering subdomain: ${subdomain}.${parentDomain}`);
877
+ console.log('⏳ Submitting transaction...\n');
878
+ const result = await domain.registerSubdomain(subdomain, mnemonic);
879
+ if (result.success) {
880
+ if (options.json) {
881
+ console.log(JSON.stringify({
882
+ success: true,
883
+ subdomain: result.data.subdomain,
884
+ fullDomainName: result.data.fullDomainName,
885
+ owner: result.data.owner,
886
+ did: result.data.did,
887
+ transactionHash: result.transactionHash,
888
+ gasUsed: result.gasUsed?.toString(),
889
+ blockNumber: result.blockNumber
890
+ }, null, 2));
891
+ }
892
+ else {
893
+ console.log('✅ Subdomain registered successfully!\n');
894
+ console.log('═'.repeat(60));
895
+ console.log('Registration Details:');
896
+ console.log('═'.repeat(60));
897
+ console.log(`Subdomain label: ${result.data.subdomain}`);
898
+ console.log(`Full domain name: ${result.data.fullDomainName}`);
899
+ console.log(`Owner address: ${result.data.owner}`);
900
+ console.log(`DID: ${result.data.did}`);
901
+ console.log(`Transaction hash: ${result.transactionHash}`);
902
+ console.log(`Gas used: ${result.gasUsed?.toString() || 'N/A'}`);
903
+ console.log(`Block number: ${result.blockNumber || 'N/A'}`);
904
+ console.log('═'.repeat(60));
905
+ const explorerUrl = options.network === 'mainnet'
906
+ ? `https://optimistic.etherscan.io/tx/${result.transactionHash}`
907
+ : `https://sepolia-optimism.etherscan.io/tx/${result.transactionHash}`;
908
+ console.log(`\n🔗 View on block explorer:`);
909
+ console.log(` ${explorerUrl}\n`);
910
+ }
911
+ }
912
+ else {
913
+ console.error('❌ Subdomain registration failed!');
914
+ console.error(` Error: ${result.error}`);
915
+ process.exit(1);
916
+ }
917
+ }
918
+ catch (error) {
919
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
920
+ if (options.debug && error instanceof Error && error.stack) {
921
+ console.error('\nStack trace:');
922
+ console.error(error.stack);
923
+ }
924
+ process.exit(1);
925
+ }
926
+ }
927
+ /**
928
+ * Transfer domain ownership to a new owner
929
+ */
930
+ async function transferDomain(domain, options) {
931
+ try {
932
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
933
+ const didConsole = getConsole(options);
934
+ // Initialize with current owner's signer
935
+ await didConsole.setSigner(privateKeyOrMnemonic);
936
+ const domainContext = didConsole.domain(domain);
937
+ // Get or generate mnemonic for new owner
938
+ let mnemonic;
939
+ const newOwnerMnemonic = process.env.MNEMONIC;
940
+ if (newOwnerMnemonic) {
941
+ mnemonic = newOwnerMnemonic;
942
+ console.log('📝 Using mnemonic from MNEMONIC environment variable for new owner');
943
+ }
944
+ else {
945
+ const wordCount = options.words || 12;
946
+ if (![12, 15, 18, 21, 24].includes(wordCount)) {
947
+ console.error('❌ Error: Word count must be one of: 12, 15, 18, 21, 24');
948
+ process.exit(1);
949
+ }
950
+ mnemonic = (0, index_1.generateMnemonic)(wordCount);
951
+ // Save mnemonic to file
952
+ const mnemonicFile = './transfer-new-owner-mnemonic.txt';
953
+ fs.writeFileSync(mnemonicFile, mnemonic, 'utf-8');
954
+ console.log(`🔑 Generated ${wordCount}-word mnemonic for new owner`);
955
+ console.log(`📄 Mnemonic saved to: ${mnemonicFile}`);
956
+ console.log('\n⚠️ SECURITY WARNING:');
957
+ console.log(' • Keep this mnemonic secure! It controls the domain!');
958
+ console.log(' • Store it in a safe place (paper backup, hardware wallet, etc.)');
959
+ console.log(' • Delete the file after copying to a secure location');
960
+ console.log(` • Command: rm ${mnemonicFile}`);
961
+ console.log('\n💡 To use this mnemonic for future operations:');
962
+ console.log(` export MNEMONIC="$(cat ${mnemonicFile})"\n`);
963
+ }
964
+ // Transfer domain
965
+ console.log(`📋 Transferring domain: ${domain}`);
966
+ console.log('⏳ Submitting transactions...\n');
967
+ const result = await domainContext.transfer(mnemonic);
968
+ if (result.success) {
969
+ if (options.json) {
970
+ console.log(JSON.stringify({
971
+ success: true,
972
+ domain: domain,
973
+ newOwner: result.data.newOwner,
974
+ newDid: result.data.newDid,
975
+ transferTxHash: result.data.transferTxHash,
976
+ setDidTxHash: result.data.setDidTxHash
977
+ }, null, 2));
978
+ }
979
+ else {
980
+ console.log('✅ Domain transfer successful!\n');
981
+ console.log('Transaction Details:');
982
+ console.log(' Domain:', domain);
983
+ console.log(' New Owner:', result.data.newOwner);
984
+ console.log(' New DID:', result.data.newDid);
985
+ console.log(' Transfer Tx:', result.data.transferTxHash);
986
+ console.log(' Set DID Tx:', result.data.setDidTxHash);
987
+ if (!newOwnerMnemonic) {
988
+ console.log('\n📝 New owner mnemonic saved to: ./transfer-new-owner-mnemonic.txt');
989
+ }
990
+ }
991
+ }
992
+ else {
993
+ console.error('❌ Transfer failed:', result.error);
994
+ process.exit(1);
995
+ }
996
+ }
997
+ catch (error) {
998
+ console.error('❌ Failed:', error);
999
+ if (error instanceof Error) {
1000
+ console.error(' Message:', error.message);
1001
+ }
1002
+ process.exit(1);
1003
+ }
1004
+ }
1005
+ /**
1006
+ * Crypto utility: Generate mnemonic
1007
+ */
1008
+ async function cryptoGenerate(options) {
1009
+ try {
1010
+ const wordCount = options.words || 12;
1011
+ if (![12, 15, 18, 21, 24].includes(wordCount)) {
1012
+ console.error('❌ Error: Word count must be one of: 12, 15, 18, 21, 24');
1013
+ process.exit(1);
1014
+ }
1015
+ const mnemonic = (0, index_1.generateMnemonic)(wordCount);
1016
+ // Save mnemonic to file
1017
+ const outputFile = options.output || './mnemonic.txt';
1018
+ fs.writeFileSync(outputFile, mnemonic, 'utf-8');
1019
+ if (options.json) {
1020
+ console.log(JSON.stringify({
1021
+ words: wordCount,
1022
+ savedTo: outputFile
1023
+ }, null, 2));
1024
+ }
1025
+ else {
1026
+ console.log(`🔑 Generated ${wordCount}-word mnemonic`);
1027
+ console.log(`📄 Mnemonic saved to: ${outputFile}`);
1028
+ console.log('\n⚠️ SECURITY WARNING:');
1029
+ console.log(' • Keep this mnemonic secure! It controls all derived keys!');
1030
+ console.log(' • Store it in a safe place (paper backup, hardware wallet, etc.)');
1031
+ console.log(' • Delete the file after copying to a secure location');
1032
+ console.log(` • Command: rm ${outputFile}`);
1033
+ console.log('\n💡 To use the mnemonic:');
1034
+ console.log(` export MNEMONIC="$(cat ${outputFile})"`);
1035
+ }
1036
+ }
1037
+ catch (error) {
1038
+ console.error('❌ Failed:', error);
1039
+ if (error instanceof Error) {
1040
+ console.error(' Message:', error.message);
1041
+ }
1042
+ process.exit(1);
1043
+ }
1044
+ }
1045
+ /**
1046
+ * Get mnemonic from environment variable
1047
+ */
1048
+ function getMnemonic() {
1049
+ const mnemonic = process.env.MNEMONIC;
1050
+ if (!mnemonic) {
1051
+ console.error('❌ Error: MNEMONIC environment variable is required');
1052
+ console.error('Please set MNEMONIC environment variable');
1053
+ console.error('Example: export MNEMONIC="your twelve word mnemonic phrase here"');
1054
+ console.error('\n⚠️ Important: Always use quotes for mnemonic phrases!');
1055
+ process.exit(1);
1056
+ }
1057
+ return mnemonic;
1058
+ }
1059
+ /**
1060
+ * Crypto utility: Get Ethereum address from mnemonic
1061
+ */
1062
+ async function cryptoGetAddress(options) {
1063
+ try {
1064
+ const mnemonic = getMnemonic();
1065
+ const address = await (0, index_1.getEthereumAddressFromMnemonic)(mnemonic);
1066
+ if (options.json) {
1067
+ console.log(JSON.stringify({
1068
+ address: address
1069
+ }, null, 2));
1070
+ }
1071
+ else {
1072
+ console.log('🏠 Ethereum Address:');
1073
+ console.log(` ${address}`);
1074
+ }
1075
+ }
1076
+ catch (error) {
1077
+ console.error('❌ Failed:', error);
1078
+ if (error instanceof Error) {
1079
+ console.error(' Message:', error.message);
1080
+ }
1081
+ process.exit(1);
1082
+ }
1083
+ }
1084
+ /**
1085
+ * Crypto utility: Get DID from mnemonic
1086
+ */
1087
+ async function cryptoGetDID(options) {
1088
+ try {
1089
+ const mnemonic = getMnemonic();
1090
+ const did = await (0, index_1.getDIDFromMnemonic)(mnemonic);
1091
+ if (options.json) {
1092
+ console.log(JSON.stringify({
1093
+ did: did
1094
+ }, null, 2));
1095
+ }
1096
+ else {
1097
+ console.log('🆔 DID:');
1098
+ console.log(` ${did}`);
1099
+ }
1100
+ }
1101
+ catch (error) {
1102
+ console.error('❌ Failed:', error);
1103
+ if (error instanceof Error) {
1104
+ console.error(' Message:', error.message);
1105
+ }
1106
+ process.exit(1);
1107
+ }
1108
+ }
1109
+ /**
1110
+ * Crypto utility: Get EVM private key from mnemonic
1111
+ */
1112
+ async function cryptoGetPrivateKey(options) {
1113
+ try {
1114
+ const mnemonic = getMnemonic();
1115
+ const privateKey = await (0, index_1.getEVMPrivateKeyFromMnemonic)(mnemonic);
1116
+ // Save private key to file
1117
+ const outputFile = options.output || './private-key.txt';
1118
+ fs.writeFileSync(outputFile, privateKey, 'utf-8');
1119
+ if (options.json) {
1120
+ console.log(JSON.stringify({
1121
+ savedTo: outputFile
1122
+ }, null, 2));
1123
+ }
1124
+ else {
1125
+ console.log('🔑 EVM Private Key generated');
1126
+ console.log(`📄 Private key saved to: ${outputFile}`);
1127
+ console.log('\n⚠️ SECURITY WARNING:');
1128
+ console.log(' • Keep this private key secure! Never share it!');
1129
+ console.log(' • Delete the file after copying to a secure location');
1130
+ console.log(` • Command: rm ${outputFile}`);
1131
+ }
1132
+ }
1133
+ catch (error) {
1134
+ console.error('❌ Failed:', error);
1135
+ if (error instanceof Error) {
1136
+ console.error(' Message:', error.message);
1137
+ }
1138
+ process.exit(1);
1139
+ }
1140
+ }
1141
+ /**
1142
+ * Crypto utility: Derive all keys from mnemonic
1143
+ */
1144
+ async function cryptoDerive(options) {
1145
+ try {
1146
+ const mnemonic = getMnemonic();
1147
+ const { owner, did } = await (0, index_1.deriveDIDFromMnemonic)(mnemonic);
1148
+ const privateKey = await (0, index_1.getEVMPrivateKeyFromMnemonic)(mnemonic);
1149
+ // Save all keys to file
1150
+ const outputFile = options.output || './derived-keys.txt';
1151
+ const fileContent = `Ethereum Address: ${owner}\nDID: ${did}\nPrivate Key: ${privateKey}`;
1152
+ fs.writeFileSync(outputFile, fileContent, 'utf-8');
1153
+ if (options.json) {
1154
+ console.log(JSON.stringify({
1155
+ address: owner,
1156
+ did: did,
1157
+ savedTo: outputFile
1158
+ }, null, 2));
1159
+ }
1160
+ else {
1161
+ console.log('🔐 Derived Keys:');
1162
+ console.log(' Address:', owner);
1163
+ console.log(' DID:', did);
1164
+ console.log(`\n📄 All keys saved to: ${outputFile}`);
1165
+ console.log('\n⚠️ SECURITY WARNING:');
1166
+ console.log(' • Keep these credentials secure! Never share them!');
1167
+ console.log(' • Private key included in file - handle with extreme care!');
1168
+ console.log(' • Delete the file after copying to a secure location');
1169
+ console.log(` • Command: rm ${outputFile}`);
1170
+ }
1171
+ }
1172
+ catch (error) {
1173
+ console.error('❌ Failed:', error);
1174
+ if (error instanceof Error) {
1175
+ console.error(' Message:', error.message);
1176
+ }
1177
+ process.exit(1);
1178
+ }
1179
+ }
1180
+ // ============================================================================
1181
+ // Wallet Management Commands
1182
+ // ============================================================================
1183
+ async function walletEvm(action, domain, options) {
1184
+ try {
1185
+ const didConsole = getConsole(options);
1186
+ const domainContext = didConsole.domain(domain);
1187
+ switch (action) {
1188
+ case 'add': {
1189
+ const evmPrivateKey = process.env.EVM_PRIVATE_KEY;
1190
+ if (!evmPrivateKey) {
1191
+ console.error('❌ Error: EVM_PRIVATE_KEY environment variable is required');
1192
+ console.error(' Set it with: export EVM_PRIVATE_KEY="0x..."');
1193
+ process.exit(1);
1194
+ }
1195
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
1196
+ await didConsole.setSigner(privateKeyOrMnemonic);
1197
+ console.log(`\n💼 Adding EVM wallet to domain: ${domain}`);
1198
+ const result = await domainContext.addEVMWallet(evmPrivateKey);
1199
+ if (result.success) {
1200
+ if (options.json) {
1201
+ console.log(JSON.stringify({
1202
+ success: true,
1203
+ domain,
1204
+ address: result.data?.address,
1205
+ transactionHash: result.transactionHash,
1206
+ gasUsed: result.gasUsed?.toString(),
1207
+ blockNumber: result.blockNumber
1208
+ }, null, 2));
1209
+ }
1210
+ else {
1211
+ console.log(`\n✅ EVM wallet added successfully!`);
1212
+ console.log(` Address: ${result.data?.address}`);
1213
+ console.log(` Transaction: ${result.transactionHash}`);
1214
+ console.log(` Gas used: ${result.gasUsed?.toString()}`);
1215
+ }
1216
+ }
1217
+ else {
1218
+ console.error(`\n❌ Failed: ${result.error}`);
1219
+ process.exit(1);
1220
+ }
1221
+ break;
1222
+ }
1223
+ case 'remove': {
1224
+ const evmPrivateKey = process.env.EVM_PRIVATE_KEY;
1225
+ if (!evmPrivateKey) {
1226
+ console.error('❌ Error: EVM_PRIVATE_KEY environment variable is required');
1227
+ console.error(' Set it with: export EVM_PRIVATE_KEY="0x..."');
1228
+ process.exit(1);
1229
+ }
1230
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
1231
+ await didConsole.setSigner(privateKeyOrMnemonic);
1232
+ console.log(`\n🗑️ Removing EVM wallet from domain: ${domain}`);
1233
+ const result = await domainContext.removeEVMWallet(evmPrivateKey);
1234
+ if (result.success) {
1235
+ if (options.json) {
1236
+ console.log(JSON.stringify({
1237
+ success: true,
1238
+ domain,
1239
+ address: result.data?.address,
1240
+ transactionHash: result.transactionHash,
1241
+ gasUsed: result.gasUsed?.toString(),
1242
+ blockNumber: result.blockNumber
1243
+ }, null, 2));
1244
+ }
1245
+ else {
1246
+ console.log(`\n✅ EVM wallet removed successfully!`);
1247
+ console.log(` Address: ${result.data?.address}`);
1248
+ console.log(` Transaction: ${result.transactionHash}`);
1249
+ }
1250
+ }
1251
+ else {
1252
+ console.error(`\n❌ Failed: ${result.error}`);
1253
+ process.exit(1);
1254
+ }
1255
+ break;
1256
+ }
1257
+ case 'list': {
1258
+ console.log(`\n📋 Listing EVM wallets for domain: ${domain}`);
1259
+ const wallets = await domainContext.getEVMWallets();
1260
+ if (options.json) {
1261
+ console.log(JSON.stringify({
1262
+ domain,
1263
+ wallets,
1264
+ count: wallets.length
1265
+ }, null, 2));
1266
+ }
1267
+ else {
1268
+ if (wallets.length === 0) {
1269
+ console.log(` No EVM wallets found`);
1270
+ }
1271
+ else {
1272
+ console.log(` Found ${wallets.length} wallet(s):`);
1273
+ wallets.forEach((addr, i) => {
1274
+ console.log(` ${i + 1}. ${addr}`);
1275
+ });
1276
+ }
1277
+ }
1278
+ break;
1279
+ }
1280
+ default:
1281
+ console.error(`❌ Unknown action: ${action}`);
1282
+ console.error(' Valid actions: add, remove, list');
1283
+ process.exit(1);
1284
+ }
1285
+ }
1286
+ catch (error) {
1287
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
1288
+ process.exit(1);
1289
+ }
1290
+ }
1291
+ async function walletSolana(action, domain, options) {
1292
+ try {
1293
+ const didConsole = getConsole(options);
1294
+ const domainContext = didConsole.domain(domain);
1295
+ switch (action) {
1296
+ case 'add': {
1297
+ const solanaPrivateKey = process.env.SOLANA_PRIVATE_KEY;
1298
+ if (!solanaPrivateKey) {
1299
+ console.error('❌ Error: SOLANA_PRIVATE_KEY environment variable is required');
1300
+ console.error(' Set it with: export SOLANA_PRIVATE_KEY="[1,2,3,...]"');
1301
+ console.error(' Or: export SOLANA_PRIVATE_KEY="base58string"');
1302
+ process.exit(1);
1303
+ }
1304
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
1305
+ await didConsole.setSigner(privateKeyOrMnemonic);
1306
+ console.log(`\n💼 Adding Solana wallet to domain: ${domain}`);
1307
+ const result = await domainContext.addSolanaWallet(solanaPrivateKey);
1308
+ if (result.success) {
1309
+ if (options.json) {
1310
+ console.log(JSON.stringify({
1311
+ success: true,
1312
+ domain,
1313
+ address: result.data?.address,
1314
+ addressHex: result.data?.addressHex,
1315
+ transactionHash: result.transactionHash,
1316
+ gasUsed: result.gasUsed?.toString(),
1317
+ blockNumber: result.blockNumber
1318
+ }, null, 2));
1319
+ }
1320
+ else {
1321
+ console.log(`\n✅ Solana wallet added successfully!`);
1322
+ console.log(` Address: ${result.data?.address}`);
1323
+ console.log(` Transaction: ${result.transactionHash}`);
1324
+ console.log(` Gas used: ${result.gasUsed?.toString()}`);
1325
+ }
1326
+ }
1327
+ else {
1328
+ console.error(`\n❌ Failed: ${result.error}`);
1329
+ process.exit(1);
1330
+ }
1331
+ break;
1332
+ }
1333
+ case 'remove': {
1334
+ const solanaPrivateKey = process.env.SOLANA_PRIVATE_KEY;
1335
+ if (!solanaPrivateKey) {
1336
+ console.error('❌ Error: SOLANA_PRIVATE_KEY environment variable is required');
1337
+ console.error(' Set it with: export SOLANA_PRIVATE_KEY="[1,2,3,...]"');
1338
+ console.error(' Or: export SOLANA_PRIVATE_KEY="base58string"');
1339
+ process.exit(1);
1340
+ }
1341
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
1342
+ await didConsole.setSigner(privateKeyOrMnemonic);
1343
+ console.log(`\n🗑️ Removing Solana wallet from domain: ${domain}`);
1344
+ const result = await domainContext.removeSolanaWallet(solanaPrivateKey);
1345
+ if (result.success) {
1346
+ if (options.json) {
1347
+ console.log(JSON.stringify({
1348
+ success: true,
1349
+ domain,
1350
+ address: result.data?.address,
1351
+ addressHex: result.data?.addressHex,
1352
+ transactionHash: result.transactionHash,
1353
+ gasUsed: result.gasUsed?.toString(),
1354
+ blockNumber: result.blockNumber
1355
+ }, null, 2));
1356
+ }
1357
+ else {
1358
+ console.log(`\n✅ Solana wallet removed successfully!`);
1359
+ console.log(` Address: ${result.data?.address}`);
1360
+ console.log(` Transaction: ${result.transactionHash}`);
1361
+ }
1362
+ }
1363
+ else {
1364
+ console.error(`\n❌ Failed: ${result.error}`);
1365
+ process.exit(1);
1366
+ }
1367
+ break;
1368
+ }
1369
+ case 'list': {
1370
+ console.log(`\n📋 Listing Solana wallets for domain: ${domain}`);
1371
+ const wallets = await domainContext.getSolanaWallets();
1372
+ if (options.json) {
1373
+ console.log(JSON.stringify({
1374
+ domain,
1375
+ wallets,
1376
+ count: wallets.length
1377
+ }, null, 2));
1378
+ }
1379
+ else {
1380
+ if (wallets.length === 0) {
1381
+ console.log(` No Solana wallets found`);
1382
+ }
1383
+ else {
1384
+ console.log(` Found ${wallets.length} wallet(s):`);
1385
+ wallets.forEach((addr, i) => {
1386
+ console.log(` ${i + 1}. ${addr}`);
1387
+ });
1388
+ }
1389
+ }
1390
+ break;
1391
+ }
1392
+ default:
1393
+ console.error(`❌ Unknown action: ${action}`);
1394
+ console.error(' Valid actions: add, remove, list');
1395
+ process.exit(1);
1396
+ }
1397
+ }
1398
+ catch (error) {
1399
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
1400
+ process.exit(1);
1401
+ }
1402
+ }
1403
+ // ========================================
1404
+ // Tag Management Functions
1405
+ // ========================================
1406
+ /**
1407
+ * Define a simple tag type
1408
+ */
1409
+ async function tagDefine(domain, tagName, typeString, options) {
1410
+ try {
1411
+ const didConsole = getConsole(options);
1412
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
1413
+ await didConsole.setSigner(privateKeyOrMnemonic);
1414
+ const domainContext = didConsole.domain(domain);
1415
+ const tagCtx = domainContext.tag();
1416
+ console.log(`\n📝 Defining tag "${tagName}" for domain: ${domain}`);
1417
+ console.log(` Type: ${typeString}`);
1418
+ // Parse type string and create TagTypeBuilder
1419
+ let tagType;
1420
+ // Support simple types: string, uint8, uint256, int8, int256, bool, address, bytes, bytes32
1421
+ // Match pattern: (type)(size)(array)?
1422
+ // Examples: uint8, string[], bytes32[]
1423
+ const match = typeString.match(/^(uint|int|bytes|string|bool|address)(\d*)(\[\])?$/);
1424
+ if (!match) {
1425
+ throw new Error(`Invalid type string: ${typeString}. Supported: string, uint8, uint256, int8, int256, bool, address, bytes, bytes32, and arrays (e.g., string[], uint8[])`);
1426
+ }
1427
+ const [, baseType, size, isArray] = match;
1428
+ // Create base type
1429
+ switch (baseType) {
1430
+ case 'string':
1431
+ tagType = index_1.TagTypeBuilder.string();
1432
+ break;
1433
+ case 'uint':
1434
+ const uintSize = size ? parseInt(size) : 256;
1435
+ tagType = index_1.TagTypeBuilder.uint(uintSize);
1436
+ break;
1437
+ case 'int':
1438
+ const intSize = size ? parseInt(size) : 256;
1439
+ tagType = index_1.TagTypeBuilder.int(intSize);
1440
+ break;
1441
+ case 'bool':
1442
+ tagType = index_1.TagTypeBuilder.bool();
1443
+ break;
1444
+ case 'address':
1445
+ tagType = index_1.TagTypeBuilder.address();
1446
+ break;
1447
+ case 'bytes':
1448
+ if (size) {
1449
+ const bytesSize = parseInt(size);
1450
+ tagType = index_1.TagTypeBuilder.fixedBytes(bytesSize);
1451
+ }
1452
+ else {
1453
+ tagType = index_1.TagTypeBuilder.bytes();
1454
+ }
1455
+ break;
1456
+ default:
1457
+ throw new Error(`Unsupported type: ${baseType}`);
1458
+ }
1459
+ // Wrap in array if needed
1460
+ if (isArray) {
1461
+ tagType = index_1.TagTypeBuilder.array(tagType);
1462
+ }
1463
+ const result = await tagCtx.defineTag(tagName, tagType);
1464
+ if (result.success) {
1465
+ if (options.json) {
1466
+ console.log(JSON.stringify({
1467
+ success: true,
1468
+ domain,
1469
+ tagName,
1470
+ type: typeString,
1471
+ transactionHash: result.transactionHash,
1472
+ gasUsed: result.gasUsed?.toString(),
1473
+ blockNumber: result.blockNumber
1474
+ }, null, 2));
1475
+ }
1476
+ else {
1477
+ console.log(`\n✅ Tag "${tagName}" defined successfully`);
1478
+ console.log(` Transaction: ${result.transactionHash}`);
1479
+ if (options.verbose) {
1480
+ console.log(` Block: ${result.blockNumber}`);
1481
+ console.log(` Gas used: ${result.gasUsed?.toString()}`);
1482
+ }
1483
+ }
1484
+ }
1485
+ else {
1486
+ console.error(`\n❌ Failed to define tag`);
1487
+ process.exit(1);
1488
+ }
1489
+ }
1490
+ catch (error) {
1491
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
1492
+ process.exit(1);
1493
+ }
1494
+ }
1495
+ /**
1496
+ * Set tag value
1497
+ */
1498
+ async function tagSet(domain, tagName, valueStr, options) {
1499
+ try {
1500
+ const didConsole = getConsole(options);
1501
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
1502
+ await didConsole.setSigner(privateKeyOrMnemonic);
1503
+ const domainContext = didConsole.domain(domain);
1504
+ const tagCtx = domainContext.tag();
1505
+ console.log(`\n📝 Setting tag "${tagName}" for domain: ${domain}`);
1506
+ console.log(` Value: ${valueStr}`);
1507
+ // Try to parse value as JSON, otherwise use as string
1508
+ let value;
1509
+ try {
1510
+ value = JSON.parse(valueStr);
1511
+ }
1512
+ catch {
1513
+ value = valueStr;
1514
+ }
1515
+ const result = await tagCtx.setTag(domain, tagName, value);
1516
+ if (result.success) {
1517
+ if (options.json) {
1518
+ console.log(JSON.stringify({
1519
+ success: true,
1520
+ domain,
1521
+ tagName,
1522
+ value,
1523
+ transactionHash: result.transactionHash,
1524
+ gasUsed: result.gasUsed?.toString(),
1525
+ blockNumber: result.blockNumber
1526
+ }, null, 2));
1527
+ }
1528
+ else {
1529
+ console.log(`\n✅ Tag "${tagName}" set successfully`);
1530
+ console.log(` Transaction: ${result.transactionHash}`);
1531
+ if (options.verbose) {
1532
+ console.log(` Block: ${result.blockNumber}`);
1533
+ console.log(` Gas used: ${result.gasUsed?.toString()}`);
1534
+ }
1535
+ }
1536
+ }
1537
+ else {
1538
+ console.error(`\n❌ Failed to set tag`);
1539
+ process.exit(1);
1540
+ }
1541
+ }
1542
+ catch (error) {
1543
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
1544
+ process.exit(1);
1545
+ }
1546
+ }
1547
+ /**
1548
+ * Get tag value
1549
+ */
1550
+ async function tagGet(domain, tagName, options) {
1551
+ try {
1552
+ const didConsole = getConsole(options);
1553
+ const domainContext = didConsole.domain(domain);
1554
+ const tagCtx = domainContext.tag();
1555
+ console.log(`\n📖 Getting tag "${tagName}" for domain: ${domain}`);
1556
+ const value = await tagCtx.getTag(domain, tagName);
1557
+ if (value !== null && value !== undefined) {
1558
+ if (options.json) {
1559
+ console.log(JSON.stringify({
1560
+ success: true,
1561
+ domain,
1562
+ tagName,
1563
+ value
1564
+ }, (_, v) => (typeof v === 'bigint' ? v.toString() : v), 2));
1565
+ }
1566
+ else {
1567
+ console.log(`\n✅ Tag value:`);
1568
+ if (typeof value === 'object') {
1569
+ console.log(` ${JSON.stringify(value, (_, v) => typeof v === 'bigint' ? v.toString() : v, 2)}`);
1570
+ }
1571
+ else {
1572
+ console.log(` ${value}`);
1573
+ }
1574
+ }
1575
+ }
1576
+ else {
1577
+ if (options.json) {
1578
+ console.log(JSON.stringify({
1579
+ success: true,
1580
+ domain,
1581
+ tagName,
1582
+ value: null
1583
+ }));
1584
+ }
1585
+ else {
1586
+ console.log(`\n Tag "${tagName}" has no value (or does not exist)`);
1587
+ }
1588
+ }
1589
+ }
1590
+ catch (error) {
1591
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
1592
+ process.exit(1);
1593
+ }
1594
+ }
1595
+ /**
1596
+ * Remove tag value
1597
+ */
1598
+ async function tagRemove(domain, tagName, options) {
1599
+ try {
1600
+ const didConsole = getConsole(options);
1601
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
1602
+ await didConsole.setSigner(privateKeyOrMnemonic);
1603
+ const domainContext = didConsole.domain(domain);
1604
+ const tagCtx = domainContext.tag();
1605
+ console.log(`\n🗑️ Removing tag "${tagName}" for domain: ${domain}`);
1606
+ const result = await tagCtx.removeTag(domain, tagName);
1607
+ if (result.success) {
1608
+ if (options.json) {
1609
+ console.log(JSON.stringify({
1610
+ success: true,
1611
+ domain,
1612
+ tagName,
1613
+ transactionHash: result.transactionHash,
1614
+ gasUsed: result.gasUsed?.toString(),
1615
+ blockNumber: result.blockNumber
1616
+ }, null, 2));
1617
+ }
1618
+ else {
1619
+ console.log(`\n✅ Tag "${tagName}" value removed successfully`);
1620
+ console.log(` Transaction: ${result.transactionHash}`);
1621
+ if (options.verbose) {
1622
+ console.log(` Block: ${result.blockNumber}`);
1623
+ console.log(` Gas used: ${result.gasUsed?.toString()}`);
1624
+ }
1625
+ }
1626
+ }
1627
+ else {
1628
+ console.error(`\n❌ Failed to remove tag`);
1629
+ process.exit(1);
1630
+ }
1631
+ }
1632
+ catch (error) {
1633
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
1634
+ process.exit(1);
1635
+ }
1636
+ }
1637
+ /**
1638
+ * List all tags for a domain
1639
+ */
1640
+ async function tagList(domain, options) {
1641
+ try {
1642
+ const didConsole = getConsole(options);
1643
+ const domainContext = didConsole.domain(domain);
1644
+ console.log(`\n📋 Listing all tags for domain: ${domain}`);
1645
+ const tags = await domainContext.getAllTags();
1646
+ if (options.json) {
1647
+ console.log(JSON.stringify({
1648
+ success: true,
1649
+ domain,
1650
+ count: tags.length,
1651
+ tags
1652
+ }, (_, v) => (typeof v === 'bigint' ? v.toString() : v), 2));
1653
+ }
1654
+ else {
1655
+ console.log(`\n✅ Found ${tags.length} tags:\n`);
1656
+ for (const tag of tags) {
1657
+ console.log(` Tag: "${tag.name}"`);
1658
+ if (typeof tag.value === 'object' && tag.value !== null) {
1659
+ console.log(` Value: ${JSON.stringify(tag.value, (_, v) => typeof v === 'bigint' ? v.toString() : v)}`);
1660
+ }
1661
+ else {
1662
+ console.log(` Value: ${tag.value}`);
1663
+ }
1664
+ }
1665
+ }
1666
+ }
1667
+ catch (error) {
1668
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
1669
+ process.exit(1);
1670
+ }
1671
+ }
1672
+ /**
1673
+ * List all defined tag types for a domain
1674
+ */
1675
+ async function tagListDefined(domain, options) {
1676
+ try {
1677
+ const didConsole = getConsole(options);
1678
+ const domainContext = didConsole.domain(domain);
1679
+ console.log(`\n📋 Listing defined tag types for domain: ${domain}`);
1680
+ const tags = await domainContext.getDefinedTags();
1681
+ if (options.json) {
1682
+ console.log(JSON.stringify({
1683
+ success: true,
1684
+ domain,
1685
+ count: tags.length,
1686
+ tags
1687
+ }, null, 2));
1688
+ }
1689
+ else {
1690
+ console.log(`\n✅ Found ${tags.length} defined tag types:\n`);
1691
+ for (const tagName of tags) {
1692
+ console.log(` - ${tagName}`);
1693
+ }
1694
+ }
1695
+ }
1696
+ catch (error) {
1697
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
1698
+ process.exit(1);
1699
+ }
1700
+ }
1701
+ /**
1702
+ * Set tagger for a tag
1703
+ */
1704
+ async function tagSetTagger(domain, tagName, taggerAddress, options) {
1705
+ try {
1706
+ const didConsole = getConsole(options);
1707
+ const privateKeyOrMnemonic = getPrivateKeyOrMnemonic();
1708
+ await didConsole.setSigner(privateKeyOrMnemonic);
1709
+ const domainContext = didConsole.domain(domain);
1710
+ console.log(`\n🔐 Setting tagger for tag "${tagName}" in domain: ${domain}`);
1711
+ console.log(` Tagger address: ${taggerAddress}`);
1712
+ const result = await domainContext.setTagger(tagName, taggerAddress);
1713
+ if (result.success) {
1714
+ if (options.json) {
1715
+ console.log(JSON.stringify({
1716
+ success: true,
1717
+ domain,
1718
+ tagName,
1719
+ taggerAddress,
1720
+ transactionHash: result.transactionHash,
1721
+ gasUsed: result.gasUsed?.toString(),
1722
+ blockNumber: result.blockNumber
1723
+ }, null, 2));
1724
+ }
1725
+ else {
1726
+ console.log(`\n✅ Tagger set successfully`);
1727
+ console.log(` Transaction: ${result.transactionHash}`);
1728
+ if (options.verbose) {
1729
+ console.log(` Block: ${result.blockNumber}`);
1730
+ console.log(` Gas used: ${result.gasUsed?.toString()}`);
1731
+ }
1732
+ }
1733
+ }
1734
+ else {
1735
+ console.error(`\n❌ Failed to set tagger`);
1736
+ process.exit(1);
1737
+ }
1738
+ }
1739
+ catch (error) {
1740
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
1741
+ process.exit(1);
1742
+ }
1743
+ }
1744
+ /**
1745
+ * Get tagger for a tag
1746
+ */
1747
+ async function tagGetTagger(domain, tagName, options) {
1748
+ try {
1749
+ const didConsole = getConsole(options);
1750
+ const domainContext = didConsole.domain(domain);
1751
+ const tagCtx = domainContext.tag();
1752
+ console.log(`\n🔍 Getting tagger for tag "${tagName}" in domain: ${domain}`);
1753
+ const taggerAddress = await tagCtx.getTagger(tagName);
1754
+ if (options.json) {
1755
+ console.log(JSON.stringify({
1756
+ success: true,
1757
+ domain,
1758
+ tagName,
1759
+ taggerAddress
1760
+ }, null, 2));
1761
+ }
1762
+ else {
1763
+ console.log(`\n✅ Tagger address: ${taggerAddress}`);
1764
+ }
1765
+ }
1766
+ catch (error) {
1767
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
1768
+ process.exit(1);
1769
+ }
1770
+ }
172
1771
  async function main() {
173
- const { command, domain, options } = parseArgs();
1772
+ const { command, subCommand, domain, value, options } = parseArgs();
174
1773
  if (options.help || !command || command === 'help') {
175
1774
  showHelp();
176
1775
  return;
177
1776
  }
178
- switch (command) {
179
- case 'fetch':
180
- case 'fetch-domain':
181
- if (!domain) {
182
- console.error('❌ Error: Domain argument is required');
183
- console.error('Usage: did-cli fetch <domain> [options]');
1777
+ // Set debug options
1778
+ if (options.verbose || options.debug) {
1779
+ debug_1.debug.enable();
1780
+ debug_1.debug.setLevel(options.debugLevel);
1781
+ }
1782
+ try {
1783
+ switch (command) {
1784
+ // Query commands
1785
+ case 'info':
1786
+ if (!domain) {
1787
+ console.error('❌ Error: Domain argument is required');
1788
+ console.error('Usage: did-cli info <domain>');
1789
+ process.exit(1);
1790
+ }
1791
+ await getDomainInfo(domain, options);
1792
+ break;
1793
+ case 'owner':
1794
+ if (!domain) {
1795
+ console.error('❌ Error: Domain argument is required');
1796
+ console.error('Usage: did-cli owner <domain>');
1797
+ process.exit(1);
1798
+ }
1799
+ await getDomainOwner(domain, options);
1800
+ break;
1801
+ case 'is-owner':
1802
+ if (!domain) {
1803
+ console.error('❌ Error: Domain argument is required');
1804
+ console.error('Usage: did-cli is-owner <domain>');
1805
+ console.error('Note: Set PRIVATE_KEY_OR_MNEMONIC environment variable first');
1806
+ process.exit(1);
1807
+ }
1808
+ await checkIsOwner(domain, options);
1809
+ break;
1810
+ // Transfer command
1811
+ case 'transfer':
1812
+ if (!domain) {
1813
+ console.error('❌ Error: Domain argument is required');
1814
+ console.error('Usage: did-cli transfer <domain>');
1815
+ console.error('Options: --words 12|24 (default: 12)');
1816
+ console.error('Note: Set PRIVATE_KEY_OR_MNEMONIC environment variable first');
1817
+ console.error('Optional: Set MNEMONIC environment variable for new owner (auto-generates if not set)');
1818
+ process.exit(1);
1819
+ }
1820
+ await transferDomain(domain, options);
1821
+ break;
1822
+ // RSA commands
1823
+ case 'rsa':
1824
+ if (!subCommand) {
1825
+ console.error('❌ Error: RSA subcommand is required');
1826
+ console.error('Usage: did-cli rsa <generate|get|set|remove> [args]');
1827
+ process.exit(1);
1828
+ }
1829
+ switch (subCommand) {
1830
+ case 'generate':
1831
+ await generateRsaKey(options);
1832
+ break;
1833
+ case 'get':
1834
+ if (!domain) {
1835
+ console.error('❌ Error: Domain argument is required');
1836
+ process.exit(1);
1837
+ }
1838
+ await getRsaKey(domain, options);
1839
+ break;
1840
+ case 'set':
1841
+ if (!domain || !value) {
1842
+ console.error('❌ Error: Domain and PEM file path are required');
1843
+ console.error('Usage: did-cli rsa set <domain> <pem-file>');
1844
+ console.error('Note: Set PRIVATE_KEY_OR_MNEMONIC environment variable first');
1845
+ process.exit(1);
1846
+ }
1847
+ await setRsaKey(domain, value, options);
1848
+ break;
1849
+ case 'remove':
1850
+ if (!domain) {
1851
+ console.error('❌ Error: Domain argument is required');
1852
+ process.exit(1);
1853
+ }
1854
+ await removeRsaKey(domain, options);
1855
+ break;
1856
+ default:
1857
+ console.error(`❌ Unknown RSA subcommand: ${subCommand}`);
1858
+ process.exit(1);
1859
+ }
1860
+ break;
1861
+ // IP commands
1862
+ case 'ip':
1863
+ if (!subCommand) {
1864
+ console.error('❌ Error: IP subcommand is required');
1865
+ console.error('Usage: did-cli ip <get|set|remove> [args]');
1866
+ process.exit(1);
1867
+ }
1868
+ switch (subCommand) {
1869
+ case 'get':
1870
+ if (!domain) {
1871
+ console.error('❌ Error: Domain argument is required');
1872
+ process.exit(1);
1873
+ }
1874
+ await getIP(domain, options);
1875
+ break;
1876
+ case 'set':
1877
+ if (!domain || !value) {
1878
+ console.error('❌ Error: Domain and IP address are required');
1879
+ console.error('Usage: did-cli ip set <domain> <ip-address>');
1880
+ console.error('Note: Set PRIVATE_KEY_OR_MNEMONIC environment variable first');
1881
+ process.exit(1);
1882
+ }
1883
+ await setIP(domain, value, options);
1884
+ break;
1885
+ case 'remove':
1886
+ if (!domain) {
1887
+ console.error('❌ Error: Domain argument is required');
1888
+ process.exit(1);
1889
+ }
1890
+ await removeIP(domain, options);
1891
+ break;
1892
+ default:
1893
+ console.error(`❌ Unknown IP subcommand: ${subCommand}`);
1894
+ process.exit(1);
1895
+ }
1896
+ break;
1897
+ // Subdomain commands
1898
+ case 'subdomain':
1899
+ if (!subCommand) {
1900
+ console.error('❌ Error: Subdomain subcommand is required');
1901
+ console.error('Usage: did-cli subdomain <register> <parent-domain> <subdomain-label>');
1902
+ process.exit(1);
1903
+ }
1904
+ switch (subCommand) {
1905
+ case 'register':
1906
+ if (!domain || !value) {
1907
+ console.error('❌ Error: Parent domain and subdomain label are required');
1908
+ console.error('Usage: did-cli subdomain register <parent-domain> <subdomain-label>');
1909
+ console.error('Options: --words 12|24 (default: 12)');
1910
+ console.error('Note: Set PRIVATE_KEY_OR_MNEMONIC environment variable first');
1911
+ console.error('Optional: Set MNEMONIC environment variable for subdomain owner (auto-generates if not set)');
1912
+ process.exit(1);
1913
+ }
1914
+ await registerSubdomain(domain, value, options);
1915
+ break;
1916
+ default:
1917
+ console.error(`❌ Unknown subdomain subcommand: ${subCommand}`);
1918
+ process.exit(1);
1919
+ }
1920
+ break;
1921
+ // Operator commands
1922
+ case 'operator':
1923
+ if (!subCommand) {
1924
+ console.error('❌ Error: Operator subcommand is required');
1925
+ console.error('Usage: did-cli operator <get|set> [args]');
1926
+ process.exit(1);
1927
+ }
1928
+ switch (subCommand) {
1929
+ case 'get':
1930
+ await getOperator(options);
1931
+ break;
1932
+ case 'set':
1933
+ if (!domain) {
1934
+ console.error('❌ Error: Operator address is required');
1935
+ console.error('Usage: did-cli operator set <address>');
1936
+ console.error('Note: Set PRIVATE_KEY_OR_MNEMONIC environment variable first');
1937
+ process.exit(1);
1938
+ }
1939
+ await setOperator(domain, options);
1940
+ break;
1941
+ default:
1942
+ console.error(`❌ Unknown operator subcommand: ${subCommand}`);
1943
+ process.exit(1);
1944
+ }
1945
+ break;
1946
+ // Crypto utilities
1947
+ case 'crypto':
1948
+ if (!subCommand) {
1949
+ console.error('❌ Error: Crypto subcommand is required');
1950
+ console.error('Usage: did-cli crypto <generate|address|did|privatekey|derive> [mnemonic]');
1951
+ process.exit(1);
1952
+ }
1953
+ switch (subCommand) {
1954
+ case 'generate':
1955
+ await cryptoGenerate(options);
1956
+ break;
1957
+ case 'address':
1958
+ await cryptoGetAddress(options);
1959
+ break;
1960
+ case 'did':
1961
+ await cryptoGetDID(options);
1962
+ break;
1963
+ case 'privatekey':
1964
+ await cryptoGetPrivateKey(options);
1965
+ break;
1966
+ case 'derive':
1967
+ await cryptoDerive(options);
1968
+ break;
1969
+ default:
1970
+ console.error(`❌ Unknown crypto subcommand: ${subCommand}`);
1971
+ console.error('Available: generate, address, did, privatekey, derive');
1972
+ process.exit(1);
1973
+ }
1974
+ break;
1975
+ // Conversion utilities
1976
+ case 'convert':
1977
+ if (!subCommand) {
1978
+ console.error('❌ Error: Conversion type is required');
1979
+ console.error('Usage: did-cli convert <pem-to-der|der-to-pem|ip-to-bytes|bytes-to-ip> <value>');
1980
+ process.exit(1);
1981
+ }
1982
+ switch (subCommand) {
1983
+ case 'pem-to-der':
1984
+ if (!domain) {
1985
+ console.error('❌ Error: PEM file path is required');
1986
+ process.exit(1);
1987
+ }
1988
+ convertPemToDer(domain, options);
1989
+ break;
1990
+ case 'der-to-pem':
1991
+ if (!domain) {
1992
+ console.error('❌ Error: DER hex string is required');
1993
+ process.exit(1);
1994
+ }
1995
+ convertDerToPem(domain, options);
1996
+ break;
1997
+ case 'ip-to-bytes':
1998
+ if (!domain) {
1999
+ console.error('❌ Error: IP address is required');
2000
+ process.exit(1);
2001
+ }
2002
+ convertIpToBytes(domain, options);
2003
+ break;
2004
+ case 'bytes-to-ip':
2005
+ if (!domain) {
2006
+ console.error('❌ Error: Bytes4 hex string is required');
2007
+ process.exit(1);
2008
+ }
2009
+ convertBytesToIp(domain, options);
2010
+ break;
2011
+ default:
2012
+ console.error(`❌ Unknown conversion type: ${subCommand}`);
2013
+ process.exit(1);
2014
+ }
2015
+ break;
2016
+ case 'wallet':
2017
+ if (!subCommand) {
2018
+ console.error('❌ Error: Wallet subcommand is required');
2019
+ console.error('Usage: did-cli wallet <evm|solana> <add|remove|list> <domain>');
2020
+ process.exit(1);
2021
+ }
2022
+ switch (subCommand) {
2023
+ case 'evm':
2024
+ if (!domain || !value) {
2025
+ console.error('❌ Error: wallet evm requires <action> and <domain>');
2026
+ console.error('Usage: did-cli wallet evm <add|remove|list> <domain>');
2027
+ process.exit(1);
2028
+ }
2029
+ await walletEvm(domain, value, options);
2030
+ break;
2031
+ case 'solana':
2032
+ if (!domain || !value) {
2033
+ console.error('❌ Error: wallet solana requires <action> and <domain>');
2034
+ console.error('Usage: did-cli wallet solana <add|remove|list> <domain>');
2035
+ process.exit(1);
2036
+ }
2037
+ await walletSolana(domain, value, options);
2038
+ break;
2039
+ default:
2040
+ console.error(`❌ Unknown wallet type: ${subCommand}`);
2041
+ console.error('Usage: did-cli wallet <evm|solana> <add|remove|list> <domain>');
2042
+ process.exit(1);
2043
+ }
2044
+ break;
2045
+ // Tag commands
2046
+ case 'tag':
2047
+ if (!subCommand) {
2048
+ console.error('❌ Error: Tag subcommand is required');
2049
+ console.error('Usage: did-cli tag <define|set|get|remove|list|list-defined|set-tagger|get-tagger> [args]');
2050
+ process.exit(1);
2051
+ }
2052
+ switch (subCommand) {
2053
+ case 'define':
2054
+ if (!domain || !value) {
2055
+ console.error('❌ Error: tag define requires <domain>, <tag-name> and <type>');
2056
+ console.error('Usage: did-cli tag define <domain> <tag-name> <type>');
2057
+ console.error(' Supported types: string, uint8, uint256, int8, int256, bool, address, bytes, bytes32');
2058
+ console.error(' Array types: string[], uint8[], etc.');
2059
+ console.error('\nNote: Set PRIVATE_KEY_OR_MNEMONIC environment variable first');
2060
+ process.exit(1);
2061
+ }
2062
+ // For define command: domain=tagName, value=type
2063
+ // We need to get the actual domain from the previous positional arg
2064
+ // This is a bit tricky with current parsing, let's handle it
2065
+ {
2066
+ const args = process.argv.slice(2);
2067
+ const defineIdx = args.indexOf('define');
2068
+ if (defineIdx >= 0 && args.length > defineIdx + 3) {
2069
+ const actualDomain = args[defineIdx + 1];
2070
+ const tagName = args[defineIdx + 2];
2071
+ const typeString = args[defineIdx + 3];
2072
+ await tagDefine(actualDomain, tagName, typeString, options);
2073
+ }
2074
+ else {
2075
+ console.error('❌ Error: Missing arguments for tag define');
2076
+ console.error('Usage: did-cli tag define <domain> <tag-name> <type>');
2077
+ process.exit(1);
2078
+ }
2079
+ }
2080
+ break;
2081
+ case 'set':
2082
+ if (!domain || !value) {
2083
+ console.error('❌ Error: tag set requires <domain>, <tag-name> and <value>');
2084
+ console.error('Usage: did-cli tag set <domain> <tag-name> <value>');
2085
+ console.error(' Value can be a string or JSON (e.g., \'["item1","item2"]\' for arrays)');
2086
+ console.error('\nNote: Set PRIVATE_KEY_OR_MNEMONIC environment variable first');
2087
+ process.exit(1);
2088
+ }
2089
+ {
2090
+ const args = process.argv.slice(2);
2091
+ const setIdx = args.indexOf('set');
2092
+ if (setIdx >= 0 && args.length > setIdx + 3) {
2093
+ const actualDomain = args[setIdx + 1];
2094
+ const tagName = args[setIdx + 2];
2095
+ const valueStr = args[setIdx + 3];
2096
+ await tagSet(actualDomain, tagName, valueStr, options);
2097
+ }
2098
+ else {
2099
+ console.error('❌ Error: Missing arguments for tag set');
2100
+ console.error('Usage: did-cli tag set <domain> <tag-name> <value>');
2101
+ process.exit(1);
2102
+ }
2103
+ }
2104
+ break;
2105
+ case 'get':
2106
+ if (!domain) {
2107
+ console.error('❌ Error: tag get requires <domain> and <tag-name>');
2108
+ console.error('Usage: did-cli tag get <domain> <tag-name>');
2109
+ process.exit(1);
2110
+ }
2111
+ {
2112
+ const args = process.argv.slice(2);
2113
+ const getIdx = args.indexOf('get');
2114
+ if (getIdx >= 0 && args.length > getIdx + 2) {
2115
+ const actualDomain = args[getIdx + 1];
2116
+ const tagName = args[getIdx + 2];
2117
+ await tagGet(actualDomain, tagName, options);
2118
+ }
2119
+ else {
2120
+ console.error('❌ Error: Missing arguments for tag get');
2121
+ console.error('Usage: did-cli tag get <domain> <tag-name>');
2122
+ process.exit(1);
2123
+ }
2124
+ }
2125
+ break;
2126
+ case 'remove':
2127
+ if (!domain) {
2128
+ console.error('❌ Error: tag remove requires <domain> and <tag-name>');
2129
+ console.error('Usage: did-cli tag remove <domain> <tag-name>');
2130
+ console.error('\nNote: Set PRIVATE_KEY_OR_MNEMONIC environment variable first');
2131
+ process.exit(1);
2132
+ }
2133
+ {
2134
+ const args = process.argv.slice(2);
2135
+ const removeIdx = args.indexOf('remove');
2136
+ if (removeIdx >= 0 && args.length > removeIdx + 2) {
2137
+ const actualDomain = args[removeIdx + 1];
2138
+ const tagName = args[removeIdx + 2];
2139
+ await tagRemove(actualDomain, tagName, options);
2140
+ }
2141
+ else {
2142
+ console.error('❌ Error: Missing arguments for tag remove');
2143
+ console.error('Usage: did-cli tag remove <domain> <tag-name>');
2144
+ process.exit(1);
2145
+ }
2146
+ }
2147
+ break;
2148
+ case 'list':
2149
+ if (!domain) {
2150
+ console.error('❌ Error: Domain argument is required');
2151
+ console.error('Usage: did-cli tag list <domain>');
2152
+ process.exit(1);
2153
+ }
2154
+ await tagList(domain, options);
2155
+ break;
2156
+ case 'list-defined':
2157
+ if (!domain) {
2158
+ console.error('❌ Error: Domain argument is required');
2159
+ console.error('Usage: did-cli tag list-defined <domain>');
2160
+ process.exit(1);
2161
+ }
2162
+ await tagListDefined(domain, options);
2163
+ break;
2164
+ case 'set-tagger':
2165
+ if (!domain || !value) {
2166
+ console.error('❌ Error: tag set-tagger requires <domain>, <tag-name> and <tagger-address>');
2167
+ console.error('Usage: did-cli tag set-tagger <domain> <tag-name> <tagger-address>');
2168
+ console.error('\nNote: Set PRIVATE_KEY_OR_MNEMONIC environment variable first');
2169
+ process.exit(1);
2170
+ }
2171
+ {
2172
+ const args = process.argv.slice(2);
2173
+ const setTaggerIdx = args.indexOf('set-tagger');
2174
+ if (setTaggerIdx >= 0 &&
2175
+ args.length > setTaggerIdx + 3) {
2176
+ const actualDomain = args[setTaggerIdx + 1];
2177
+ const tagName = args[setTaggerIdx + 2];
2178
+ const taggerAddress = args[setTaggerIdx + 3];
2179
+ await tagSetTagger(actualDomain, tagName, taggerAddress, options);
2180
+ }
2181
+ else {
2182
+ console.error('❌ Error: Missing arguments for tag set-tagger');
2183
+ console.error('Usage: did-cli tag set-tagger <domain> <tag-name> <tagger-address>');
2184
+ process.exit(1);
2185
+ }
2186
+ }
2187
+ break;
2188
+ case 'get-tagger':
2189
+ if (!domain) {
2190
+ console.error('❌ Error: tag get-tagger requires <domain> and <tag-name>');
2191
+ console.error('Usage: did-cli tag get-tagger <domain> <tag-name>');
2192
+ process.exit(1);
2193
+ }
2194
+ {
2195
+ const args = process.argv.slice(2);
2196
+ const getTaggerIdx = args.indexOf('get-tagger');
2197
+ if (getTaggerIdx >= 0 &&
2198
+ args.length > getTaggerIdx + 2) {
2199
+ const actualDomain = args[getTaggerIdx + 1];
2200
+ const tagName = args[getTaggerIdx + 2];
2201
+ await tagGetTagger(actualDomain, tagName, options);
2202
+ }
2203
+ else {
2204
+ console.error('❌ Error: Missing arguments for tag get-tagger');
2205
+ console.error('Usage: did-cli tag get-tagger <domain> <tag-name>');
2206
+ process.exit(1);
2207
+ }
2208
+ }
2209
+ break;
2210
+ default:
2211
+ console.error(`❌ Unknown tag subcommand: ${subCommand}`);
2212
+ console.error('Usage: did-cli tag <define|set|get|remove|list|list-defined|set-tagger|get-tagger> [args]');
2213
+ process.exit(1);
2214
+ }
2215
+ break;
2216
+ // Legacy commands
2217
+ case 'fetch':
2218
+ case 'fetch-domain':
2219
+ if (!domain) {
2220
+ console.error('❌ Error: Domain argument is required');
2221
+ console.error('Usage: did-cli fetch <domain> [options]');
2222
+ process.exit(1);
2223
+ }
2224
+ await fetchDomain(domain, options);
2225
+ break;
2226
+ default:
2227
+ console.error(`❌ Unknown command: ${command}`);
2228
+ console.error('Run "did-cli help" for usage information');
184
2229
  process.exit(1);
185
- }
186
- await fetchDomain(domain, options);
187
- break;
188
- default:
189
- console.error(`❌ Unknown command: ${command}`);
190
- console.error('Run "did-cli help" for usage information');
191
- process.exit(1);
2230
+ }
2231
+ }
2232
+ catch (error) {
2233
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
2234
+ if (debug_1.debug.isEnabled()) {
2235
+ debug_1.debug.error('Full error details:', error);
2236
+ }
2237
+ process.exit(1);
192
2238
  }
193
2239
  }
194
2240
  // 运行主函数