@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,190 @@
1
+ import OlaresID from '../src/index';
2
+ import { TagTypeBuilder } from '../src/utils/tag-type-builder';
3
+
4
+ // Helper function to wait for blockchain indexing
5
+ async function waitForIndexing(seconds: number = 3) {
6
+ console.log(`⏳ Waiting ${seconds} seconds for blockchain indexing...`);
7
+ await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
8
+ }
9
+
10
+ /**
11
+ * Example: Nested Tuple Tag Operations
12
+ * Demonstrates automatic object-to-array conversion for nested tuples
13
+ */
14
+
15
+ async function main() {
16
+ const domainName = process.argv[2];
17
+ if (!domainName) {
18
+ console.error(
19
+ 'Usage: npx ts-node examples/tag-nested-tuple.ts <domain-name>'
20
+ );
21
+ process.exit(1);
22
+ }
23
+
24
+ const privateKeyOrMnemonic = process.env.PRIVATE_KEY_OR_MNEMONIC;
25
+ if (!privateKeyOrMnemonic) {
26
+ console.error(
27
+ 'Error: PRIVATE_KEY_OR_MNEMONIC environment variable is required'
28
+ );
29
+ process.exit(1);
30
+ }
31
+
32
+ console.log('🚀 Nested Tuple Tag Example\n');
33
+ console.log(`Domain: ${domainName}\n`);
34
+
35
+ // Initialize
36
+ const olaresId = OlaresID.createTestnet();
37
+ await olaresId.setSigner(privateKeyOrMnemonic);
38
+ const domain = olaresId.domain(domainName);
39
+ const tagCtx = domain.tag();
40
+ const signerAddress = await olaresId.signer!.getAddress();
41
+
42
+ // ========================================
43
+ // Part 1: Define Nested Tuple Type
44
+ // ========================================
45
+ console.log('='.repeat(60));
46
+ console.log('Part 1: Define Nested Tuple Type');
47
+ console.log('='.repeat(60));
48
+
49
+ const profileType = TagTypeBuilder.tuple({
50
+ name: TagTypeBuilder.string(),
51
+ details: TagTypeBuilder.tuple({
52
+ age: TagTypeBuilder.uint8(),
53
+ verified: TagTypeBuilder.bool()
54
+ }),
55
+ contact: TagTypeBuilder.tuple({
56
+ email: TagTypeBuilder.string(),
57
+ phone: TagTypeBuilder.string()
58
+ })
59
+ });
60
+
61
+ try {
62
+ await tagCtx.defineTag('profile', profileType);
63
+ console.log('✅ Defined "profile" nested tuple tag\n');
64
+ } catch (error: any) {
65
+ if (error.message.includes('already been defined')) {
66
+ console.log('⚠️ "profile" tag already defined, skipping...\n');
67
+ } else {
68
+ throw error;
69
+ }
70
+ }
71
+
72
+ // Set tagger
73
+ await domain.setTagger('profile', signerAddress);
74
+ console.log(`✅ Set tagger for "profile" to ${signerAddress}\n`);
75
+
76
+ // ========================================
77
+ // Part 2: Set Nested Tuple using Object
78
+ // ========================================
79
+ console.log('='.repeat(60));
80
+ console.log('Part 2: Set Nested Tuple (Object Notation)');
81
+ console.log('='.repeat(60));
82
+
83
+ const profileValue = {
84
+ name: 'Alice Johnson',
85
+ details: {
86
+ age: 30,
87
+ verified: true
88
+ },
89
+ contact: {
90
+ email: 'alice@example.com',
91
+ phone: '+1-555-0123'
92
+ }
93
+ };
94
+
95
+ console.log('📝 Setting nested tuple with object notation:');
96
+ console.log(JSON.stringify(profileValue, null, 2));
97
+
98
+ await tagCtx.setTag(domainName, 'profile', profileValue);
99
+ console.log('\n✅ Nested tuple set successfully!\n');
100
+ await waitForIndexing(3);
101
+
102
+ // ========================================
103
+ // Part 3: Get and Display Nested Tuple
104
+ // ========================================
105
+ console.log('='.repeat(60));
106
+ console.log('Part 3: Read Nested Tuple');
107
+ console.log('='.repeat(60));
108
+
109
+ const profile = await tagCtx.getTag(domainName, 'profile');
110
+ console.log('📖 Retrieved profile (raw array):');
111
+ console.log(
112
+ JSON.stringify(profile, (_, v) =>
113
+ typeof v === 'bigint' ? v.toString() : v
114
+ )
115
+ );
116
+
117
+ console.log('\n📖 Retrieved profile (parsed):');
118
+ console.log(` name: ${profile[0]}`);
119
+ console.log(` details.age: ${profile[1][0]}`);
120
+ console.log(` details.verified: ${profile[1][1]}`);
121
+ console.log(` contact.email: ${profile[2][0]}`);
122
+ console.log(` contact.phone: ${profile[2][1]}\n`);
123
+
124
+ // ========================================
125
+ // Part 4: Update Nested Field
126
+ // ========================================
127
+ console.log('='.repeat(60));
128
+ console.log('Part 4: Update Nested Field');
129
+ console.log('='.repeat(60));
130
+
131
+ console.log('🔄 Updating details.age from 30 to 31...\n');
132
+
133
+ const updatedProfile = {
134
+ name: profile[0],
135
+ details: {
136
+ age: 31, // Updated
137
+ verified: profile[1][1]
138
+ },
139
+ contact: {
140
+ email: profile[2][0],
141
+ phone: profile[2][1]
142
+ }
143
+ };
144
+
145
+ await tagCtx.setTag(domainName, 'profile', updatedProfile);
146
+ console.log('✅ Updated nested field\n');
147
+ await waitForIndexing(3);
148
+
149
+ // Verify update
150
+ const updatedProfileRead = await tagCtx.getTag(domainName, 'profile');
151
+ console.log('📖 Verified update:');
152
+ console.log(
153
+ ` details.age: ${updatedProfileRead[1][0]} (was 30, now 31)\n`
154
+ );
155
+
156
+ // ========================================
157
+ // Part 5: Array Notation (Still Supported)
158
+ // ========================================
159
+ console.log('='.repeat(60));
160
+ console.log('Part 5: Array Notation (Alternative)');
161
+ console.log('='.repeat(60));
162
+
163
+ console.log('📝 Setting with array notation (for comparison):\n');
164
+
165
+ await tagCtx.setTag(domainName, 'profile', [
166
+ 'Bob Smith', // name
167
+ [25, false], // details: {age: 25, verified: false}
168
+ ['bob@example.com', '+1-555-9999'] // contact: {email, phone}
169
+ ]);
170
+
171
+ console.log('✅ Array notation also works!\n');
172
+ await waitForIndexing(3);
173
+
174
+ const profileArray = await tagCtx.getTag(domainName, 'profile');
175
+ console.log('📖 Retrieved (set via array notation):');
176
+ console.log(` name: ${profileArray[0]}`);
177
+ console.log(` details.age: ${profileArray[1][0]}`);
178
+ console.log(` details.verified: ${profileArray[1][1]}\n`);
179
+
180
+ console.log('='.repeat(60));
181
+ console.log('✅ All nested tuple operations completed!');
182
+ console.log('='.repeat(60));
183
+ console.log('\n💡 Key Takeaways:');
184
+ console.log(' • Objects are automatically converted to arrays');
185
+ console.log(' • Nested tuples work seamlessly');
186
+ console.log(' • No need to provide field names manually');
187
+ console.log(' • Array notation is still supported for flexibility\n');
188
+ }
189
+
190
+ main().catch(console.error);
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Simple Tag Example
3
+ *
4
+ * This example shows the simplest way to use Tags:
5
+ * - Define a few simple tags
6
+ * - Set and get values
7
+ * - No complex types or arrays
8
+ *
9
+ * Prerequisites:
10
+ * - Set PRIVATE_KEY_OR_MNEMONIC environment variable
11
+ * - You must own the domain you're operating on
12
+ *
13
+ * Run:
14
+ * export PRIVATE_KEY_OR_MNEMONIC="your private key or mnemonic"
15
+ * npx ts-node examples/tag-simple.ts <domain-name>
16
+ */
17
+
18
+ import OlaresID from '../src/index';
19
+
20
+ async function main() {
21
+ // Initialize
22
+ const olaresId = OlaresID.createTestnet();
23
+ const privateKeyOrMnemonic = process.env.PRIVATE_KEY_OR_MNEMONIC;
24
+
25
+ if (!privateKeyOrMnemonic) {
26
+ console.error(
27
+ '❌ Error: PRIVATE_KEY_OR_MNEMONIC environment variable not set'
28
+ );
29
+ process.exit(1);
30
+ }
31
+
32
+ await olaresId.setSigner(privateKeyOrMnemonic);
33
+
34
+ const domainName = process.argv[2];
35
+ if (!domainName) {
36
+ console.error('❌ Error: Please provide a domain name');
37
+ console.log('Usage: npx ts-node examples/tag-simple.ts <domain-name>');
38
+ process.exit(1);
39
+ }
40
+
41
+ const domain = olaresId.domain(domainName);
42
+ const signerAddress = await olaresId.getSigner().getAddress();
43
+ console.log(`\n🏷️ Simple Tag Example for: ${domainName}`);
44
+ console.log(`👤 Signer: ${signerAddress}\n`);
45
+
46
+ // Step 1: Define tag types (skip if already defined)
47
+ console.log('1️⃣ Defining tag types...');
48
+
49
+ try {
50
+ await domain.defineSimpleTag('bio', 'string');
51
+ console.log(' ✅ Defined "bio" (string)');
52
+ await new Promise((resolve) => setTimeout(resolve, 3000));
53
+ } catch (error: any) {
54
+ if (
55
+ error.message?.includes('RedefinedTag') ||
56
+ error.message?.includes('already been defined')
57
+ ) {
58
+ console.log(' ⚠️ "bio" already defined, skipping...');
59
+ } else {
60
+ throw error;
61
+ }
62
+ }
63
+
64
+ try {
65
+ await domain.defineSimpleTag('followers', 'uint32');
66
+ console.log(' ✅ Defined "followers" (uint32)');
67
+ await new Promise((resolve) => setTimeout(resolve, 3000));
68
+ } catch (error: any) {
69
+ if (
70
+ error.message?.includes('RedefinedTag') ||
71
+ error.message?.includes('already been defined')
72
+ ) {
73
+ console.log(' ⚠️ "followers" already defined, skipping...');
74
+ } else {
75
+ throw error;
76
+ }
77
+ }
78
+
79
+ try {
80
+ await domain.defineSimpleTag('premium', 'bool');
81
+ console.log(' ✅ Defined "premium" (bool)\n');
82
+ await new Promise((resolve) => setTimeout(resolve, 3000));
83
+ } catch (error: any) {
84
+ if (
85
+ error.message?.includes('RedefinedTag') ||
86
+ error.message?.includes('already been defined')
87
+ ) {
88
+ console.log(' ⚠️ "premium" already defined, skipping...\n');
89
+ } else {
90
+ throw error;
91
+ }
92
+ }
93
+
94
+ // Step 2: Set taggers (IMPORTANT!)
95
+ console.log('2️⃣ Setting taggers (required before setting values)...');
96
+ await domain.setTagger('bio', signerAddress);
97
+ console.log(' ✅ Set tagger for "bio"');
98
+
99
+ await domain.setTagger('followers', signerAddress);
100
+ console.log(' ✅ Set tagger for "followers"');
101
+
102
+ await domain.setTagger('premium', signerAddress);
103
+ console.log(' ✅ Set tagger for "premium"\n');
104
+
105
+ // Wait for indexing
106
+ await new Promise((resolve) => setTimeout(resolve, 5000));
107
+
108
+ // Step 3: Set values
109
+ console.log('3️⃣ Setting tag values...');
110
+ await domain.setTag('bio', 'Web3 developer and blockchain enthusiast');
111
+ console.log(' ✅ Set "bio"');
112
+
113
+ await domain.setTag('followers', 1250);
114
+ console.log(' ✅ Set "followers"');
115
+
116
+ await domain.setTag('premium', true);
117
+ console.log(' ✅ Set "premium"\n');
118
+
119
+ // Wait for indexing
120
+ await new Promise((resolve) => setTimeout(resolve, 5000));
121
+
122
+ // Step 4: Get values
123
+ console.log('4️⃣ Reading tag values...');
124
+ const bio = await domain.getTag('bio');
125
+ const followers = await domain.getTag('followers');
126
+ const premium = await domain.getTag('premium');
127
+
128
+ console.log(` bio: "${bio}"`);
129
+ console.log(` followers: ${followers}`);
130
+ console.log(` premium: ${premium}\n`);
131
+
132
+ // Step 5: Update a value
133
+ console.log('5️⃣ Updating "followers" count...');
134
+ await domain.setTag('followers', 1350);
135
+ console.log(' ✅ Updated "followers"\n');
136
+
137
+ // Wait for indexing
138
+ await new Promise((resolve) => setTimeout(resolve, 5000));
139
+
140
+ const updatedFollowers = await domain.getTag('followers');
141
+ console.log(` New followers count: ${updatedFollowers}\n`);
142
+
143
+ console.log('✅ Simple Tag Example Completed!\n');
144
+ }
145
+
146
+ main().catch((error) => {
147
+ console.error('❌ Error:', error.message);
148
+ process.exit(1);
149
+ });
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Tag Tagger Management Example
3
+ *
4
+ * This example demonstrates how to set and get taggers (managers) for Tags.
5
+ * A tagger is an address that has permission to manage a specific Tag.
6
+ *
7
+ * Prerequisites:
8
+ * - Set PRIVATE_KEY_OR_MNEMONIC environment variable (domain owner)
9
+ * - You must own the domain you're operating on
10
+ *
11
+ * Run:
12
+ * export PRIVATE_KEY_OR_MNEMONIC="your private key or mnemonic"
13
+ * npx ts-node examples/tag-tagger.ts <domain-name>
14
+ */
15
+
16
+ import OlaresID from '../src/index';
17
+
18
+ async function main() {
19
+ // Initialize OlaresID
20
+ const olaresId = OlaresID.createTestnet();
21
+
22
+ // Get private key or mnemonic from environment
23
+ const privateKeyOrMnemonic = process.env.PRIVATE_KEY_OR_MNEMONIC;
24
+ if (!privateKeyOrMnemonic) {
25
+ console.error(
26
+ '❌ Error: PRIVATE_KEY_OR_MNEMONIC environment variable not set'
27
+ );
28
+ console.log(
29
+ 'Usage: export PRIVATE_KEY_OR_MNEMONIC="your private key or mnemonic"'
30
+ );
31
+ process.exit(1);
32
+ }
33
+
34
+ await olaresId.setSigner(privateKeyOrMnemonic);
35
+ const signerAddress = await olaresId.getSigner().getAddress();
36
+ console.log(`✅ Signer address: ${signerAddress}\n`);
37
+
38
+ // Get domain name from command line
39
+ const domainName = process.argv[2];
40
+ if (!domainName) {
41
+ console.error('❌ Error: Please provide a domain name');
42
+ console.log('Usage: npx ts-node examples/tag-tagger.ts <domain-name>');
43
+ process.exit(1);
44
+ }
45
+
46
+ const domain = olaresId.domain(domainName);
47
+ console.log(`🏷️ Managing Taggers for domain: ${domainName}\n`);
48
+
49
+ // ========================================
50
+ // Part 1: Define a Tag
51
+ // ========================================
52
+ console.log('='.repeat(60));
53
+ console.log('Part 1: Define a Tag');
54
+ console.log('='.repeat(60));
55
+
56
+ const tagName = 'userStatus';
57
+
58
+ try {
59
+ console.log(`📝 Defining "${tagName}" tag (type: string)...`);
60
+ await domain.defineSimpleTag(tagName, 'string');
61
+ console.log(`✅ "${tagName}" tag defined\n`);
62
+
63
+ // Wait for indexing
64
+ await new Promise((resolve) => setTimeout(resolve, 3000));
65
+ } catch (error: any) {
66
+ console.error(`❌ Error defining tag: ${error.message}\n`);
67
+ }
68
+
69
+ // ========================================
70
+ // Part 2: Check Initial Tagger
71
+ // ========================================
72
+ console.log('='.repeat(60));
73
+ console.log('Part 2: Check Initial Tagger');
74
+ console.log('='.repeat(60));
75
+
76
+ try {
77
+ const initialTagger = await domain.getTagger(tagName);
78
+ console.log(`📖 Current tagger: ${initialTagger}`);
79
+
80
+ if (initialTagger === '0x0000000000000000000000000000000000000000') {
81
+ console.log(' ℹ️ No specific tagger set (zero address)');
82
+ console.log(' ℹ️ No one can manage this tag (disabled)\n');
83
+ } else {
84
+ console.log(` ℹ️ Tagger is set to: ${initialTagger}\n`);
85
+ }
86
+ } catch (error: any) {
87
+ console.error(`❌ Error getting tagger: ${error.message}\n`);
88
+ }
89
+
90
+ // ========================================
91
+ // Part 3: Set a Specific Tagger
92
+ // ========================================
93
+ console.log('='.repeat(60));
94
+ console.log('Part 3: Set a Specific Tagger');
95
+ console.log('='.repeat(60));
96
+
97
+ // Example tagger address (replace with your own)
98
+ const taggerAddress = '0x1234567890123456789012345678901234567890';
99
+
100
+ try {
101
+ console.log(`📝 Setting tagger to: ${taggerAddress}...`);
102
+ const result = await domain.setTagger(tagName, taggerAddress);
103
+ console.log(`✅ Tagger set successfully`);
104
+ console.log(` Transaction hash: ${result.transactionHash}\n`);
105
+
106
+ // Wait for indexing
107
+ await new Promise((resolve) => setTimeout(resolve, 3000));
108
+
109
+ // Verify the tagger was set
110
+ const newTagger = await domain.getTagger(tagName);
111
+ console.log(`📖 Verified tagger: ${newTagger}`);
112
+
113
+ if (newTagger.toLowerCase() === taggerAddress.toLowerCase()) {
114
+ console.log(' ✅ Tagger correctly set!\n');
115
+ } else {
116
+ console.log(' ⚠️ Tagger mismatch!\n');
117
+ }
118
+ } catch (error: any) {
119
+ console.error(`❌ Error setting tagger: ${error.message}\n`);
120
+ }
121
+
122
+ // ========================================
123
+ // Part 4: Set Tagger to Zero Address (Disable Tag Management)
124
+ // ========================================
125
+ console.log('='.repeat(60));
126
+ console.log('Part 4: Set Tagger to Zero Address (Disable Management)');
127
+ console.log('='.repeat(60));
128
+
129
+ const zeroAddress = '0x0000000000000000000000000000000000000000';
130
+
131
+ try {
132
+ console.log(
133
+ `📝 Setting tagger to zero address (disable management)...`
134
+ );
135
+ const result = await domain.setTagger(tagName, zeroAddress);
136
+ console.log(`✅ Tagger set to zero address`);
137
+ console.log(` Transaction hash: ${result.transactionHash}\n`);
138
+
139
+ // Wait for indexing
140
+ await new Promise((resolve) => setTimeout(resolve, 3000));
141
+
142
+ // Verify
143
+ const publicTagger = await domain.getTagger(tagName);
144
+ console.log(`📖 Verified tagger: ${publicTagger}`);
145
+
146
+ if (publicTagger === zeroAddress) {
147
+ console.log(
148
+ ' ✅ Tag management is now disabled (no one can set it)!\n'
149
+ );
150
+ }
151
+ } catch (error: any) {
152
+ console.error(`❌ Error setting tagger to zero: ${error.message}\n`);
153
+ }
154
+
155
+ // ========================================
156
+ // Part 5: Set Tagger to Self (Owner Only)
157
+ // ========================================
158
+ console.log('='.repeat(60));
159
+ console.log('Part 5: Set Tagger to Self (Owner Only)');
160
+ console.log('='.repeat(60));
161
+
162
+ try {
163
+ console.log(`📝 Setting tagger to signer address (owner only)...`);
164
+ const result = await domain.setTagger(tagName, signerAddress);
165
+ console.log(`✅ Tagger set to: ${signerAddress}`);
166
+ console.log(` Transaction hash: ${result.transactionHash}\n`);
167
+
168
+ // Wait for indexing
169
+ await new Promise((resolve) => setTimeout(resolve, 3000));
170
+
171
+ // Verify
172
+ const ownerTagger = await domain.getTagger(tagName);
173
+ console.log(`📖 Verified tagger: ${ownerTagger}`);
174
+
175
+ if (ownerTagger.toLowerCase() === signerAddress.toLowerCase()) {
176
+ console.log(' ✅ Only the owner can manage this tag now!\n');
177
+ }
178
+ } catch (error: any) {
179
+ console.error(`❌ Error setting tagger to self: ${error.message}\n`);
180
+ }
181
+
182
+ // ========================================
183
+ // Part 6: Using TagContext (Advanced)
184
+ // ========================================
185
+ console.log('='.repeat(60));
186
+ console.log('Part 6: Using TagContext (Advanced API)');
187
+ console.log('='.repeat(60));
188
+
189
+ try {
190
+ const tagCtx = domain.tag();
191
+
192
+ console.log('📖 Getting tagger using TagContext...');
193
+ const ctxTagger = await tagCtx.getTagger(tagName);
194
+ console.log(` Tagger: ${ctxTagger}`);
195
+
196
+ console.log('\n📝 Setting tagger back to zero using TagContext...');
197
+ const result = await tagCtx.setTagger(tagName, zeroAddress);
198
+ console.log(` ✅ Done: ${result.transactionHash}\n`);
199
+ } catch (error: any) {
200
+ console.error(`❌ Error with TagContext: ${error.message}\n`);
201
+ }
202
+
203
+ console.log('='.repeat(60));
204
+ console.log('✅ Tag Tagger Management Example Completed');
205
+ console.log('='.repeat(60));
206
+ console.log('\n💡 Key Points:');
207
+ console.log(' • Only domain owner can set taggers');
208
+ console.log(' • Zero address = disabled (no one can manage)');
209
+ console.log(' • Specific address = only that address can manage');
210
+ console.log(' • Use getTagger() to check who can manage a tag\n');
211
+ }
212
+
213
+ // Run the example
214
+ main().catch((error) => {
215
+ console.error('❌ Fatal error:', error);
216
+ process.exit(1);
217
+ });
@@ -0,0 +1,143 @@
1
+ import { TagAbiCodec } from '../src/utils/tag-abi-codec';
2
+
3
+ /**
4
+ * Test script for TagAbiCodec nested tuple conversion
5
+ * Tests the parseTupleFields and convertObjectToArray functions
6
+ */
7
+
8
+ console.log('='.repeat(60));
9
+ console.log('TagAbiCodec Nested Tuple Conversion Test');
10
+ console.log('='.repeat(60));
11
+
12
+ // Test 1: Simple tuple
13
+ console.log('\n1. Simple Tuple:');
14
+ console.log(' ABI Type: tuple(string,uint8)');
15
+ const obj1 = { name: 'Alice', age: 30 };
16
+ console.log(' Input:', JSON.stringify(obj1));
17
+ const encoded1 = TagAbiCodec.encode('tuple(string,uint8)', obj1);
18
+ console.log(' Encoded:', encoded1);
19
+ const decoded1 = TagAbiCodec.decode('tuple(string,uint8)', encoded1);
20
+ console.log(
21
+ ' Decoded:',
22
+ JSON.stringify(decoded1, (_, v) =>
23
+ typeof v === 'bigint' ? v.toString() : v
24
+ )
25
+ );
26
+
27
+ // Test 2: Nested tuple (1 level)
28
+ console.log('\n2. Nested Tuple (1 level):');
29
+ console.log(' ABI Type: tuple(string,tuple(uint8,bool))');
30
+ const obj2 = {
31
+ name: 'Alice',
32
+ details: {
33
+ age: 30,
34
+ verified: true
35
+ }
36
+ };
37
+ console.log(' Input:', JSON.stringify(obj2));
38
+ const encoded2 = TagAbiCodec.encode('tuple(string,tuple(uint8,bool))', obj2);
39
+ console.log(' Encoded:', encoded2);
40
+ const decoded2 = TagAbiCodec.decode(
41
+ 'tuple(string,tuple(uint8,bool))',
42
+ encoded2
43
+ );
44
+ console.log(
45
+ ' Decoded:',
46
+ JSON.stringify(decoded2, (_, v) =>
47
+ typeof v === 'bigint' ? v.toString() : v
48
+ )
49
+ );
50
+
51
+ // Test 3: Nested tuple (2 levels)
52
+ console.log('\n3. Nested Tuple (2 levels):');
53
+ console.log(
54
+ ' ABI Type: tuple(string,tuple(uint8,bool),tuple(string,string))'
55
+ );
56
+ const obj3 = {
57
+ name: 'Alice',
58
+ details: {
59
+ age: 30,
60
+ verified: true
61
+ },
62
+ contact: {
63
+ email: 'alice@example.com',
64
+ phone: '+1-555-0123'
65
+ }
66
+ };
67
+ console.log(' Input:', JSON.stringify(obj3, null, 2));
68
+ const encoded3 = TagAbiCodec.encode(
69
+ 'tuple(string,tuple(uint8,bool),tuple(string,string))',
70
+ obj3
71
+ );
72
+ console.log(' Encoded:', encoded3);
73
+ const decoded3 = TagAbiCodec.decode(
74
+ 'tuple(string,tuple(uint8,bool),tuple(string,string))',
75
+ encoded3
76
+ );
77
+ console.log(
78
+ ' Decoded:',
79
+ JSON.stringify(
80
+ decoded3,
81
+ (_, v) => (typeof v === 'bigint' ? v.toString() : v),
82
+ 2
83
+ )
84
+ );
85
+
86
+ // Test 4: Array notation (still supported)
87
+ console.log('\n4. Array Notation (still supported):');
88
+ console.log(' ABI Type: tuple(string,tuple(uint8,bool))');
89
+ const arr4 = ['Bob', [25, false]];
90
+ console.log(' Input:', JSON.stringify(arr4));
91
+ const encoded4 = TagAbiCodec.encode('tuple(string,tuple(uint8,bool))', arr4);
92
+ console.log(' Encoded:', encoded4);
93
+ const decoded4 = TagAbiCodec.decode(
94
+ 'tuple(string,tuple(uint8,bool))',
95
+ encoded4
96
+ );
97
+ console.log(
98
+ ' Decoded:',
99
+ JSON.stringify(decoded4, (_, v) =>
100
+ typeof v === 'bigint' ? v.toString() : v
101
+ )
102
+ );
103
+
104
+ // Test 5: Complex nested structure
105
+ console.log('\n5. Complex Nested Structure:');
106
+ console.log(' ABI Type: tuple(string,tuple(tuple(uint8,bool),address))');
107
+ const obj5 = {
108
+ name: 'Charlie',
109
+ data: {
110
+ info: {
111
+ age: 40,
112
+ active: true
113
+ },
114
+ wallet: '0x1234567890123456789012345678901234567890'
115
+ }
116
+ };
117
+ console.log(' Input:', JSON.stringify(obj5, null, 2));
118
+ const encoded5 = TagAbiCodec.encode(
119
+ 'tuple(string,tuple(tuple(uint8,bool),address))',
120
+ obj5
121
+ );
122
+ console.log(' Encoded:', encoded5);
123
+ const decoded5 = TagAbiCodec.decode(
124
+ 'tuple(string,tuple(tuple(uint8,bool),address))',
125
+ encoded5
126
+ );
127
+ console.log(
128
+ ' Decoded:',
129
+ JSON.stringify(
130
+ decoded5,
131
+ (_, v) => (typeof v === 'bigint' ? v.toString() : v),
132
+ 2
133
+ )
134
+ );
135
+
136
+ console.log('\n' + '='.repeat(60));
137
+ console.log('✅ All tests completed successfully!');
138
+ console.log('='.repeat(60));
139
+ console.log('\n💡 Key Features:');
140
+ console.log(' • Objects are automatically converted to arrays');
141
+ console.log(' • Nested tuples work recursively');
142
+ console.log(' • Array notation is still supported');
143
+ console.log(' • No need to manually provide field names\n');