@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.
- package/CLI.md +1300 -0
- package/README.md +37 -31
- package/TAG.md +589 -0
- package/dist/abi/RootResolver2ABI.d.ts +54 -0
- package/dist/abi/RootResolver2ABI.d.ts.map +1 -0
- package/dist/abi/RootResolver2ABI.js +240 -0
- package/dist/abi/RootResolver2ABI.js.map +1 -0
- package/dist/business/index.d.ts +302 -0
- package/dist/business/index.d.ts.map +1 -0
- package/dist/business/index.js +1209 -0
- package/dist/business/index.js.map +1 -0
- package/dist/business/tag-context.d.ts +219 -0
- package/dist/business/tag-context.d.ts.map +1 -0
- package/dist/business/tag-context.js +537 -0
- package/dist/business/tag-context.js.map +1 -0
- package/dist/cli.js +2085 -39
- package/dist/cli.js.map +1 -1
- package/dist/debug.d.ts.map +1 -1
- package/dist/debug.js +14 -2
- package/dist/debug.js.map +1 -1
- package/dist/index.d.ts +50 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +229 -9
- package/dist/index.js.map +1 -1
- package/dist/utils/crypto-utils.d.ts +130 -0
- package/dist/utils/crypto-utils.d.ts.map +1 -0
- package/dist/utils/crypto-utils.js +402 -0
- package/dist/utils/crypto-utils.js.map +1 -0
- package/dist/utils/error-parser.d.ts +35 -0
- package/dist/utils/error-parser.d.ts.map +1 -0
- package/dist/utils/error-parser.js +202 -0
- package/dist/utils/error-parser.js.map +1 -0
- package/dist/utils/tag-abi-codec.d.ts +69 -0
- package/dist/utils/tag-abi-codec.d.ts.map +1 -0
- package/dist/utils/tag-abi-codec.js +144 -0
- package/dist/utils/tag-abi-codec.js.map +1 -0
- package/dist/utils/tag-type-builder.d.ts +158 -0
- package/dist/utils/tag-type-builder.d.ts.map +1 -0
- package/dist/utils/tag-type-builder.js +410 -0
- package/dist/utils/tag-type-builder.js.map +1 -0
- package/examples/crypto-utilities.ts +140 -0
- package/examples/domain-context.ts +80 -0
- package/examples/generate-mnemonic.ts +149 -0
- package/examples/index.ts +1 -1
- package/examples/ip.ts +171 -0
- package/examples/legacy.ts +10 -10
- package/examples/list-wallets.ts +81 -0
- package/examples/quasar-demo/.eslintrc.js +23 -0
- package/examples/quasar-demo/.quasar/app.js +43 -0
- package/examples/quasar-demo/.quasar/client-entry.js +38 -0
- package/examples/quasar-demo/.quasar/client-prefetch.js +130 -0
- package/examples/quasar-demo/.quasar/quasar-user-options.js +16 -0
- package/examples/quasar-demo/README.md +49 -0
- package/examples/quasar-demo/index.html +11 -0
- package/examples/quasar-demo/package-lock.json +6407 -0
- package/examples/quasar-demo/package.json +36 -0
- package/examples/quasar-demo/quasar.config.js +73 -0
- package/examples/quasar-demo/src/App.vue +13 -0
- package/examples/quasar-demo/src/css/app.scss +1 -0
- package/examples/quasar-demo/src/layouts/MainLayout.vue +21 -0
- package/examples/quasar-demo/src/pages/IndexPage.vue +905 -0
- package/examples/quasar-demo/src/router/index.ts +25 -0
- package/examples/quasar-demo/src/router/routes.ts +11 -0
- package/examples/quasar-demo/tsconfig.json +28 -0
- package/examples/register-subdomain.ts +152 -0
- package/examples/rsa-keypair.ts +148 -0
- package/examples/tag-builder.ts +235 -0
- package/examples/tag-management.ts +534 -0
- package/examples/tag-nested-tuple.ts +190 -0
- package/examples/tag-simple.ts +149 -0
- package/examples/tag-tagger.ts +217 -0
- package/examples/test-nested-tuple-conversion.ts +143 -0
- package/examples/test-type-bytes-parser.ts +70 -0
- package/examples/transfer-domain.ts +197 -0
- package/examples/wallet-management.ts +196 -0
- package/package.json +24 -15
- package/src/abi/RootResolver2ABI.ts +237 -0
- package/src/business/index.ts +1490 -0
- package/src/business/tag-context.ts +713 -0
- package/src/cli.ts +2755 -39
- package/src/debug.ts +17 -2
- package/src/index.ts +300 -14
- package/src/utils/crypto-utils.ts +459 -0
- package/src/utils/error-parser.ts +225 -0
- package/src/utils/tag-abi-codec.ts +158 -0
- package/src/utils/tag-type-builder.ts +469 -0
- package/tsconfig.json +1 -1
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tag Management Example
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates the complete Tag system workflow:
|
|
5
|
+
* 1. Defining Tag types (simple types, arrays, tuples)
|
|
6
|
+
* 2. Setting and getting Tag values
|
|
7
|
+
* 3. Array operations (push, pop, update)
|
|
8
|
+
* 4. Cross-domain Tag operations
|
|
9
|
+
*
|
|
10
|
+
* Prerequisites:
|
|
11
|
+
* - Set PRIVATE_KEY_OR_MNEMONIC environment variable
|
|
12
|
+
* - You must own the domain you're operating on
|
|
13
|
+
*
|
|
14
|
+
* Run:
|
|
15
|
+
* export PRIVATE_KEY_OR_MNEMONIC="your private key or mnemonic"
|
|
16
|
+
* npx ts-node examples/tag-management.ts
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import OlaresID, { TagTypeBuilder } from '../src/index';
|
|
20
|
+
|
|
21
|
+
// Helper function to wait for blockchain indexing
|
|
22
|
+
async function waitForIndexing(seconds: number = 3) {
|
|
23
|
+
console.log(`⏳ Waiting ${seconds} seconds for blockchain indexing...`);
|
|
24
|
+
await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function main() {
|
|
28
|
+
// Initialize OlaresID
|
|
29
|
+
const olaresId = OlaresID.createTestnet();
|
|
30
|
+
|
|
31
|
+
// Get private key or mnemonic from environment
|
|
32
|
+
const privateKeyOrMnemonic = process.env.PRIVATE_KEY_OR_MNEMONIC;
|
|
33
|
+
if (!privateKeyOrMnemonic) {
|
|
34
|
+
console.error(
|
|
35
|
+
'❌ Error: PRIVATE_KEY_OR_MNEMONIC environment variable not set'
|
|
36
|
+
);
|
|
37
|
+
console.log(
|
|
38
|
+
'Usage: export PRIVATE_KEY_OR_MNEMONIC="your private key or mnemonic"'
|
|
39
|
+
);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
await olaresId.setSigner(privateKeyOrMnemonic);
|
|
44
|
+
console.log('✅ Signer set successfully\n');
|
|
45
|
+
|
|
46
|
+
// Replace with your domain
|
|
47
|
+
const domainName = process.argv[2];
|
|
48
|
+
if (!domainName) {
|
|
49
|
+
console.error('❌ Error: Please provide a domain name');
|
|
50
|
+
console.log(
|
|
51
|
+
'Usage: npx ts-node examples/tag-management.ts <domain-name>'
|
|
52
|
+
);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const domain = olaresId.domain(domainName);
|
|
57
|
+
const signerAddress = await olaresId.getSigner().getAddress();
|
|
58
|
+
console.log(`🏷️ Managing Tags for domain: ${domainName}`);
|
|
59
|
+
console.log(`👤 Signer: ${signerAddress}\n`);
|
|
60
|
+
|
|
61
|
+
// ========================================
|
|
62
|
+
// Part 1: Define Simple Tag Types
|
|
63
|
+
// ========================================
|
|
64
|
+
console.log('='.repeat(60));
|
|
65
|
+
console.log('Part 1: Defining Simple Tag Types');
|
|
66
|
+
console.log('='.repeat(60));
|
|
67
|
+
|
|
68
|
+
// Define "email" tag
|
|
69
|
+
console.log('📝 Defining "email" tag (type: string)...');
|
|
70
|
+
try {
|
|
71
|
+
await domain.defineSimpleTag('email', 'string');
|
|
72
|
+
console.log('✅ "email" tag defined');
|
|
73
|
+
await waitForIndexing(3);
|
|
74
|
+
} catch (error: any) {
|
|
75
|
+
if (
|
|
76
|
+
error.message?.includes('RedefinedTag') ||
|
|
77
|
+
error.message?.includes('already been defined')
|
|
78
|
+
) {
|
|
79
|
+
console.log('⚠️ "email" already defined, skipping...');
|
|
80
|
+
} else {
|
|
81
|
+
console.error(`❌ Error: ${error.message}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Define "age" tag
|
|
86
|
+
console.log('📝 Defining "age" tag (type: uint8)...');
|
|
87
|
+
try {
|
|
88
|
+
await domain.defineSimpleTag('age', 'uint8');
|
|
89
|
+
console.log('✅ "age" tag defined');
|
|
90
|
+
await waitForIndexing(3);
|
|
91
|
+
} catch (error: any) {
|
|
92
|
+
if (
|
|
93
|
+
error.message?.includes('RedefinedTag') ||
|
|
94
|
+
error.message?.includes('already been defined')
|
|
95
|
+
) {
|
|
96
|
+
console.log('⚠️ "age" already defined, skipping...');
|
|
97
|
+
} else {
|
|
98
|
+
console.error(`❌ Error: ${error.message}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Define "verified" tag
|
|
103
|
+
console.log('📝 Defining "verified" tag (type: bool)...');
|
|
104
|
+
try {
|
|
105
|
+
await domain.defineSimpleTag('verified', 'bool');
|
|
106
|
+
console.log('✅ "verified" tag defined');
|
|
107
|
+
await waitForIndexing(3);
|
|
108
|
+
} catch (error: any) {
|
|
109
|
+
if (
|
|
110
|
+
error.message?.includes('RedefinedTag') ||
|
|
111
|
+
error.message?.includes('already been defined')
|
|
112
|
+
) {
|
|
113
|
+
console.log('⚠️ "verified" already defined, skipping...');
|
|
114
|
+
} else {
|
|
115
|
+
console.error(`❌ Error: ${error.message}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Define "wallets" tag
|
|
120
|
+
console.log('📝 Defining "wallets" tag (type: address[])...');
|
|
121
|
+
try {
|
|
122
|
+
await domain.defineSimpleTag('wallets', 'address[]');
|
|
123
|
+
console.log('✅ "wallets" tag defined\n');
|
|
124
|
+
await waitForIndexing(3);
|
|
125
|
+
} catch (error: any) {
|
|
126
|
+
if (
|
|
127
|
+
error.message?.includes('RedefinedTag') ||
|
|
128
|
+
error.message?.includes('already been defined')
|
|
129
|
+
) {
|
|
130
|
+
console.log('⚠️ "wallets" already defined, skipping...\n');
|
|
131
|
+
} else {
|
|
132
|
+
console.error(`❌ Error: ${error.message}\n`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ========================================
|
|
137
|
+
// Part 2: Define Complex Tag Types
|
|
138
|
+
// ========================================
|
|
139
|
+
console.log('='.repeat(60));
|
|
140
|
+
console.log('Part 2: Defining Complex Tag Types (using TagTypeBuilder)');
|
|
141
|
+
console.log('='.repeat(60));
|
|
142
|
+
|
|
143
|
+
const tagCtx = domain.tag();
|
|
144
|
+
|
|
145
|
+
// Define "userInfo" tag
|
|
146
|
+
console.log('📝 Defining "userInfo" tag (complex tuple)...');
|
|
147
|
+
try {
|
|
148
|
+
const userInfoType = TagTypeBuilder.tuple({
|
|
149
|
+
name: TagTypeBuilder.string(),
|
|
150
|
+
age: TagTypeBuilder.uint8(),
|
|
151
|
+
wallets: TagTypeBuilder.addressArray(),
|
|
152
|
+
verified: TagTypeBuilder.bool()
|
|
153
|
+
});
|
|
154
|
+
console.log(` Type bytes: 0x${userInfoType.getTypeBytes()}`);
|
|
155
|
+
console.log(
|
|
156
|
+
` Field names: ${JSON.stringify(userInfoType.getFieldNames())}`
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
await tagCtx.defineTag('userInfo', userInfoType);
|
|
160
|
+
console.log('✅ "userInfo" tag defined\n');
|
|
161
|
+
await waitForIndexing(3);
|
|
162
|
+
} catch (error: any) {
|
|
163
|
+
if (
|
|
164
|
+
error.message?.includes('RedefinedTag') ||
|
|
165
|
+
error.message?.includes('already been defined')
|
|
166
|
+
) {
|
|
167
|
+
console.log('⚠️ "userInfo" already defined, skipping...\n');
|
|
168
|
+
} else {
|
|
169
|
+
console.error(`❌ Error: ${error.message}\n`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Define "socialLinks" tag
|
|
174
|
+
console.log('📝 Defining "socialLinks" tag (string array)...');
|
|
175
|
+
try {
|
|
176
|
+
const socialLinksType = TagTypeBuilder.stringArray();
|
|
177
|
+
await tagCtx.defineTag('socialLinks', socialLinksType);
|
|
178
|
+
console.log('✅ "socialLinks" tag defined\n');
|
|
179
|
+
await waitForIndexing(3);
|
|
180
|
+
} catch (error: any) {
|
|
181
|
+
if (
|
|
182
|
+
error.message?.includes('RedefinedTag') ||
|
|
183
|
+
error.message?.includes('already been defined')
|
|
184
|
+
) {
|
|
185
|
+
console.log('⚠️ "socialLinks" already defined, skipping...\n');
|
|
186
|
+
} else {
|
|
187
|
+
console.error(`❌ Error: ${error.message}\n`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// ========================================
|
|
192
|
+
// Part 3: Set Taggers (IMPORTANT!)
|
|
193
|
+
// ========================================
|
|
194
|
+
console.log('='.repeat(60));
|
|
195
|
+
console.log('Part 3: Setting Taggers (Required Before Setting Values)');
|
|
196
|
+
console.log('='.repeat(60));
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
console.log('📝 Setting taggers for all defined tags...');
|
|
200
|
+
|
|
201
|
+
// Set tagger for simple tags
|
|
202
|
+
await domain.setTagger('email', signerAddress);
|
|
203
|
+
console.log(' ✅ Set tagger for "email"');
|
|
204
|
+
await waitForIndexing(2);
|
|
205
|
+
|
|
206
|
+
await domain.setTagger('age', signerAddress);
|
|
207
|
+
console.log(' ✅ Set tagger for "age"');
|
|
208
|
+
await waitForIndexing(2);
|
|
209
|
+
|
|
210
|
+
await domain.setTagger('verified', signerAddress);
|
|
211
|
+
console.log(' ✅ Set tagger for "verified"');
|
|
212
|
+
await waitForIndexing(2);
|
|
213
|
+
|
|
214
|
+
await domain.setTagger('wallets', signerAddress);
|
|
215
|
+
console.log(' ✅ Set tagger for "wallets"');
|
|
216
|
+
await waitForIndexing(2);
|
|
217
|
+
|
|
218
|
+
// Set tagger for complex tags
|
|
219
|
+
await domain.setTagger('userInfo', signerAddress);
|
|
220
|
+
console.log(' ✅ Set tagger for "userInfo"');
|
|
221
|
+
await waitForIndexing(2);
|
|
222
|
+
|
|
223
|
+
await domain.setTagger('socialLinks', signerAddress);
|
|
224
|
+
console.log(' ✅ Set tagger for "socialLinks"\n');
|
|
225
|
+
await waitForIndexing(2);
|
|
226
|
+
} catch (error: any) {
|
|
227
|
+
console.error(`❌ Error setting taggers: ${error.message}\n`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// ========================================
|
|
231
|
+
// Part 4: Set and Get Tag Values
|
|
232
|
+
// ========================================
|
|
233
|
+
console.log('='.repeat(60));
|
|
234
|
+
console.log('Part 4: Setting and Getting Tag Values');
|
|
235
|
+
console.log('='.repeat(60));
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
// Set simple tag values
|
|
239
|
+
console.log('📝 Setting "email" tag...');
|
|
240
|
+
await domain.setTag('email', 'alice@example.com');
|
|
241
|
+
console.log('✅ "email" tag set');
|
|
242
|
+
await waitForIndexing(3);
|
|
243
|
+
|
|
244
|
+
console.log('📝 Setting "age" tag...');
|
|
245
|
+
await domain.setTag('age', 30);
|
|
246
|
+
console.log('✅ "age" tag set');
|
|
247
|
+
await waitForIndexing(3);
|
|
248
|
+
|
|
249
|
+
console.log('📝 Setting "verified" tag...');
|
|
250
|
+
await domain.setTag('verified', true);
|
|
251
|
+
console.log('✅ "verified" tag set\n');
|
|
252
|
+
await waitForIndexing(3);
|
|
253
|
+
|
|
254
|
+
// Get tag values
|
|
255
|
+
console.log('📖 Reading tag values...');
|
|
256
|
+
const email = await domain.getTag('email');
|
|
257
|
+
const age = await domain.getTag('age');
|
|
258
|
+
const verified = await domain.getTag('verified');
|
|
259
|
+
|
|
260
|
+
console.log(` email: ${email}`);
|
|
261
|
+
console.log(` age: ${age}`);
|
|
262
|
+
console.log(` verified: ${verified}\n`);
|
|
263
|
+
} catch (error: any) {
|
|
264
|
+
console.error(`❌ Error with simple tags: ${error.message}\n`);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// ========================================
|
|
268
|
+
// Part 5: Array Operations
|
|
269
|
+
// ========================================
|
|
270
|
+
console.log('='.repeat(60));
|
|
271
|
+
console.log('Part 5: Array Operations');
|
|
272
|
+
console.log('='.repeat(60));
|
|
273
|
+
|
|
274
|
+
try {
|
|
275
|
+
const tagCtx = domain.tag();
|
|
276
|
+
|
|
277
|
+
// Initialize array with setTag first (required before push operations)
|
|
278
|
+
console.log('📝 Initializing "socialLinks" array...');
|
|
279
|
+
await tagCtx.setTag(domainName, 'socialLinks', [
|
|
280
|
+
'https://twitter.com/alice',
|
|
281
|
+
'https://github.com/alice',
|
|
282
|
+
'https://linkedin.com/in/alice'
|
|
283
|
+
]);
|
|
284
|
+
console.log('✅ Social links initialized with 3 items\n');
|
|
285
|
+
await waitForIndexing(3);
|
|
286
|
+
|
|
287
|
+
// Get array length
|
|
288
|
+
const length = await tagCtx.getArrayLength(domainName, 'socialLinks');
|
|
289
|
+
console.log(`📊 Social links count: ${length}`);
|
|
290
|
+
|
|
291
|
+
// Get all array elements
|
|
292
|
+
console.log('📖 Reading all social links:');
|
|
293
|
+
for (let i = 0; i < length; i++) {
|
|
294
|
+
const link = await tagCtx.getElement(domainName, 'socialLinks', [
|
|
295
|
+
i
|
|
296
|
+
]);
|
|
297
|
+
console.log(` [${i}] ${link}`);
|
|
298
|
+
}
|
|
299
|
+
console.log();
|
|
300
|
+
|
|
301
|
+
// Test push operation (add a new element)
|
|
302
|
+
console.log('📝 Adding a new social link (push)...');
|
|
303
|
+
try {
|
|
304
|
+
await tagCtx.pushElement(
|
|
305
|
+
domainName,
|
|
306
|
+
'socialLinks',
|
|
307
|
+
'https://discord.gg/alice'
|
|
308
|
+
);
|
|
309
|
+
console.log('✅ Added Discord link');
|
|
310
|
+
await waitForIndexing(3);
|
|
311
|
+
|
|
312
|
+
const afterPush = await tagCtx.getArrayLength(
|
|
313
|
+
domainName,
|
|
314
|
+
'socialLinks'
|
|
315
|
+
);
|
|
316
|
+
console.log(`📊 Social links count after push: ${afterPush}\n`);
|
|
317
|
+
const link = await tagCtx.getElement(domainName, 'socialLinks', [
|
|
318
|
+
afterPush - 1
|
|
319
|
+
]);
|
|
320
|
+
console.log(` [${afterPush - 1}] ${link}`);
|
|
321
|
+
} catch (error: any) {
|
|
322
|
+
console.log(`⚠️ Push operation failed: ${error.message}\n`);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Update an element
|
|
326
|
+
console.log('📝 Updating first social link...');
|
|
327
|
+
await tagCtx.updateElement(
|
|
328
|
+
domainName,
|
|
329
|
+
'socialLinks',
|
|
330
|
+
[0],
|
|
331
|
+
'https://x.com/alice'
|
|
332
|
+
);
|
|
333
|
+
console.log('✅ First link updated\n');
|
|
334
|
+
await waitForIndexing(3);
|
|
335
|
+
const link = await tagCtx.getElement(domainName, 'socialLinks', [0]);
|
|
336
|
+
console.log(` [0] ${link}`);
|
|
337
|
+
|
|
338
|
+
// Pop an element (remove last)
|
|
339
|
+
console.log('📝 Removing last social link (pop)...');
|
|
340
|
+
try {
|
|
341
|
+
await tagCtx.popElement(domainName, 'socialLinks');
|
|
342
|
+
console.log('✅ Last link removed');
|
|
343
|
+
await waitForIndexing(3);
|
|
344
|
+
|
|
345
|
+
const afterPop = await tagCtx.getArrayLength(
|
|
346
|
+
domainName,
|
|
347
|
+
'socialLinks'
|
|
348
|
+
);
|
|
349
|
+
console.log(`📊 Social links count after pop: ${afterPop}\n`);
|
|
350
|
+
} catch (error: any) {
|
|
351
|
+
console.log(`⚠️ Pop operation failed: ${error.message}\n`);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Verify final state
|
|
355
|
+
const finalLength = await tagCtx.getArrayLength(
|
|
356
|
+
domainName,
|
|
357
|
+
'socialLinks'
|
|
358
|
+
);
|
|
359
|
+
console.log(`📊 Final social links count: ${finalLength}`);
|
|
360
|
+
console.log('📖 Current social links:');
|
|
361
|
+
for (let i = 0; i < finalLength; i++) {
|
|
362
|
+
const link = await tagCtx.getElement(domainName, 'socialLinks', [
|
|
363
|
+
i
|
|
364
|
+
]);
|
|
365
|
+
console.log(` [${i}] ${link}`);
|
|
366
|
+
}
|
|
367
|
+
console.log();
|
|
368
|
+
} catch (error: any) {
|
|
369
|
+
console.error(`❌ Error with array operations: ${error.message}\n`);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// ========================================
|
|
373
|
+
// Part 6: Complex Tuple Values
|
|
374
|
+
// ========================================
|
|
375
|
+
console.log('='.repeat(60));
|
|
376
|
+
console.log('Part 6: Complex Tuple Values');
|
|
377
|
+
console.log('='.repeat(60));
|
|
378
|
+
|
|
379
|
+
try {
|
|
380
|
+
const tagCtx = domain.tag();
|
|
381
|
+
|
|
382
|
+
// Set tuple value using object notation (automatic conversion!)
|
|
383
|
+
console.log('📝 Setting "userInfo" tuple...');
|
|
384
|
+
console.log(' Using object notation (no fieldNames needed)');
|
|
385
|
+
await tagCtx.setTag(domainName, 'userInfo', {
|
|
386
|
+
name: 'Alice Johnson',
|
|
387
|
+
age: 30,
|
|
388
|
+
wallets: [
|
|
389
|
+
'0x1111111111111111111111111111111111111111',
|
|
390
|
+
'0x2222222222222222222222222222222222222222'
|
|
391
|
+
],
|
|
392
|
+
verified: true
|
|
393
|
+
});
|
|
394
|
+
console.log('✅ "userInfo" tuple set');
|
|
395
|
+
await waitForIndexing(3);
|
|
396
|
+
|
|
397
|
+
// Get tuple value
|
|
398
|
+
console.log('📖 Reading "userInfo" tuple...');
|
|
399
|
+
const userInfo = await tagCtx.getTag(domainName, 'userInfo');
|
|
400
|
+
console.log(' User Info (raw):');
|
|
401
|
+
console.log(
|
|
402
|
+
` ${JSON.stringify(userInfo, (_, v) =>
|
|
403
|
+
typeof v === 'bigint' ? v.toString() : v
|
|
404
|
+
)}`
|
|
405
|
+
);
|
|
406
|
+
console.log(
|
|
407
|
+
` Type: ${typeof userInfo}, IsArray: ${Array.isArray(userInfo)}`
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
// The returned data is directly the tuple array: [field1, field2, field3, field4]
|
|
411
|
+
// No need to access [0], it's already the tuple data
|
|
412
|
+
console.log(' User Info (parsed):');
|
|
413
|
+
console.log(` name: ${userInfo[0]}`);
|
|
414
|
+
console.log(` age: ${userInfo[1]}`);
|
|
415
|
+
console.log(` wallets: ${JSON.stringify(userInfo[2])}`);
|
|
416
|
+
console.log(` verified: ${userInfo[3]}\n`);
|
|
417
|
+
|
|
418
|
+
// Update a specific field in the tuple
|
|
419
|
+
console.log('🔄 Updating "age" field in "userInfo" tuple...');
|
|
420
|
+
console.log(` Current age: ${userInfo[1]}`);
|
|
421
|
+
|
|
422
|
+
// To update a single field, we need to read the entire tuple, modify it, and set it back
|
|
423
|
+
const updatedUserInfo = {
|
|
424
|
+
name: userInfo[0], // Keep existing name
|
|
425
|
+
age: 31, // Update age
|
|
426
|
+
wallets: userInfo[2], // Keep existing wallets
|
|
427
|
+
verified: userInfo[3] // Keep existing verified status
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
await tagCtx.setTag(domainName, 'userInfo', updatedUserInfo);
|
|
431
|
+
console.log('✅ "age" field updated to 31');
|
|
432
|
+
await waitForIndexing(3);
|
|
433
|
+
|
|
434
|
+
// Verify the update
|
|
435
|
+
const updatedInfo = await tagCtx.getTag(domainName, 'userInfo');
|
|
436
|
+
console.log('📖 Updated User Info:');
|
|
437
|
+
console.log(
|
|
438
|
+
` ${JSON.stringify(updatedInfo, (_, v) =>
|
|
439
|
+
typeof v === 'bigint' ? v.toString() : v
|
|
440
|
+
)}\n`
|
|
441
|
+
);
|
|
442
|
+
} catch (error: any) {
|
|
443
|
+
console.error(`❌ Error with tuple values: ${error.message}\n`);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// ========================================
|
|
447
|
+
// Part 7: Get All Tags
|
|
448
|
+
// ========================================
|
|
449
|
+
console.log('='.repeat(60));
|
|
450
|
+
console.log('Part 7: Get All Tags');
|
|
451
|
+
console.log('='.repeat(60));
|
|
452
|
+
|
|
453
|
+
try {
|
|
454
|
+
console.log('📖 Getting all tags for domain...');
|
|
455
|
+
const allTags = await domain.getAllTags();
|
|
456
|
+
console.log(`✅ Found ${allTags.length} tags:\n`);
|
|
457
|
+
|
|
458
|
+
for (const tag of allTags) {
|
|
459
|
+
console.log(` Tag: "${tag.name}"`);
|
|
460
|
+
if (typeof tag.value === 'object' && tag.value !== null) {
|
|
461
|
+
console.log(
|
|
462
|
+
` Value: ${JSON.stringify(tag.value, (_, v) =>
|
|
463
|
+
typeof v === 'bigint' ? v.toString() : v
|
|
464
|
+
)}`
|
|
465
|
+
);
|
|
466
|
+
} else {
|
|
467
|
+
console.log(` Value: ${tag.value}`);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
console.log();
|
|
471
|
+
|
|
472
|
+
console.log('📖 Getting all defined tag types...');
|
|
473
|
+
const definedTags = await domain.getDefinedTags();
|
|
474
|
+
console.log(`✅ Found ${definedTags.length} defined tag types:`);
|
|
475
|
+
for (const tagName of definedTags) {
|
|
476
|
+
console.log(` - ${tagName}`);
|
|
477
|
+
}
|
|
478
|
+
console.log();
|
|
479
|
+
} catch (error: any) {
|
|
480
|
+
console.error(`❌ Error getting all tags: ${error.message}\n`);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// ========================================
|
|
484
|
+
// Part 8: Remove Tags
|
|
485
|
+
// ========================================
|
|
486
|
+
console.log('='.repeat(60));
|
|
487
|
+
console.log('Part 8: Remove Tags (Cleanup)');
|
|
488
|
+
console.log('='.repeat(60));
|
|
489
|
+
|
|
490
|
+
console.log('📝 Attempting to remove "verified" tag value...');
|
|
491
|
+
try {
|
|
492
|
+
// Note: removeTag() removes the tag VALUE from the storage
|
|
493
|
+
// The tag DEFINITION (type) remains and can be reused
|
|
494
|
+
// TagInvalidOp error occurs if the tag has no value to remove
|
|
495
|
+
await domain.removeTag('verified');
|
|
496
|
+
console.log('✅ "verified" tag value removed');
|
|
497
|
+
await waitForIndexing(3);
|
|
498
|
+
|
|
499
|
+
// Verify removal
|
|
500
|
+
const verified = await domain.getTag('verified');
|
|
501
|
+
console.log(` Verification: verified = ${verified} (should be null)`);
|
|
502
|
+
|
|
503
|
+
// Check if tag definition still exists
|
|
504
|
+
const definedTags = await domain.getDefinedTags();
|
|
505
|
+
const stillDefined = definedTags.includes('verified');
|
|
506
|
+
console.log(
|
|
507
|
+
` Tag definition still exists: ${stillDefined} (should be true)`
|
|
508
|
+
);
|
|
509
|
+
console.log(' 💡 You can set a new value for this tag later\n');
|
|
510
|
+
} catch (error: any) {
|
|
511
|
+
if (
|
|
512
|
+
error.message?.includes('TagInvalidOp') ||
|
|
513
|
+
error.message?.includes('Invalid tag operation')
|
|
514
|
+
) {
|
|
515
|
+
console.log('⚠️ Tag removal failed: Tag has no value to remove');
|
|
516
|
+
console.log(' This happens when:');
|
|
517
|
+
console.log(' - The tag was never set');
|
|
518
|
+
console.log(' - The tag was already removed');
|
|
519
|
+
console.log(' - Running this example multiple times\n');
|
|
520
|
+
} else {
|
|
521
|
+
console.error(`❌ Error removing tag: ${error.message}\n`);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
console.log('='.repeat(60));
|
|
526
|
+
console.log('✅ Tag Management Example Completed');
|
|
527
|
+
console.log('='.repeat(60));
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// Run the example
|
|
531
|
+
main().catch((error) => {
|
|
532
|
+
console.error('❌ Fatal error:', error);
|
|
533
|
+
process.exit(1);
|
|
534
|
+
});
|