@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
@@ -0,0 +1,1209 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.DomainContext = exports.UserType = exports.TagTypeBuilder = exports.TagContext = exports.deriveDIDFromMnemonic = exports.generateDIDKeyData = exports.getDIDFromMnemonic = exports.getEVMPrivateKeyFromMnemonic = exports.getEthereumAddressFromMnemonic = exports.generateMnemonic = exports.createRsaKeyPair = void 0;
37
+ exports.ipv4ToBytes4 = ipv4ToBytes4;
38
+ exports.bytes4ToIpv4 = bytes4ToIpv4;
39
+ exports.pemToDer = pemToDer;
40
+ exports.derToPem = derToPem;
41
+ const ethers_1 = require("ethers");
42
+ const error_parser_1 = require("../utils/error-parser");
43
+ const tag_context_1 = require("./tag-context");
44
+ const tag_type_builder_1 = require("../utils/tag-type-builder");
45
+ // Re-export from crypto-utils
46
+ var crypto_utils_1 = require("../utils/crypto-utils");
47
+ Object.defineProperty(exports, "createRsaKeyPair", { enumerable: true, get: function () { return crypto_utils_1.createRsaKeyPair; } });
48
+ Object.defineProperty(exports, "generateMnemonic", { enumerable: true, get: function () { return crypto_utils_1.generateMnemonic; } });
49
+ Object.defineProperty(exports, "getEthereumAddressFromMnemonic", { enumerable: true, get: function () { return crypto_utils_1.getEthereumAddressFromMnemonic; } });
50
+ Object.defineProperty(exports, "getEVMPrivateKeyFromMnemonic", { enumerable: true, get: function () { return crypto_utils_1.getEVMPrivateKeyFromMnemonic; } });
51
+ Object.defineProperty(exports, "getDIDFromMnemonic", { enumerable: true, get: function () { return crypto_utils_1.getDIDFromMnemonic; } });
52
+ Object.defineProperty(exports, "generateDIDKeyData", { enumerable: true, get: function () { return crypto_utils_1.generateDIDKeyData; } });
53
+ Object.defineProperty(exports, "deriveDIDFromMnemonic", { enumerable: true, get: function () { return crypto_utils_1.deriveDIDFromMnemonic; } });
54
+ // Re-export Tag-related classes
55
+ var tag_context_2 = require("./tag-context");
56
+ Object.defineProperty(exports, "TagContext", { enumerable: true, get: function () { return tag_context_2.TagContext; } });
57
+ var tag_type_builder_2 = require("../utils/tag-type-builder");
58
+ Object.defineProperty(exports, "TagTypeBuilder", { enumerable: true, get: function () { return tag_type_builder_2.TagTypeBuilder; } });
59
+ /**
60
+ * Domain registration type
61
+ */
62
+ var UserType;
63
+ (function (UserType) {
64
+ UserType["IndividualOrganizationalUser"] = "Individual:OrganizationalUser";
65
+ UserType["IndividualTerminusUser"] = "Individual:TerminusUser";
66
+ UserType["Organization"] = "Organization";
67
+ UserType["Entity"] = "Entity";
68
+ })(UserType || (exports.UserType = UserType = {}));
69
+ class DomainContext {
70
+ constructor(domainName, console) {
71
+ this.domainName = domainName;
72
+ this.console = console;
73
+ }
74
+ /**
75
+ * Calculate the tokenId for the domain name
76
+ * This is a pure function that hashes the domain name using keccak256
77
+ * The result is cached after the first call
78
+ * @returns The tokenId as a decimal string
79
+ */
80
+ getTokenId() {
81
+ if (!this.tokenId) {
82
+ const hash = ethers_1.ethers.keccak256(ethers_1.ethers.toUtf8Bytes(this.domainName));
83
+ // Convert hex string to decimal string (BigInt format)
84
+ this.tokenId = BigInt(hash).toString();
85
+ }
86
+ return this.tokenId;
87
+ }
88
+ /**
89
+ * Get only the basic information of the domain
90
+ * Uses parallel RPC calls to get metadata and latest DID for optimal performance
91
+ * TokenId is calculated locally using keccak256
92
+ * @throws Error if domain is not registered or RPC call fails
93
+ */
94
+ async getMetaInfo() {
95
+ const didContract = this.console.getContractDID();
96
+ const resolverContract = this.console.getContractRootResolver();
97
+ // Calculate tokenId locally (no RPC call needed)
98
+ const tokenId = this.getTokenId();
99
+ // Parallel execution: Get metadata and latestDID simultaneously
100
+ const [metadata, latestDID] = await Promise.all([
101
+ didContract.getMetadata(tokenId),
102
+ // Use catch to handle cases where latestDID is not set
103
+ resolverContract.getLatestDID(this.domainName).catch(() => '')
104
+ ]);
105
+ // Use latestDID if it has a value, otherwise fallback to metadata.did
106
+ const finalDid = latestDID && latestDID.trim() !== '' ? latestDID : metadata.did;
107
+ return {
108
+ id: tokenId,
109
+ name: metadata.domain,
110
+ did: finalDid,
111
+ note: metadata.notes,
112
+ allowSubdomain: metadata.allowSubdomain
113
+ };
114
+ }
115
+ /**
116
+ * Get the owner address of the domain
117
+ * Uses cached value if available, otherwise fetches from chain
118
+ * @throws Error if domain is not registered or RPC call fails
119
+ */
120
+ async getOwner() {
121
+ // Return cached owner if available
122
+ if (this.owner) {
123
+ return this.owner;
124
+ }
125
+ const contract = this.console.getContractDID();
126
+ // Calculate tokenId locally (no RPC call needed)
127
+ const tokenId = this.getTokenId();
128
+ // Single RPC call to get owner
129
+ const owner = await contract.ownerOf(tokenId);
130
+ // Cache the owner for later use
131
+ this.owner = owner;
132
+ return owner;
133
+ }
134
+ /**
135
+ * Check if the connected signer is the owner of the domain
136
+ * @throws Error if no signer is connected or RPC call fails
137
+ */
138
+ async isOwner() {
139
+ const signer = this.console.getSigner();
140
+ const signerAddress = await signer.getAddress();
141
+ const owner = await this.getOwner();
142
+ return signerAddress.toLowerCase() === owner.toLowerCase();
143
+ }
144
+ /**
145
+ * Register a subdomain using mnemonic-derived keys
146
+ *
147
+ * @param subdomain Subdomain label only (e.g., "child" for "child.parent.com")
148
+ * @param mnemonic BIP39 mnemonic phrase (12 words by default) to derive owner and DID
149
+ * @returns Transaction result with success status and transaction hash
150
+ * @throws Error if no signer is connected, parent domain doesn't exist, or transaction fails
151
+ *
152
+ * The subdomain's metadata:
153
+ * - owner: derived from mnemonic using Trust Wallet Core (same as TermiPass)
154
+ * - DID: derived from mnemonic using Ed25519 (same as TermiPass)
155
+ * - note: inherits from parent domain
156
+ * - allowSubdomain: inherits from parent domain
157
+ *
158
+ * @example
159
+ * ```typescript
160
+ * // For parent domain "parent.com", register subdomain "child"
161
+ * const parentDomain = olaresId.domain('parent.com');
162
+ * const mnemonic = generateMnemonic(12);
163
+ *
164
+ * const result = await parentDomain.registerSubdomain('child', mnemonic);
165
+ * // This will register "child.parent.com"
166
+ *
167
+ * if (result.success) {
168
+ * console.log('Full domain:', result.data.fullDomainName); // "child.parent.com"
169
+ * console.log('Owner:', result.data.owner);
170
+ * console.log('DID:', result.data.did);
171
+ * }
172
+ * ```
173
+ */
174
+ async registerSubdomain(subdomain, mnemonic) {
175
+ try {
176
+ // 1. Get parent domain metadata to inherit note and allowSubdomain
177
+ const parentMetadata = await this.getMetaInfo();
178
+ // 2. Construct full domain name: subdomain.parentDomain
179
+ const fullDomainName = `${subdomain}.${parentMetadata.name}`;
180
+ // 3. Derive owner and DID from mnemonic using Trust Wallet Core
181
+ const { deriveDIDFromMnemonic } = await Promise.resolve().then(() => __importStar(require('../utils/crypto-utils')));
182
+ const { owner, did } = await deriveDIDFromMnemonic(mnemonic);
183
+ // 4. Prepare metadata for subdomain (inherit from parent)
184
+ const subdomainNote = parentMetadata.note;
185
+ const subdomainAllowSubdomain = parentMetadata.allowSubdomain;
186
+ // 5. Call register function on the contract
187
+ const contract = this.console.getSignerContractDID();
188
+ const metadata = {
189
+ domain: fullDomainName,
190
+ did: did,
191
+ notes: subdomainNote,
192
+ allowSubdomain: subdomainAllowSubdomain
193
+ };
194
+ const tx = await contract.register(owner, metadata);
195
+ const receipt = await tx.wait();
196
+ return {
197
+ success: true,
198
+ transactionHash: receipt.hash,
199
+ gasUsed: receipt.gasUsed,
200
+ blockNumber: receipt.blockNumber,
201
+ data: {
202
+ owner,
203
+ did,
204
+ subdomain,
205
+ fullDomainName
206
+ }
207
+ };
208
+ }
209
+ catch (error) {
210
+ const parsedError = (0, error_parser_1.parseContractError)(error);
211
+ // Always throw network errors
212
+ if (parsedError.isNetworkError) {
213
+ throw new Error(`Network error: ${parsedError.message}`);
214
+ }
215
+ return {
216
+ success: false,
217
+ transactionHash: '',
218
+ error: parsedError.message
219
+ };
220
+ }
221
+ }
222
+ /**
223
+ * Transfer domain ownership to a new owner derived from mnemonic
224
+ *
225
+ * @param mnemonic BIP39 mnemonic phrase to derive new owner and DID
226
+ * @returns Transaction result with success status
227
+ *
228
+ * This function performs two operations:
229
+ * 1. Transfer NFT ownership via DID contract's transferFrom
230
+ * 2. Update DID via RootResolver's setLatestDID
231
+ *
232
+ * @example
233
+ * ```typescript
234
+ * const mnemonic = generateMnemonic(12);
235
+ * const result = await domain.transfer(mnemonic);
236
+ * if (result.success) {
237
+ * console.log('Domain transferred!');
238
+ * console.log('New Owner:', result.data.newOwner);
239
+ * console.log('New DID:', result.data.newDid);
240
+ * }
241
+ * ```
242
+ */
243
+ async transfer(mnemonic) {
244
+ try {
245
+ // 1. Get current domain info
246
+ const currentOwner = await this.getOwner();
247
+ const tokenId = this.getTokenId();
248
+ // 2. Derive new owner and DID from mnemonic
249
+ const { deriveDIDFromMnemonic } = await Promise.resolve().then(() => __importStar(require('../utils/crypto-utils')));
250
+ const { owner: newOwner, did: newDid } = await deriveDIDFromMnemonic(mnemonic);
251
+ // 3. Update DID FIRST (while current owner still has permission)
252
+ // This must be done before transferFrom, because after transfer,
253
+ // the current owner will lose permission to call setLatestDID
254
+ const resolverContract = this.console.getSignerContractRootResolver();
255
+ const setDidTx = await resolverContract.setLatestDID(this.domainName, newDid);
256
+ const setDidReceipt = await setDidTx.wait();
257
+ // 4. Transfer NFT ownership (DID contract)
258
+ // After this, the new owner will have control
259
+ const didContract = this.console.getSignerContractDID();
260
+ const transferTx = await didContract.transferFrom(currentOwner, newOwner, tokenId);
261
+ const transferReceipt = await transferTx.wait();
262
+ // Calculate total gas used
263
+ const totalGasUsed = setDidReceipt.gasUsed + transferReceipt.gasUsed;
264
+ return {
265
+ success: true,
266
+ transactionHash: transferReceipt.hash,
267
+ gasUsed: totalGasUsed,
268
+ blockNumber: transferReceipt.blockNumber,
269
+ data: {
270
+ newOwner,
271
+ newDid,
272
+ tokenId,
273
+ setDidTxHash: setDidReceipt.hash,
274
+ transferTxHash: transferReceipt.hash
275
+ }
276
+ };
277
+ }
278
+ catch (error) {
279
+ const parsedError = (0, error_parser_1.parseContractError)(error);
280
+ // Always throw network errors
281
+ if (parsedError.isNetworkError) {
282
+ throw new Error(`Network error: ${parsedError.message}`);
283
+ }
284
+ return {
285
+ success: false,
286
+ transactionHash: '',
287
+ error: parsedError.message
288
+ };
289
+ }
290
+ }
291
+ /**
292
+ * Set the RSA public key for your own domain
293
+ * Users can use the helper function createRsaKeyPair to generate a new RSA key pair
294
+ * The pubKey parameter should be in RSA PKCS8 ASN.1 format
295
+ * @param rsaPublicKey - The RSA public key in PEM format or DER hex format (with or without '0x' prefix)
296
+ * @throws Error if no signer is connected or transaction fails
297
+ */
298
+ async setRSAPublicKey(rsaPublicKey) {
299
+ const contract = this.console.getSignerContractRootResolver();
300
+ try {
301
+ let pubKeyBytes;
302
+ // Check if input is PEM format (contains BEGIN/END markers)
303
+ if (rsaPublicKey.includes('BEGIN')) {
304
+ // Convert PEM to DER hex format
305
+ pubKeyBytes = pemToDer(rsaPublicKey);
306
+ }
307
+ else {
308
+ // Assume it's already in hex format, ensure it has '0x' prefix
309
+ pubKeyBytes = rsaPublicKey.startsWith('0x')
310
+ ? rsaPublicKey
311
+ : '0x' + rsaPublicKey;
312
+ }
313
+ const tx = await contract.setRsaPubKey(this.domainName, pubKeyBytes);
314
+ const receipt = await tx.wait();
315
+ return {
316
+ success: true,
317
+ transactionHash: receipt.hash,
318
+ gasUsed: receipt.gasUsed,
319
+ blockNumber: receipt.blockNumber
320
+ };
321
+ }
322
+ catch (error) {
323
+ const parsedError = (0, error_parser_1.parseContractError)(error);
324
+ // Always throw network errors
325
+ if (parsedError.isNetworkError) {
326
+ throw new Error(`Network error: ${parsedError.message}`);
327
+ }
328
+ return {
329
+ success: false,
330
+ transactionHash: '',
331
+ error: parsedError.message
332
+ };
333
+ }
334
+ }
335
+ /**
336
+ * Remove the RSA public key for your own domain
337
+ * This is done by calling setRsaPubKey with empty bytes
338
+ * @throws Error if no signer is connected or transaction fails
339
+ */
340
+ async removeRSAPublicKey() {
341
+ const contract = this.console.getSignerContractRootResolver();
342
+ try {
343
+ // Pass empty bytes to remove the RSA public key
344
+ const tx = await contract.setRsaPubKey(this.domainName, '0x');
345
+ const receipt = await tx.wait();
346
+ return {
347
+ success: true,
348
+ transactionHash: receipt.hash,
349
+ gasUsed: receipt.gasUsed,
350
+ blockNumber: receipt.blockNumber
351
+ };
352
+ }
353
+ catch (error) {
354
+ const parsedError = (0, error_parser_1.parseContractError)(error);
355
+ // Always throw network errors
356
+ if (parsedError.isNetworkError) {
357
+ throw new Error(`Network error: ${parsedError.message}`);
358
+ }
359
+ return {
360
+ success: false,
361
+ transactionHash: '',
362
+ error: parsedError.message
363
+ };
364
+ }
365
+ }
366
+ /**
367
+ * Get the RSA public key for the domain
368
+ * @returns The RSA public key in PEM PKCS#8 format, or null if not set
369
+ * @throws Error if network error or unexpected contract error occurs
370
+ */
371
+ async getRSAPublicKey() {
372
+ const contract = this.console.getContractRootResolver();
373
+ try {
374
+ const pubKey = await contract.getRsaPubKey(this.domainName);
375
+ // If pubKey is empty bytes, return null
376
+ if (pubKey === '0x' || pubKey.length === 2) {
377
+ return null;
378
+ }
379
+ // Convert DER hex format to PEM PKCS#8 format
380
+ return derToPem(pubKey);
381
+ }
382
+ catch (error) {
383
+ const parsedError = (0, error_parser_1.parseContractError)(error);
384
+ // Always throw network errors
385
+ if (parsedError.isNetworkError) {
386
+ throw new Error(`Network error: ${parsedError.message}`);
387
+ }
388
+ // If tag doesn't exist, return null (this is expected)
389
+ if (parsedError.errorName === 'RootTagNoExists' ||
390
+ parsedError.errorName === 'TagNotExist') {
391
+ return null;
392
+ }
393
+ // For other contract errors, throw with friendly message
394
+ throw new Error(parsedError.message);
395
+ }
396
+ }
397
+ /**
398
+ * Set the DNS A record for your own domain, currently the contract only supports IPv4 address format
399
+ * The parameter is an IPv4 address, in xxx.xxx.xxx.xxx format
400
+ * @param aRecord - IPv4 address string (e.g., "192.168.1.1")
401
+ * @throws Error if no signer is connected or transaction fails
402
+ */
403
+ async setIP(aRecord) {
404
+ const contract = this.console.getSignerContractRootResolver();
405
+ try {
406
+ // Convert IPv4 string to bytes4 format
407
+ const ipv4Bytes = ipv4ToBytes4(aRecord);
408
+ const tx = await contract.setDnsARecord(this.domainName, ipv4Bytes);
409
+ const receipt = await tx.wait();
410
+ return {
411
+ success: true,
412
+ transactionHash: receipt.hash,
413
+ gasUsed: receipt.gasUsed,
414
+ blockNumber: receipt.blockNumber
415
+ };
416
+ }
417
+ catch (error) {
418
+ const parsedError = (0, error_parser_1.parseContractError)(error);
419
+ // Always throw network errors
420
+ if (parsedError.isNetworkError) {
421
+ throw new Error(`Network error: ${parsedError.message}`);
422
+ }
423
+ return {
424
+ success: false,
425
+ transactionHash: '',
426
+ error: parsedError.message
427
+ };
428
+ }
429
+ }
430
+ /**
431
+ * Remove the DNS A record for your own domain
432
+ * This is done by calling setDnsARecord with bytes4(0)
433
+ * @throws Error if no signer is connected or transaction fails
434
+ */
435
+ async removeIP() {
436
+ const contract = this.console.getSignerContractRootResolver();
437
+ try {
438
+ // Pass bytes4(0) to remove the DNS A record
439
+ const tx = await contract.setDnsARecord(this.domainName, '0x00000000');
440
+ const receipt = await tx.wait();
441
+ return {
442
+ success: true,
443
+ transactionHash: receipt.hash,
444
+ gasUsed: receipt.gasUsed,
445
+ blockNumber: receipt.blockNumber
446
+ };
447
+ }
448
+ catch (error) {
449
+ const parsedError = (0, error_parser_1.parseContractError)(error);
450
+ // Always throw network errors
451
+ if (parsedError.isNetworkError) {
452
+ throw new Error(`Network error: ${parsedError.message}`);
453
+ }
454
+ return {
455
+ success: false,
456
+ transactionHash: '',
457
+ error: parsedError.message
458
+ };
459
+ }
460
+ }
461
+ /**
462
+ * Get the DNS A record for your own domain
463
+ * @returns The IPv4 address as a string (e.g., "192.168.1.1"), or null if not set
464
+ * @throws Error if network error or unexpected contract error occurs
465
+ */
466
+ async getIP() {
467
+ const contract = this.console.getContractRootResolver();
468
+ try {
469
+ const ipv4Bytes = await contract.getDnsARecord(this.domainName);
470
+ // If ipv4Bytes is 0x00000000, return null
471
+ if (ipv4Bytes === '0x00000000') {
472
+ return null;
473
+ }
474
+ // Convert bytes4 to IPv4 string
475
+ return bytes4ToIpv4(ipv4Bytes);
476
+ }
477
+ catch (error) {
478
+ const parsedError = (0, error_parser_1.parseContractError)(error);
479
+ // Always throw network errors
480
+ if (parsedError.isNetworkError) {
481
+ throw new Error(`Network error: ${parsedError.message}`);
482
+ }
483
+ // If tag doesn't exist, return null (this is expected)
484
+ if (parsedError.errorName === 'RootTagNoExists' ||
485
+ parsedError.errorName === 'TagNotExist') {
486
+ return null;
487
+ }
488
+ // For other contract errors, throw with friendly message
489
+ throw new Error(parsedError.message);
490
+ }
491
+ }
492
+ /**
493
+ * Add EVM wallet address to the domain's authenticated address tag
494
+ * @param evmPrivateKey - EVM private key (hex string with 0x prefix)
495
+ * @returns Transaction result with success status and transaction hash
496
+ */
497
+ async addEVMWallet(evmPrivateKey) {
498
+ try {
499
+ // Get wallet address from private key
500
+ const wallet = new ethers_1.ethers.Wallet(evmPrivateKey);
501
+ const evmAddress = wallet.address;
502
+ // Get current timestamp
503
+ const signAt = Math.floor(Date.now() / 1000) - 30 * 60; // 30 minutes ago
504
+ // Prepare the request value
505
+ const value = {
506
+ addr: evmAddress,
507
+ domain: this.domainName,
508
+ signAt: signAt,
509
+ action: 0 // Action.Add
510
+ };
511
+ // Get domain owner's signer
512
+ const domainOwner = this.console.getSigner();
513
+ if (!domainOwner) {
514
+ throw new Error('Signer not set. Please call setSigner() first.');
515
+ }
516
+ // Get RootTagger2 contract
517
+ const rootTagger = this.console.getSignerContractRootResolver2();
518
+ const chainId = (await domainOwner.provider?.getNetwork())?.chainId;
519
+ // Define EIP-712 domain
520
+ const domain = {
521
+ name: 'Terminus DID Root Tagger',
522
+ version: '1',
523
+ chainId: chainId,
524
+ verifyingContract: await rootTagger.getAddress()
525
+ };
526
+ // Define EIP-712 types
527
+ const types = {
528
+ EVMAuthAddressReq: [
529
+ { name: 'addr', type: 'address' },
530
+ { name: 'domain', type: 'string' },
531
+ { name: 'signAt', type: 'uint256' },
532
+ { name: 'action', type: 'uint8' }
533
+ ]
534
+ };
535
+ // Sign by domain owner
536
+ const sigFromDomainOwner = await domainOwner.signTypedData(domain, types, value);
537
+ // Sign by the EVM wallet
538
+ const sigFromAuthAddr = await wallet.signTypedData(domain, types, value);
539
+ // Call contract
540
+ const tx = await rootTagger.updateEVMWallet(value, sigFromDomainOwner, sigFromAuthAddr);
541
+ const receipt = await tx.wait();
542
+ return {
543
+ success: true,
544
+ transactionHash: receipt.hash,
545
+ gasUsed: receipt.gasUsed,
546
+ blockNumber: receipt.blockNumber,
547
+ data: { address: evmAddress }
548
+ };
549
+ }
550
+ catch (error) {
551
+ const errorInfo = (0, error_parser_1.parseContractError)(error);
552
+ // Always throw network errors
553
+ if (errorInfo.isNetworkError) {
554
+ throw new Error(`Network error: ${errorInfo.message}`);
555
+ }
556
+ return {
557
+ success: false,
558
+ transactionHash: '',
559
+ error: errorInfo.message
560
+ };
561
+ }
562
+ }
563
+ /**
564
+ * Remove EVM wallet address from the domain's authenticated address tag
565
+ * @param evmPrivateKey - EVM private key (hex string with 0x prefix)
566
+ * @returns Transaction result with success status and transaction hash
567
+ */
568
+ async removeEVMWallet(evmPrivateKey) {
569
+ try {
570
+ // Get wallet address from private key
571
+ const wallet = new ethers_1.ethers.Wallet(evmPrivateKey);
572
+ const evmAddress = wallet.address;
573
+ // Get current timestamp
574
+ const signAt = Math.floor(Date.now() / 1000) - 30 * 60; // 30 minutes ago
575
+ // Prepare the request value
576
+ const value = {
577
+ addr: evmAddress,
578
+ domain: this.domainName,
579
+ signAt: signAt,
580
+ action: 1 // Action.Remove
581
+ };
582
+ // Get domain owner's signer
583
+ const domainOwner = this.console.getSigner();
584
+ if (!domainOwner) {
585
+ throw new Error('Signer not set. Please call setSigner() first.');
586
+ }
587
+ // Get RootTagger2 contract
588
+ const rootTagger = this.console.getSignerContractRootResolver2();
589
+ const chainId = (await domainOwner.provider?.getNetwork())?.chainId;
590
+ // Define EIP-712 domain
591
+ const domain = {
592
+ name: 'Terminus DID Root Tagger',
593
+ version: '1',
594
+ chainId: chainId,
595
+ verifyingContract: await rootTagger.getAddress()
596
+ };
597
+ // Define EIP-712 types
598
+ const types = {
599
+ EVMAuthAddressReq: [
600
+ { name: 'addr', type: 'address' },
601
+ { name: 'domain', type: 'string' },
602
+ { name: 'signAt', type: 'uint256' },
603
+ { name: 'action', type: 'uint8' }
604
+ ]
605
+ };
606
+ // Sign by domain owner
607
+ const sigFromDomainOwner = await domainOwner.signTypedData(domain, types, value);
608
+ // For remove action, signature from address is not required (pass empty bytes)
609
+ const sigFromAuthAddr = '0x';
610
+ // Call contract
611
+ const tx = await rootTagger.updateEVMWallet(value, sigFromDomainOwner, sigFromAuthAddr);
612
+ const receipt = await tx.wait();
613
+ return {
614
+ success: true,
615
+ transactionHash: receipt.hash,
616
+ gasUsed: receipt.gasUsed,
617
+ blockNumber: receipt.blockNumber,
618
+ data: { address: evmAddress }
619
+ };
620
+ }
621
+ catch (error) {
622
+ const errorInfo = (0, error_parser_1.parseContractError)(error);
623
+ // Always throw network errors
624
+ if (errorInfo.isNetworkError) {
625
+ throw new Error(`Network error: ${errorInfo.message}`);
626
+ }
627
+ return {
628
+ success: false,
629
+ transactionHash: '',
630
+ error: errorInfo.message
631
+ };
632
+ }
633
+ }
634
+ /**
635
+ * Get all EVM wallet addresses for the domain
636
+ * Combines addresses from both RootTagger2 (new) and RootResolver (legacy) for backward compatibility
637
+ * @returns Array of unique EVM wallet addresses
638
+ */
639
+ async getEVMWallets() {
640
+ const addresses = [];
641
+ // Get addresses from RootTagger2 (new method)
642
+ try {
643
+ const rootTagger2 = this.console.getContractRootResolver2();
644
+ const result = await rootTagger2.getEVMWallets(this.domainName);
645
+ // Extract addresses from the result
646
+ // Result is array of { algorithm, addr }
647
+ const tagger2Addresses = result.map((item) => item.addr.toLowerCase());
648
+ addresses.push(...tagger2Addresses);
649
+ }
650
+ catch (error) {
651
+ const errorInfo = (0, error_parser_1.parseContractError)(error);
652
+ // Only skip if it's a contract error (tag doesn't exist, etc.)
653
+ // Re-throw network errors
654
+ if (errorInfo.isNetworkError) {
655
+ throw new Error(`Network error fetching from RootTagger2: ${errorInfo.message}`);
656
+ }
657
+ // Contract errors are silently handled (tag doesn't exist is normal)
658
+ }
659
+ // Get addresses from RootResolver (legacy method for backward compatibility)
660
+ try {
661
+ const rootResolver = this.console.getContractRootResolver();
662
+ const result = await rootResolver.getAuthenticationAddresses(this.domainName);
663
+ // Extract addresses from the result
664
+ // Result is array of { algorithm, addr }
665
+ const legacyAddresses = result.map((item) => item.addr.toLowerCase());
666
+ addresses.push(...legacyAddresses);
667
+ }
668
+ catch (error) {
669
+ const errorInfo = (0, error_parser_1.parseContractError)(error);
670
+ // Only skip if it's a contract error
671
+ // Re-throw network errors
672
+ if (errorInfo.isNetworkError) {
673
+ throw new Error(`Network error fetching from RootResolver (legacy): ${errorInfo.message}`);
674
+ }
675
+ // Contract errors are silently handled
676
+ }
677
+ // Remove duplicates and return
678
+ return [...new Set(addresses)];
679
+ }
680
+ /**
681
+ * Add Solana wallet address to the domain's authenticated address tag
682
+ * @param solanaPrivateKey - Solana private key (base64 or base58 encoded string)
683
+ * @returns Transaction result with success status and transaction hash
684
+ */
685
+ async addSolanaWallet(solanaPrivateKey) {
686
+ try {
687
+ // Import Solana libraries dynamically
688
+ const { Keypair } = await Promise.resolve().then(() => __importStar(require('@solana/web3.js')));
689
+ const nacl = await Promise.resolve().then(() => __importStar(require('tweetnacl')));
690
+ const { decodeUTF8 } = await Promise.resolve().then(() => __importStar(require('tweetnacl-util')));
691
+ // Parse Solana private key (support both base58 and base64)
692
+ let solanaWallet;
693
+ try {
694
+ // Try base58 first (most common format for Phantom)
695
+ const bs58 = await Promise.resolve().then(() => __importStar(require('bs58')));
696
+ const secretKey = bs58.default.decode(solanaPrivateKey);
697
+ solanaWallet = Keypair.fromSecretKey(secretKey);
698
+ }
699
+ catch {
700
+ // Try base64
701
+ try {
702
+ const secretKey = Buffer.from(solanaPrivateKey, 'base64');
703
+ solanaWallet = Keypair.fromSecretKey(secretKey);
704
+ }
705
+ catch {
706
+ // Try as JSON array
707
+ const secretKey = JSON.parse(solanaPrivateKey);
708
+ solanaWallet = Keypair.fromSecretKey(Uint8Array.from(secretKey));
709
+ }
710
+ }
711
+ // Get Solana address as bytes32
712
+ const solanaAddressBytes = '0x' + solanaWallet.publicKey.toBuffer().toString('hex');
713
+ // Get current timestamp
714
+ const signAt = Math.floor(Date.now() / 1000) - 30 * 60; // 30 minutes ago
715
+ // Prepare the request value
716
+ const value = {
717
+ addr: solanaAddressBytes,
718
+ domain: this.domainName,
719
+ signAt: signAt,
720
+ action: 0 // Action.Add
721
+ };
722
+ // Get domain owner's signer
723
+ const domainOwner = this.console.getSigner();
724
+ if (!domainOwner) {
725
+ throw new Error('Signer not set. Please call setSigner() first.');
726
+ }
727
+ // Get RootTagger2 contract
728
+ const rootTagger = this.console.getSignerContractRootResolver2();
729
+ const chainId = (await domainOwner.provider?.getNetwork())?.chainId;
730
+ // Define EIP-712 domain
731
+ const domain = {
732
+ name: 'Terminus DID Root Tagger',
733
+ version: '1',
734
+ chainId: chainId,
735
+ verifyingContract: await rootTagger.getAddress()
736
+ };
737
+ // Define EIP-712 types for Solana
738
+ const types = {
739
+ SolanaAuthAddressReq: [
740
+ { name: 'addr', type: 'bytes32' },
741
+ { name: 'domain', type: 'string' },
742
+ { name: 'signAt', type: 'uint256' },
743
+ { name: 'action', type: 'uint8' }
744
+ ]
745
+ };
746
+ // Sign by domain owner
747
+ const sigFromDomainOwner = await domainOwner.signTypedData(domain, types, value);
748
+ // Sign by the Solana wallet (different signature method)
749
+ const solanaMsg = 'prove ownership of Solana wallet ' +
750
+ solanaWallet.publicKey.toBase58() +
751
+ ' for Terminus DID ' +
752
+ this.domainName;
753
+ const sigFromAuthAddr = nacl.default.sign.detached(decodeUTF8(solanaMsg), solanaWallet.secretKey);
754
+ const sigFromAuthAddrHex = '0x' + Buffer.from(sigFromAuthAddr).toString('hex');
755
+ // Call contract
756
+ const tx = await rootTagger.updateSolanaWallet(value, sigFromDomainOwner, sigFromAuthAddrHex);
757
+ const receipt = await tx.wait();
758
+ return {
759
+ success: true,
760
+ transactionHash: receipt.hash,
761
+ gasUsed: receipt.gasUsed,
762
+ blockNumber: receipt.blockNumber,
763
+ data: {
764
+ address: solanaWallet.publicKey.toBase58(),
765
+ addressHex: solanaAddressBytes
766
+ }
767
+ };
768
+ }
769
+ catch (error) {
770
+ const errorInfo = (0, error_parser_1.parseContractError)(error);
771
+ // Always throw network errors
772
+ if (errorInfo.isNetworkError) {
773
+ throw new Error(`Network error: ${errorInfo.message}`);
774
+ }
775
+ return {
776
+ success: false,
777
+ transactionHash: '',
778
+ error: errorInfo.message
779
+ };
780
+ }
781
+ }
782
+ /**
783
+ * Remove Solana wallet address from the domain's authenticated address tag
784
+ * @param solanaPrivateKey - Solana private key (base64 or base58 encoded string)
785
+ * @returns Transaction result with success status and transaction hash
786
+ */
787
+ async removeSolanaWallet(solanaPrivateKey) {
788
+ try {
789
+ // Import Solana libraries dynamically
790
+ const { Keypair } = await Promise.resolve().then(() => __importStar(require('@solana/web3.js')));
791
+ // Parse Solana private key
792
+ let solanaWallet;
793
+ try {
794
+ // Try base58 first
795
+ const bs58 = await Promise.resolve().then(() => __importStar(require('bs58')));
796
+ const secretKey = bs58.default.decode(solanaPrivateKey);
797
+ solanaWallet = Keypair.fromSecretKey(secretKey);
798
+ }
799
+ catch {
800
+ // Try base64
801
+ try {
802
+ const secretKey = Buffer.from(solanaPrivateKey, 'base64');
803
+ solanaWallet = Keypair.fromSecretKey(secretKey);
804
+ }
805
+ catch {
806
+ // Try as JSON array
807
+ const secretKey = JSON.parse(solanaPrivateKey);
808
+ solanaWallet = Keypair.fromSecretKey(Uint8Array.from(secretKey));
809
+ }
810
+ }
811
+ // Get Solana address as bytes32
812
+ const solanaAddressBytes = '0x' + solanaWallet.publicKey.toBuffer().toString('hex');
813
+ // Get current timestamp
814
+ const signAt = Math.floor(Date.now() / 1000) - 30 * 60; // 30 minutes ago
815
+ // Prepare the request value
816
+ const value = {
817
+ addr: solanaAddressBytes,
818
+ domain: this.domainName,
819
+ signAt: signAt,
820
+ action: 1 // Action.Remove
821
+ };
822
+ // Get domain owner's signer
823
+ const domainOwner = this.console.getSigner();
824
+ if (!domainOwner) {
825
+ throw new Error('Signer not set. Please call setSigner() first.');
826
+ }
827
+ // Get RootTagger2 contract
828
+ const rootTagger = this.console.getSignerContractRootResolver2();
829
+ const chainId = (await domainOwner.provider?.getNetwork())?.chainId;
830
+ // Define EIP-712 domain
831
+ const domain = {
832
+ name: 'Terminus DID Root Tagger',
833
+ version: '1',
834
+ chainId: chainId,
835
+ verifyingContract: await rootTagger.getAddress()
836
+ };
837
+ // Define EIP-712 types for Solana
838
+ const types = {
839
+ SolanaAuthAddressReq: [
840
+ { name: 'addr', type: 'bytes32' },
841
+ { name: 'domain', type: 'string' },
842
+ { name: 'signAt', type: 'uint256' },
843
+ { name: 'action', type: 'uint8' }
844
+ ]
845
+ };
846
+ // Sign by domain owner
847
+ const sigFromDomainOwner = await domainOwner.signTypedData(domain, types, value);
848
+ // For remove action, signature from address is not required (pass empty bytes)
849
+ const sigFromAuthAddr = '0x';
850
+ // Call contract
851
+ const tx = await rootTagger.updateSolanaWallet(value, sigFromDomainOwner, sigFromAuthAddr);
852
+ const receipt = await tx.wait();
853
+ return {
854
+ success: true,
855
+ transactionHash: receipt.hash,
856
+ gasUsed: receipt.gasUsed,
857
+ blockNumber: receipt.blockNumber,
858
+ data: {
859
+ address: solanaWallet.publicKey.toBase58(),
860
+ addressHex: solanaAddressBytes
861
+ }
862
+ };
863
+ }
864
+ catch (error) {
865
+ const errorInfo = (0, error_parser_1.parseContractError)(error);
866
+ // Always throw network errors
867
+ if (errorInfo.isNetworkError) {
868
+ throw new Error(`Network error: ${errorInfo.message}`);
869
+ }
870
+ return {
871
+ success: false,
872
+ transactionHash: '',
873
+ error: errorInfo.message
874
+ };
875
+ }
876
+ }
877
+ /**
878
+ * Get all Solana wallet addresses for the domain
879
+ * @returns Array of Solana wallet addresses (in base58 format)
880
+ */
881
+ async getSolanaWallets() {
882
+ try {
883
+ const { PublicKey } = await Promise.resolve().then(() => __importStar(require('@solana/web3.js')));
884
+ const rootTagger = this.console.getContractRootResolver2();
885
+ const result = await rootTagger.getSolanaWallets(this.domainName);
886
+ // Extract addresses from the result and convert to base58
887
+ // Result is array of { algorithm, addr } where addr is bytes32
888
+ return result.map((item) => {
889
+ // Remove 0x prefix and convert hex to buffer
890
+ const hexStr = item.addr.startsWith('0x')
891
+ ? item.addr.slice(2)
892
+ : item.addr;
893
+ const buffer = Buffer.from(hexStr, 'hex');
894
+ // Convert to Solana public key and then to base58
895
+ return new PublicKey(buffer).toBase58();
896
+ });
897
+ }
898
+ catch (error) {
899
+ const errorInfo = (0, error_parser_1.parseContractError)(error);
900
+ // Only skip if it's a contract error (tag doesn't exist is normal)
901
+ // Re-throw network errors
902
+ if (errorInfo.isNetworkError) {
903
+ throw new Error(`Network error fetching Solana wallets: ${errorInfo.message}`);
904
+ }
905
+ // For contract errors, return empty array (tag doesn't exist is normal)
906
+ return [];
907
+ }
908
+ }
909
+ // ========================================
910
+ // Tag Management
911
+ // ========================================
912
+ /**
913
+ * Create a Tag context for advanced Tag operations
914
+ * @param fromDomain The domain that defines the Tag (defaults to current domain)
915
+ * @returns TagContext instance
916
+ *
917
+ * @example
918
+ * // Use current domain as the Tag definer
919
+ * const tagCtx = domain.tag();
920
+ *
921
+ * // Use a specific domain as the Tag definer (cross-domain operations)
922
+ * const tagCtx = domain.tag('parent.com');
923
+ */
924
+ tag(fromDomain = this.domainName) {
925
+ return new tag_context_1.TagContext(this.console, fromDomain);
926
+ }
927
+ // ========================================
928
+ // Simplified Tag Operations (High-Level API)
929
+ // ========================================
930
+ /**
931
+ * Set the tagger (manager) for a Tag
932
+ * Only the domain owner can set the tagger
933
+ *
934
+ * @param tagName Tag name
935
+ * @param taggerAddress Address of the tagger (manager)
936
+ * @returns Transaction result
937
+ *
938
+ * @example
939
+ * // Set a specific address as the tagger
940
+ * await domain.setTagger('email', '0x1234...');
941
+ *
942
+ * // Set zero address to allow anyone to manage
943
+ * await domain.setTagger('email', '0x0000000000000000000000000000000000000000');
944
+ */
945
+ async setTagger(tagName, taggerAddress) {
946
+ return await this.tag().setTagger(tagName, taggerAddress);
947
+ }
948
+ /**
949
+ * Get the tagger (manager) address for a Tag
950
+ *
951
+ * @param tagName Tag name
952
+ * @returns Tagger address (returns zero address if no tagger is set)
953
+ *
954
+ * @example
955
+ * const tagger = await domain.getTagger('email');
956
+ * console.log('Tagger address:', tagger);
957
+ */
958
+ async getTagger(tagName) {
959
+ return await this.tag().getTagger(tagName);
960
+ }
961
+ /**
962
+ * Define a simple Tag type
963
+ * Only supports common simple types; use tag() for complex types
964
+ *
965
+ * @param tagName Tag name
966
+ * @param type Supported simple type
967
+ * @returns Transaction result
968
+ *
969
+ * @example
970
+ * await domain.defineSimpleTag('email', 'string');
971
+ * await domain.defineSimpleTag('age', 'uint8');
972
+ * await domain.defineSimpleTag('verified', 'bool');
973
+ * await domain.defineSimpleTag('wallets', 'address[]');
974
+ */
975
+ async defineSimpleTag(tagName, type) {
976
+ const tagCtx = this.tag();
977
+ // Type mapping
978
+ let tagType;
979
+ switch (type) {
980
+ case 'string':
981
+ tagType = tag_type_builder_1.TagTypeBuilder.string();
982
+ break;
983
+ case 'address':
984
+ tagType = tag_type_builder_1.TagTypeBuilder.address();
985
+ break;
986
+ case 'bool':
987
+ tagType = tag_type_builder_1.TagTypeBuilder.bool();
988
+ break;
989
+ case 'uint8':
990
+ tagType = tag_type_builder_1.TagTypeBuilder.uint8();
991
+ break;
992
+ case 'uint16':
993
+ tagType = tag_type_builder_1.TagTypeBuilder.uint16();
994
+ break;
995
+ case 'uint32':
996
+ tagType = tag_type_builder_1.TagTypeBuilder.uint32();
997
+ break;
998
+ case 'uint64':
999
+ tagType = tag_type_builder_1.TagTypeBuilder.uint64();
1000
+ break;
1001
+ case 'uint128':
1002
+ tagType = tag_type_builder_1.TagTypeBuilder.uint128();
1003
+ break;
1004
+ case 'uint256':
1005
+ tagType = tag_type_builder_1.TagTypeBuilder.uint256();
1006
+ break;
1007
+ case 'int8':
1008
+ tagType = tag_type_builder_1.TagTypeBuilder.int8();
1009
+ break;
1010
+ case 'int16':
1011
+ tagType = tag_type_builder_1.TagTypeBuilder.int16();
1012
+ break;
1013
+ case 'int32':
1014
+ tagType = tag_type_builder_1.TagTypeBuilder.int32();
1015
+ break;
1016
+ case 'int64':
1017
+ tagType = tag_type_builder_1.TagTypeBuilder.int64();
1018
+ break;
1019
+ case 'int128':
1020
+ tagType = tag_type_builder_1.TagTypeBuilder.int128();
1021
+ break;
1022
+ case 'int256':
1023
+ tagType = tag_type_builder_1.TagTypeBuilder.int256();
1024
+ break;
1025
+ case 'bytes':
1026
+ tagType = tag_type_builder_1.TagTypeBuilder.bytes();
1027
+ break;
1028
+ case 'bytes32':
1029
+ tagType = tag_type_builder_1.TagTypeBuilder.bytes32();
1030
+ break;
1031
+ case 'string[]':
1032
+ tagType = tag_type_builder_1.TagTypeBuilder.stringArray();
1033
+ break;
1034
+ case 'address[]':
1035
+ tagType = tag_type_builder_1.TagTypeBuilder.addressArray();
1036
+ break;
1037
+ case 'uint256[]':
1038
+ tagType = tag_type_builder_1.TagTypeBuilder.uint256Array();
1039
+ break;
1040
+ default:
1041
+ throw new Error(`Unsupported simple type: ${type}. Use tag() for complex types.`);
1042
+ }
1043
+ return await tagCtx.defineTag(tagName, tagType);
1044
+ }
1045
+ /**
1046
+ * Set a Tag value for the current domain
1047
+ * from = current domain, to = current domain
1048
+ *
1049
+ * @param tagName Tag name
1050
+ * @param value Tag value
1051
+ * @returns Transaction result
1052
+ *
1053
+ * @example
1054
+ * await domain.setTag('email', 'user@example.com');
1055
+ * await domain.setTag('links', ['https://...', 'https://...']);
1056
+ */
1057
+ async setTag(tagName, value) {
1058
+ return await this.tag().setTag(this.domainName, tagName, value);
1059
+ }
1060
+ /**
1061
+ * Get a Tag value for the current domain
1062
+ * from = current domain, to = current domain
1063
+ *
1064
+ * @param tagName Tag name
1065
+ * @returns Tag value, or null if not found
1066
+ */
1067
+ async getTag(tagName) {
1068
+ return await this.tag().getTag(this.domainName, tagName);
1069
+ }
1070
+ /**
1071
+ * Remove a Tag from the current domain
1072
+ * from = current domain, to = current domain
1073
+ *
1074
+ * @param tagName Tag name
1075
+ * @returns Transaction result
1076
+ */
1077
+ async removeTag(tagName) {
1078
+ return await this.tag().removeTag(this.domainName, tagName);
1079
+ }
1080
+ /**
1081
+ * Get all Tags for the current domain
1082
+ * @returns Array of Tags with name and value
1083
+ */
1084
+ async getAllTags() {
1085
+ return await this.tag().getAllTags(this.domainName);
1086
+ }
1087
+ /**
1088
+ * Get all Tag type names defined by the current domain
1089
+ * @returns Array of Tag names
1090
+ */
1091
+ async getDefinedTags() {
1092
+ return await this.tag().getDefinedTagNames();
1093
+ }
1094
+ }
1095
+ exports.DomainContext = DomainContext;
1096
+ /*
1097
+ * Helper function to convert IPv4 string to bytes4 format
1098
+ * @param ipv4 - IPv4 address string (e.g., "192.168.1.1")
1099
+ * @returns bytes4 format as hex string with '0x' prefix
1100
+ */
1101
+ function ipv4ToBytes4(ipv4) {
1102
+ // Validate IPv4 format
1103
+ const ipv4Regex = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
1104
+ const match = ipv4.match(ipv4Regex);
1105
+ if (!match) {
1106
+ throw new Error('Invalid IPv4 address format');
1107
+ }
1108
+ // Parse and validate each octet (0-255)
1109
+ const octets = match.slice(1, 5).map((octet) => {
1110
+ const num = parseInt(octet, 10);
1111
+ if (num < 0 || num > 255) {
1112
+ throw new Error(`Invalid IPv4 octet: ${octet}. Must be between 0 and 255`);
1113
+ }
1114
+ return num;
1115
+ });
1116
+ // Convert to hex bytes4 format
1117
+ const hexString = octets
1118
+ .map((octet) => octet.toString(16).padStart(2, '0'))
1119
+ .join('');
1120
+ return '0x' + hexString;
1121
+ }
1122
+ /*
1123
+ * Helper function to convert bytes4 format to IPv4 string
1124
+ * @param bytes4Hex - bytes4 format as hex string (with or without '0x' prefix)
1125
+ * @returns IPv4 address string (e.g., "192.168.1.1")
1126
+ */
1127
+ function bytes4ToIpv4(bytes4Hex) {
1128
+ // Remove '0x' prefix if present
1129
+ const hexString = bytes4Hex.startsWith('0x')
1130
+ ? bytes4Hex.slice(2)
1131
+ : bytes4Hex;
1132
+ // Validate hex string length (should be 8 characters for 4 bytes)
1133
+ if (hexString.length !== 8) {
1134
+ throw new Error(`Invalid bytes4 format: expected 8 hex characters, got ${hexString.length}`);
1135
+ }
1136
+ // Convert each pair of hex characters to decimal
1137
+ const octets = [];
1138
+ for (let i = 0; i < 8; i += 2) {
1139
+ const octet = parseInt(hexString.slice(i, i + 2), 16);
1140
+ octets.push(octet);
1141
+ }
1142
+ return octets.join('.');
1143
+ }
1144
+ /*
1145
+ * Helper function to convert PEM format to DER hex format
1146
+ * @param pem - PEM formatted string (with BEGIN/END markers)
1147
+ * @returns DER format as hex string with '0x' prefix
1148
+ */
1149
+ function pemToDer(pem) {
1150
+ // Remove PEM headers, footers, and whitespace
1151
+ const base64 = pem
1152
+ .replace(/-----BEGIN.*?-----/g, '')
1153
+ .replace(/-----END.*?-----/g, '')
1154
+ .replace(/\s/g, '');
1155
+ // Convert base64 to hex
1156
+ let hexString;
1157
+ // Check if running in Node.js or browser
1158
+ if (typeof Buffer !== 'undefined') {
1159
+ // Node.js environment
1160
+ const derBuffer = Buffer.from(base64, 'base64');
1161
+ hexString = derBuffer.toString('hex');
1162
+ }
1163
+ else {
1164
+ // Browser environment
1165
+ const binaryString = atob(base64);
1166
+ hexString = Array.from(binaryString, (char) => char.charCodeAt(0).toString(16).padStart(2, '0')).join('');
1167
+ }
1168
+ // Convert to hex string with 0x prefix
1169
+ return '0x' + hexString;
1170
+ }
1171
+ /*
1172
+ * Helper function to convert DER hex format to PEM PKCS#8 format
1173
+ * @param derHex - DER format as hex string (with or without '0x' prefix)
1174
+ * @returns PEM formatted public key string
1175
+ */
1176
+ function derToPem(derHex) {
1177
+ // Remove '0x' prefix if present
1178
+ const hexString = derHex.startsWith('0x') ? derHex.slice(2) : derHex;
1179
+ // Convert hex to base64
1180
+ let base64;
1181
+ // Check if running in Node.js or browser
1182
+ if (typeof Buffer !== 'undefined') {
1183
+ // Node.js environment
1184
+ const derBuffer = Buffer.from(hexString, 'hex');
1185
+ base64 = derBuffer.toString('base64');
1186
+ }
1187
+ else {
1188
+ // Browser environment
1189
+ // Convert hex string to byte array
1190
+ const bytes = new Uint8Array(hexString.length / 2);
1191
+ for (let i = 0; i < hexString.length; i += 2) {
1192
+ bytes[i / 2] = parseInt(hexString.substr(i, 2), 16);
1193
+ }
1194
+ // Convert byte array to binary string
1195
+ const binaryString = String.fromCharCode(...bytes);
1196
+ // Convert to base64
1197
+ base64 = btoa(binaryString);
1198
+ }
1199
+ // Split base64 into 64-character lines for PEM format
1200
+ const lines = [];
1201
+ for (let i = 0; i < base64.length; i += 64) {
1202
+ lines.push(base64.slice(i, i + 64));
1203
+ }
1204
+ // Construct PEM format with headers and footers
1205
+ return ('-----BEGIN PUBLIC KEY-----\n' +
1206
+ lines.join('\n') +
1207
+ '\n-----END PUBLIC KEY-----');
1208
+ }
1209
+ //# sourceMappingURL=index.js.map