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