@beclab/olaresid 0.1.1 → 0.1.3

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