@beclab/olaresid 0.1.13 → 0.2.0

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 (181) hide show
  1. package/CLI-TREE.md +107 -0
  2. package/CLI.md +122 -1340
  3. package/README.md +30 -12
  4. package/SDK-TREE.md +151 -0
  5. package/TAG.md +95 -41
  6. package/config.json +6 -4
  7. package/dist/abi/TerminusDIDQueryABI.d.ts +397 -0
  8. package/dist/abi/TerminusDIDQueryABI.d.ts.map +1 -0
  9. package/dist/abi/TerminusDIDQueryABI.js +519 -0
  10. package/dist/abi/TerminusDIDQueryABI.js.map +1 -0
  11. package/dist/business/index.d.ts.map +1 -1
  12. package/dist/business/index.js +9 -23
  13. package/dist/business/index.js.map +1 -1
  14. package/dist/business/tag-context.d.ts +1 -0
  15. package/dist/business/tag-context.d.ts.map +1 -1
  16. package/dist/business/tag-context.js +13 -7
  17. package/dist/business/tag-context.js.map +1 -1
  18. package/dist/cli.js +177 -76
  19. package/dist/cli.js.map +1 -1
  20. package/dist/config/index.d.ts +16 -4
  21. package/dist/config/index.d.ts.map +1 -1
  22. package/dist/config/index.js +28 -14
  23. package/dist/config/index.js.map +1 -1
  24. package/dist/domain/core.d.ts +65 -0
  25. package/dist/domain/core.d.ts.map +1 -0
  26. package/dist/domain/core.js +317 -0
  27. package/dist/domain/core.js.map +1 -0
  28. package/dist/domain/index.d.ts +104 -57
  29. package/dist/domain/index.d.ts.map +1 -1
  30. package/dist/domain/index.js +188 -428
  31. package/dist/domain/index.js.map +1 -1
  32. package/dist/domain/types.d.ts +56 -0
  33. package/dist/domain/types.d.ts.map +1 -0
  34. package/dist/domain/types.js +3 -0
  35. package/dist/domain/types.js.map +1 -0
  36. package/dist/index.d.ts +80 -23
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +152 -143
  39. package/dist/index.js.map +1 -1
  40. package/dist/utils/crypto-utils.d.ts +110 -0
  41. package/dist/utils/crypto-utils.d.ts.map +1 -1
  42. package/dist/utils/crypto-utils.js +127 -8
  43. package/dist/utils/crypto-utils.js.map +1 -1
  44. package/dist/utils/error-parser.d.ts.map +1 -1
  45. package/dist/utils/error-parser.js +2 -1
  46. package/dist/utils/error-parser.js.map +1 -1
  47. package/dist/utils/event-parser.d.ts +161 -0
  48. package/dist/utils/event-parser.d.ts.map +1 -0
  49. package/dist/utils/event-parser.js +140 -0
  50. package/dist/utils/event-parser.js.map +1 -0
  51. package/dist/utils/tag-type-builder.d.ts +43 -0
  52. package/dist/utils/tag-type-builder.d.ts.map +1 -1
  53. package/dist/utils/tag-type-builder.js +122 -0
  54. package/dist/utils/tag-type-builder.js.map +1 -1
  55. package/dist/utils/tag-type-parser.d.ts +70 -0
  56. package/dist/utils/tag-type-parser.d.ts.map +1 -0
  57. package/dist/utils/tag-type-parser.js +190 -0
  58. package/dist/utils/tag-type-parser.js.map +1 -0
  59. package/examples/create-with-rpc-demo.ts +142 -0
  60. package/examples/fetch-all-flat-demo.ts +159 -0
  61. package/examples/fetch-by-indices-demo.ts +235 -0
  62. package/examples/fetch-domain-demo.ts +137 -0
  63. package/examples/fetch-domains-demo.ts +221 -0
  64. package/examples/frontend-demo/index.html +2 -2
  65. package/examples/frontend-demo/package-lock.json +4 -1
  66. package/examples/index.ts +3 -5
  67. package/jest.config.js +25 -0
  68. package/package.json +6 -2
  69. package/src/abi/TerminusDIDQueryABI.ts +516 -0
  70. package/src/business/index.ts +9 -33
  71. package/src/business/tag-context.ts +35 -7
  72. package/src/cli.ts +253 -90
  73. package/src/config/index.ts +34 -19
  74. package/src/domain/core.ts +382 -0
  75. package/src/domain/index.ts +271 -641
  76. package/src/domain/types.ts +59 -0
  77. package/src/index.ts +221 -207
  78. package/src/utils/crypto-utils.ts +205 -2
  79. package/src/utils/error-parser.ts +2 -1
  80. package/src/utils/event-parser.ts +353 -0
  81. package/src/utils/tag-type-builder.ts +138 -0
  82. package/src/utils/tag-type-parser.ts +246 -0
  83. package/tests/unit/crypto-utils.test.ts +338 -0
  84. package/tests/unit/ed25519-jwk.test.ts +201 -0
  85. package/tests/unit/event-parser.test.ts +690 -0
  86. package/tests/unit/generate-mnemonic.test.ts +268 -0
  87. package/tests/unit/olares-id-format.test.ts +321 -0
  88. package/tests/unit/tag-type-parser.test.ts +802 -0
  89. package/tests/unit/tag-types.test.ts +821 -0
  90. package/tsconfig.json +3 -2
  91. package/dist/abi/ABITypeABI.d.ts +0 -88
  92. package/dist/abi/ABITypeABI.d.ts.map +0 -1
  93. package/dist/abi/ABITypeABI.js +0 -382
  94. package/dist/abi/ABITypeABI.js.map +0 -1
  95. package/dist/abi/RegistryABI.d.ts +0 -77
  96. package/dist/abi/RegistryABI.d.ts.map +0 -1
  97. package/dist/abi/RegistryABI.js +0 -462
  98. package/dist/abi/RegistryABI.js.map +0 -1
  99. package/dist/tag/address.d.ts +0 -11
  100. package/dist/tag/address.d.ts.map +0 -1
  101. package/dist/tag/address.js +0 -44
  102. package/dist/tag/address.js.map +0 -1
  103. package/dist/tag/array.d.ts +0 -14
  104. package/dist/tag/array.d.ts.map +0 -1
  105. package/dist/tag/array.js +0 -72
  106. package/dist/tag/array.js.map +0 -1
  107. package/dist/tag/bool.d.ts +0 -11
  108. package/dist/tag/bool.d.ts.map +0 -1
  109. package/dist/tag/bool.js +0 -43
  110. package/dist/tag/bool.js.map +0 -1
  111. package/dist/tag/bytes.d.ts +0 -11
  112. package/dist/tag/bytes.d.ts.map +0 -1
  113. package/dist/tag/bytes.js +0 -37
  114. package/dist/tag/bytes.js.map +0 -1
  115. package/dist/tag/flarray.d.ts +0 -15
  116. package/dist/tag/flarray.d.ts.map +0 -1
  117. package/dist/tag/flarray.js +0 -81
  118. package/dist/tag/flarray.js.map +0 -1
  119. package/dist/tag/flbytes.d.ts +0 -11
  120. package/dist/tag/flbytes.d.ts.map +0 -1
  121. package/dist/tag/flbytes.js +0 -47
  122. package/dist/tag/flbytes.js.map +0 -1
  123. package/dist/tag/index.d.ts +0 -32
  124. package/dist/tag/index.d.ts.map +0 -1
  125. package/dist/tag/index.js +0 -121
  126. package/dist/tag/index.js.map +0 -1
  127. package/dist/tag/int.d.ts +0 -12
  128. package/dist/tag/int.d.ts.map +0 -1
  129. package/dist/tag/int.js +0 -49
  130. package/dist/tag/int.js.map +0 -1
  131. package/dist/tag/string.d.ts +0 -11
  132. package/dist/tag/string.d.ts.map +0 -1
  133. package/dist/tag/string.js +0 -37
  134. package/dist/tag/string.js.map +0 -1
  135. package/dist/tag/tag.d.ts +0 -67
  136. package/dist/tag/tag.d.ts.map +0 -1
  137. package/dist/tag/tag.js +0 -157
  138. package/dist/tag/tag.js.map +0 -1
  139. package/dist/tag/tuple.d.ts +0 -17
  140. package/dist/tag/tuple.d.ts.map +0 -1
  141. package/dist/tag/tuple.js +0 -162
  142. package/dist/tag/tuple.js.map +0 -1
  143. package/dist/tag/uint.d.ts +0 -12
  144. package/dist/tag/uint.d.ts.map +0 -1
  145. package/dist/tag/uint.js +0 -49
  146. package/dist/tag/uint.js.map +0 -1
  147. package/dist/test/did.d.ts +0 -2
  148. package/dist/test/did.d.ts.map +0 -1
  149. package/dist/test/did.js +0 -177
  150. package/dist/test/did.js.map +0 -1
  151. package/dist/utils/tag-abi-codec.d.ts +0 -69
  152. package/dist/utils/tag-abi-codec.d.ts.map +0 -1
  153. package/dist/utils/tag-abi-codec.js +0 -144
  154. package/dist/utils/tag-abi-codec.js.map +0 -1
  155. package/examples/crypto-utilities.ts +0 -140
  156. package/examples/ed25519-jwk.ts +0 -73
  157. package/examples/generate-mnemonic.ts +0 -149
  158. package/examples/legacy.ts +0 -33
  159. package/examples/olares-id-format.ts +0 -197
  160. package/examples/tag-builder.ts +0 -235
  161. package/examples/tag-nested-tuple.ts +0 -190
  162. package/examples/tag-simple.ts +0 -149
  163. package/examples/tag-tagger.ts +0 -217
  164. package/examples/test-nested-tuple-conversion.ts +0 -143
  165. package/examples/test-type-bytes-parser.ts +0 -70
  166. package/src/abi/ABITypeABI.ts +0 -379
  167. package/src/abi/RegistryABI.ts +0 -459
  168. package/src/tag/address.ts +0 -48
  169. package/src/tag/array.ts +0 -80
  170. package/src/tag/bool.ts +0 -43
  171. package/src/tag/bytes.ts +0 -38
  172. package/src/tag/flarray.ts +0 -99
  173. package/src/tag/flbytes.ts +0 -48
  174. package/src/tag/index.ts +0 -170
  175. package/src/tag/int.ts +0 -51
  176. package/src/tag/string.ts +0 -38
  177. package/src/tag/tag.ts +0 -229
  178. package/src/tag/tuple.ts +0 -193
  179. package/src/tag/uint.ts +0 -51
  180. package/src/test/did.ts +0 -346
  181. package/src/utils/tag-abi-codec.ts +0 -158
@@ -0,0 +1,142 @@
1
+ import OlaresID from '../src/index';
2
+
3
+ /**
4
+ * Example: Using createWithRpc factory function
5
+ *
6
+ * This demonstrates the middle-ground factory function that:
7
+ * - Allows you to specify a custom RPC endpoint
8
+ * - Automatically configures all contract addresses based on network type
9
+ * - Simpler than createConsole but more flexible than createMainnet/createTestnet
10
+ *
11
+ * Use cases:
12
+ * - You want to use your own RPC endpoint for better performance
13
+ * - You need to connect through a specific RPC provider
14
+ * - You want mainnet/testnet contracts but custom connectivity
15
+ *
16
+ * Run: npx ts-node examples/create-with-rpc-demo.ts
17
+ */
18
+
19
+ async function main() {
20
+ console.log('🚀 createWithRpc Demo\n');
21
+ console.log('='.repeat(80));
22
+ console.log('This example demonstrates three factory methods:\n');
23
+
24
+ // ============================================================================
25
+ // 1. createMainnet() - Fully configured for mainnet
26
+ // ============================================================================
27
+ console.log('📝 Method 1: createMainnet()');
28
+ console.log('-'.repeat(80));
29
+ console.log('✅ Pros: Zero configuration, ready to use');
30
+ console.log('❌ Cons: Uses default public RPC (may be slow)\n');
31
+
32
+ const consoleMainnet = OlaresID.createMainnet();
33
+ console.log(`RPC: ${consoleMainnet.rpcNode}`);
34
+ console.log(`Query Contract: ${consoleMainnet.queryContractAddress}`);
35
+
36
+ // ============================================================================
37
+ // 2. createWithRpc() - Custom RPC with auto contract config
38
+ // ============================================================================
39
+ console.log('\n📝 Method 2: createWithRpc(customRpc, network)');
40
+ console.log('-'.repeat(80));
41
+ console.log('✅ Pros: Custom RPC for better performance');
42
+ console.log('✅ Pros: All contracts auto-configured for network');
43
+ console.log('❌ Cons: Need to specify RPC endpoint\n');
44
+
45
+ // Example: Using a custom mainnet RPC
46
+ const customMainnetRpc = 'https://optimism.llamarpc.com';
47
+ const consoleCustomMainnet = OlaresID.createWithRpc(
48
+ customMainnetRpc,
49
+ 'mainnet'
50
+ );
51
+ console.log(`Custom Mainnet:`);
52
+ console.log(` RPC: ${consoleCustomMainnet.rpcNode}`);
53
+ console.log(
54
+ ` Query Contract: ${consoleCustomMainnet.queryContractAddress}`
55
+ );
56
+
57
+ // Example: Using a custom sepolia RPC
58
+ const customSepoliaRpc = 'https://sepolia.optimism.io';
59
+ const consoleCustomSepolia = OlaresID.createWithRpc(
60
+ customSepoliaRpc,
61
+ 'sepolia'
62
+ );
63
+ console.log(`\nCustom Sepolia:`);
64
+ console.log(` RPC: ${consoleCustomSepolia.rpcNode}`);
65
+ console.log(
66
+ ` Query Contract: ${consoleCustomSepolia.queryContractAddress}`
67
+ );
68
+
69
+ // Network defaults to 'mainnet' if not specified
70
+ const consoleDefaultNetwork = OlaresID.createWithRpc(
71
+ 'https://my-optimism-rpc.com'
72
+ );
73
+ console.log(`\nDefault Network (mainnet):`);
74
+ console.log(` RPC: ${consoleDefaultNetwork.rpcNode}`);
75
+ console.log(
76
+ ` Query Contract: ${consoleDefaultNetwork.queryContractAddress}`
77
+ );
78
+
79
+ // ============================================================================
80
+ // 3. createConsole() - Fully manual configuration
81
+ // ============================================================================
82
+ console.log('\n📝 Method 3: createConsole(...all params)');
83
+ console.log('-'.repeat(80));
84
+ console.log('✅ Pros: Complete control over all contracts');
85
+ console.log('❌ Cons: Most verbose, need to know all addresses\n');
86
+
87
+ const consoleManual = OlaresID.createConsole(
88
+ 'https://optimism-rpc.publicnode.com',
89
+ '0x5DA4Fa8E567d86e52Ef8Da860de1be8f54cae97D', // contractDid
90
+ '0x9bA3D0D3d2046aeD57e9897F7F79C58DfAa5325A', // contractRootResolver
91
+ '0x9ae3F16bD99294Af1784beB1a0A5C84bf2636365', // contractAbiType
92
+ '0x7e7961aB771cA942CE4DB6e79579e016a33Dc95B', // contractRootResolver2
93
+ 'https://api.olares.com/did/support', // supportSvcUrl
94
+ '0x8305411EEa5C3F99f9426845Cf2977E77D5a1711' // queryContract
95
+ );
96
+ console.log(`Manual Configuration:`);
97
+ console.log(` RPC: ${consoleManual.rpcNode}`);
98
+ console.log(` Query Contract: ${consoleManual.queryContractAddress}`);
99
+
100
+ // ============================================================================
101
+ // Test with real query
102
+ // ============================================================================
103
+ console.log('\n\n📊 Real Query Test');
104
+ console.log('='.repeat(80));
105
+ console.log('Testing createWithRpc with a real domain query...\n');
106
+
107
+ const testConsole = OlaresID.createWithRpc(
108
+ 'https://optimism-rpc.publicnode.com', // Use default public RPC
109
+ 'mainnet'
110
+ );
111
+
112
+ const totalSupply = await testConsole.getTotalSupply();
113
+ console.log(`✅ Total domains: ${totalSupply}`);
114
+
115
+ // Fetch a single domain
116
+ const domain = await testConsole.fetchDomain('tw7613781.olares.com');
117
+ if (domain) {
118
+ console.log(`✅ Fetched domain: ${domain.name}`);
119
+ console.log(` Owner: ${domain.owner}`);
120
+ console.log(` Tags: ${domain.tags.length}`);
121
+ }
122
+
123
+ console.log('\n' + '='.repeat(80));
124
+ console.log('✅ Demo completed successfully!');
125
+ console.log('\n💡 Summary:');
126
+ console.log(' createMainnet() → Default RPC + mainnet contracts');
127
+ console.log(' createTestnet() → Default RPC + sepolia contracts');
128
+ console.log(
129
+ ' createWithRpc(rpc, net) → Custom RPC + auto contracts (NEW!)'
130
+ );
131
+ console.log(' createConsole(...) → Full manual control');
132
+ }
133
+
134
+ // Run the example
135
+ main().catch((error) => {
136
+ console.error('\n❌ Error:', error);
137
+ if (error instanceof Error) {
138
+ console.error('Message:', error.message);
139
+ console.error('Stack:', error.stack);
140
+ }
141
+ process.exit(1);
142
+ });
@@ -0,0 +1,159 @@
1
+ import OlaresID from '../src/index';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+
5
+ /**
6
+ * Example: Using fetchAllFlat to efficiently fetch all domains
7
+ *
8
+ * Usage:
9
+ *
10
+ * # Test on OP Sepolia (default)
11
+ * npx ts-node examples/fetch-all-flat-demo.ts
12
+ *
13
+ * # Test on Mainnet
14
+ * NETWORK=mainnet npx ts-node examples/fetch-all-flat-demo.ts
15
+ */
16
+
17
+ async function main() {
18
+ console.log('🚀 fetchAllFlat Demo\n');
19
+ console.log('='.repeat(80));
20
+
21
+ // Setup
22
+ const network = process.env.NETWORK || 'sepolia'; // 'sepolia' or 'mainnet'
23
+
24
+ console.log('📝 Config:');
25
+ console.log(` Network: ${network}`);
26
+
27
+ // Create console based on network
28
+ const didConsole =
29
+ network === 'mainnet'
30
+ ? OlaresID.createMainnet()
31
+ : OlaresID.createTestnet();
32
+
33
+ console.log(
34
+ ` Using ${
35
+ network === 'mainnet' ? 'mainnet' : 'testnet (OP Sepolia)'
36
+ } configuration`
37
+ );
38
+ console.log(` RPC: ${didConsole.rpcNode}`);
39
+
40
+ // Verify query contract is configured
41
+ if (!didConsole.queryContractAddress) {
42
+ console.error(
43
+ `\n❌ Error: Query contract address not configured for ${network}`
44
+ );
45
+ console.error(' Please configure it in config.json');
46
+ process.exit(1);
47
+ }
48
+
49
+ console.log(` Query Contract: ${didConsole.queryContractAddress}`);
50
+ console.log('='.repeat(80));
51
+
52
+ try {
53
+ // Fetch all domains
54
+ console.log('\n📦 Fetching all domains...\n');
55
+
56
+ const startTime = Date.now();
57
+ const domains = await didConsole.fetchAllFlat({
58
+ batchSize: 50,
59
+ onProgress: (current, total) => {
60
+ const percent = ((current / total) * 100).toFixed(1);
61
+ process.stdout.write(
62
+ `\r Progress: ${current}/${total} (${percent}%)`
63
+ );
64
+ }
65
+ });
66
+ const elapsed = Date.now() - startTime;
67
+
68
+ console.log(
69
+ `\n\n✅ Fetched ${domains.length} domains in ${elapsed}ms\n`
70
+ );
71
+
72
+ // Save to JSON file
73
+ const outputDir = path.join(__dirname, '../output');
74
+ if (!fs.existsSync(outputDir)) {
75
+ fs.mkdirSync(outputDir, { recursive: true });
76
+ }
77
+
78
+ const timestamp = new Date()
79
+ .toISOString()
80
+ .replace(/[:.]/g, '-')
81
+ .split('T')[0];
82
+ const outputFile = path.join(
83
+ outputDir,
84
+ `domains-${network}-${timestamp}.json`
85
+ );
86
+ fs.writeFileSync(outputFile, JSON.stringify(domains, null, 2), 'utf-8');
87
+
88
+ console.log(`💾 Data saved to: ${outputFile}`);
89
+ console.log('='.repeat(80));
90
+
91
+ // Analyze results
92
+ console.log('\n📊 Statistics:');
93
+ const topLevel = domains.filter((d) => d.level === 1);
94
+ const subdomains = domains.filter((d) => d.level > 1);
95
+ const withTags = domains.filter((d) => d.tags.length > 0);
96
+
97
+ console.log(` Total domains: ${domains.length}`);
98
+ console.log(` Top-level domains: ${topLevel.length}`);
99
+ console.log(` Subdomains: ${subdomains.length}`);
100
+ console.log(` Domains with tags: ${withTags.length}`);
101
+
102
+ // Show examples
103
+ console.log('\n📝 Example domains:\n');
104
+
105
+ // Top-level domain
106
+ const topDomain = topLevel[0];
107
+ if (topDomain) {
108
+ console.log(`1. Top-level domain: ${topDomain.name}`);
109
+ console.log(` - ID: ${topDomain.id}`);
110
+ console.log(` - Level: ${topDomain.level}`);
111
+ console.log(` - Owner: ${topDomain.owner}`);
112
+ console.log(` - Tags: ${topDomain.tags.length}`);
113
+ console.log(` - Parent ID: ${topDomain.parentId || 'none'}`);
114
+ }
115
+
116
+ // Subdomain
117
+ const subdomain = subdomains[0];
118
+ if (subdomain) {
119
+ console.log(`\n2. Subdomain: ${subdomain.name}`);
120
+ console.log(` - ID: ${subdomain.id}`);
121
+ console.log(` - Level: ${subdomain.level}`);
122
+ console.log(` - Owner: ${subdomain.owner}`);
123
+ console.log(` - Tags: ${subdomain.tags.length}`);
124
+ console.log(` - Parent ID: ${subdomain.parentId || 'not found'}`);
125
+ }
126
+
127
+ // Domain with tags
128
+ const domainWithTags = withTags[0];
129
+ if (domainWithTags) {
130
+ console.log(`\n3. Domain with tags: ${domainWithTags.name}`);
131
+ console.log(` - Tags count: ${domainWithTags.tags.length}`);
132
+
133
+ domainWithTags.tags.slice(0, 3).forEach((tag, i) => {
134
+ console.log(` - Tag ${i + 1}: ${tag.name}`);
135
+ console.log(` * From: ${tag.from || 'global'}`);
136
+ console.log(` * Type: ${tag.abiType}`);
137
+ if (tag.valueFormatted) {
138
+ const preview =
139
+ tag.valueFormatted.length > 50
140
+ ? tag.valueFormatted.substring(0, 50) + '...'
141
+ : tag.valueFormatted;
142
+ console.log(` * Value: ${preview}`);
143
+ }
144
+ });
145
+ }
146
+
147
+ console.log('\n' + '='.repeat(80));
148
+ console.log('✅ Demo completed successfully!');
149
+ } catch (error) {
150
+ console.error('\n❌ Error:', error);
151
+ if (error instanceof Error) {
152
+ console.error('Message:', error.message);
153
+ console.error('Stack:', error.stack);
154
+ }
155
+ process.exit(1);
156
+ }
157
+ }
158
+
159
+ main().catch(console.error);
@@ -0,0 +1,235 @@
1
+ import OlaresID from '../src/index';
2
+
3
+ /**
4
+ * Example: Fetching domains by specific indices
5
+ *
6
+ * This demonstrates fetchDomainsByIndices which uses a SINGLE RPC call to:
7
+ * - Map indices to tokenIds (done in contract)
8
+ * - Fetch all domain data in one batch
9
+ *
10
+ * Benefits:
11
+ * - No RPC rate limiting issues (single call vs multiple parallel calls)
12
+ * - 20% more gas efficient than separate getTokenByIndex calls
13
+ * - Simpler and more reliable
14
+ *
15
+ * Use cases:
16
+ * - Fetching specific domains when you know their indices
17
+ * - Sampling domains (e.g., every 100th domain)
18
+ * - Retrieving bookmarked/favorite domains by index
19
+ * - Testing with specific domain positions
20
+ *
21
+ * Run: npx ts-node examples/fetch-by-indices-demo.ts
22
+ */
23
+
24
+ async function main() {
25
+ // Use testnet for faster testing
26
+ const network = process.env.NETWORK || 'sepolia';
27
+
28
+ console.log('🚀 fetchDomainsByIndices Demo\n');
29
+ console.log('='.repeat(80));
30
+ console.log('📝 Config:');
31
+ console.log(` Network: ${network}`);
32
+ console.log('='.repeat(80));
33
+ console.log('');
34
+
35
+ // Create console instance
36
+ const didConsole =
37
+ network === 'mainnet'
38
+ ? OlaresID.createMainnet()
39
+ : OlaresID.createTestnet();
40
+
41
+ // Verify query contract is configured
42
+ if (!didConsole.queryContractAddress) {
43
+ console.error(
44
+ '❌ Error: Query contract address not configured for this network'
45
+ );
46
+ process.exit(1);
47
+ }
48
+
49
+ console.log(`📋 Query Contract: ${didConsole.queryContractAddress}\n`);
50
+
51
+ // Get total supply first
52
+ const totalSupply = Number(await didConsole.getTotalSupply());
53
+ console.log(`📊 Total domains: ${totalSupply}\n`);
54
+
55
+ // ============================================================================
56
+ // Example 1: Fetch specific indices
57
+ // ============================================================================
58
+ console.log('📄 Example 1: Fetch Specific Indices');
59
+ console.log('-'.repeat(80));
60
+
61
+ // Fetch domains at indices 5, 6, 9, 10
62
+ const specificIndices = [5, 6, 9, 10];
63
+ console.log(
64
+ `Fetching domains at indices: [${specificIndices.join(', ')}]\n`
65
+ );
66
+
67
+ const startTime1 = Date.now();
68
+ const specificDomains = await didConsole.fetchDomainsByIndices(
69
+ specificIndices
70
+ );
71
+ const elapsed1 = Date.now() - startTime1;
72
+
73
+ console.log(
74
+ `✅ Fetched ${specificDomains.length} domains in ${elapsed1}ms\n`
75
+ );
76
+
77
+ specificDomains.forEach((domain, i) => {
78
+ console.log(` Index ${specificIndices[i]}: ${domain.name}`);
79
+ console.log(` Owner: ${domain.owner}`);
80
+ console.log(` Tags: ${domain.tags.length}, Level: ${domain.level}`);
81
+ });
82
+
83
+ // ============================================================================
84
+ // Example 2: Sample domains (every 10th domain)
85
+ // ============================================================================
86
+ if (totalSupply > 50) {
87
+ console.log('\n📄 Example 2: Sample Domains (every 10th)');
88
+ console.log('-'.repeat(80));
89
+
90
+ // Get every 10th domain up to 50
91
+ const samplingIndices = [0, 10, 20, 30, 40, 50].filter(
92
+ (i) => i < totalSupply
93
+ );
94
+ console.log(`Sampling indices: [${samplingIndices.join(', ')}]\n`);
95
+
96
+ const startTime2 = Date.now();
97
+ const sampledDomains = await didConsole.fetchDomainsByIndices(
98
+ samplingIndices
99
+ );
100
+ const elapsed2 = Date.now() - startTime2;
101
+
102
+ console.log(
103
+ `✅ Sampled ${sampledDomains.length} domains in ${elapsed2}ms\n`
104
+ );
105
+
106
+ sampledDomains.forEach((domain, i) => {
107
+ console.log(
108
+ ` Index ${samplingIndices[i]}: ${domain.name} (${domain.tags.length} tags)`
109
+ );
110
+ });
111
+ }
112
+
113
+ // ============================================================================
114
+ // Example 3: First and last domains
115
+ // ============================================================================
116
+ console.log('\n📄 Example 3: First and Last Domains');
117
+ console.log('-'.repeat(80));
118
+
119
+ const firstLastIndices = [0, totalSupply - 1];
120
+ console.log(`Fetching indices: [${firstLastIndices.join(', ')}]\n`);
121
+
122
+ const startTime3 = Date.now();
123
+ const firstLastDomains = await didConsole.fetchDomainsByIndices(
124
+ firstLastIndices
125
+ );
126
+ const elapsed3 = Date.now() - startTime3;
127
+
128
+ console.log(
129
+ `✅ Fetched ${firstLastDomains.length} domains in ${elapsed3}ms\n`
130
+ );
131
+
132
+ console.log(` First domain (index 0):`);
133
+ console.log(` Name: ${firstLastDomains[0].name}`);
134
+ console.log(` Owner: ${firstLastDomains[0].owner}`);
135
+
136
+ console.log(`\n Last domain (index ${totalSupply - 1}):`);
137
+ console.log(` Name: ${firstLastDomains[1].name}`);
138
+ console.log(` Owner: ${firstLastDomains[1].owner}`);
139
+
140
+ // ============================================================================
141
+ // Example 4: Comparison with pagination
142
+ // ============================================================================
143
+ console.log('\n📊 Example 4: Performance Comparison');
144
+ console.log('-'.repeat(80));
145
+
146
+ // Method 1: fetchDomainsByIndices
147
+ const indices = [5, 15, 25, 35, 45];
148
+ console.log(`\nMethod 1: fetchDomainsByIndices([${indices.join(', ')}])`);
149
+ const start1 = Date.now();
150
+ const resultByIndices = await didConsole.fetchDomainsByIndices(
151
+ indices.filter((i) => i < totalSupply)
152
+ );
153
+ const time1 = Date.now() - start1;
154
+ console.log(`✅ Fetched ${resultByIndices.length} domains in ${time1}ms`);
155
+
156
+ // Method 2: Multiple fetchDomains calls (pagination approach)
157
+ console.log(`\nMethod 2: Multiple fetchDomains calls (paginated)`);
158
+ const start2 = Date.now();
159
+ const resultByPagination = [];
160
+ for (const index of indices) {
161
+ if (index < totalSupply) {
162
+ const domains = await didConsole.fetchDomains(index, 1);
163
+ resultByPagination.push(...domains);
164
+ }
165
+ }
166
+ const time2 = Date.now() - start2;
167
+ console.log(
168
+ `✅ Fetched ${resultByPagination.length} domains in ${time2}ms`
169
+ );
170
+
171
+ console.log(
172
+ `\n💡 Performance: fetchDomainsByIndices is ${(time2 / time1).toFixed(
173
+ 1
174
+ )}x faster!`
175
+ );
176
+
177
+ // ============================================================================
178
+ // Example 5: Error handling
179
+ // ============================================================================
180
+ console.log('\n⚠️ Example 5: Error Handling');
181
+ console.log('-'.repeat(80));
182
+
183
+ // Test invalid index
184
+ try {
185
+ await didConsole.fetchDomainsByIndices([-1]);
186
+ } catch (error) {
187
+ console.log('✅ Correctly caught error for negative index:');
188
+ console.log(` ${(error as Error).message}`);
189
+ }
190
+
191
+ // Test out of bounds
192
+ try {
193
+ await didConsole.fetchDomainsByIndices([totalSupply + 100]);
194
+ } catch (error) {
195
+ console.log('✅ Correctly caught error for out-of-bounds index:');
196
+ console.log(` ${(error as Error).message}`);
197
+ }
198
+
199
+ // Test empty array
200
+ try {
201
+ await didConsole.fetchDomainsByIndices([]);
202
+ } catch (error) {
203
+ console.log('✅ Correctly caught error for empty array:');
204
+ console.log(` ${(error as Error).message}`);
205
+ }
206
+
207
+ console.log('\n' + '='.repeat(80));
208
+ console.log('✅ Demo completed successfully!');
209
+ console.log('\n💡 Use Cases for fetchDomainsByIndices:');
210
+ console.log(' - Fetch specific domains by position');
211
+ console.log(' - Sample domains at regular intervals');
212
+ console.log(' - Random access without pagination overhead');
213
+ console.log(' - Bookmarked/favorite domains by index');
214
+ console.log('\n💡 Key Benefits:');
215
+ console.log(' ✅ Single RPC call (no rate limiting issues)');
216
+ console.log(' ✅ 20% more gas efficient');
217
+ console.log(' ✅ Simpler implementation');
218
+ console.log('\n💡 API Differences:');
219
+ console.log(
220
+ ' fetchDomains(offset, limit) → Contiguous range [offset, offset+limit)'
221
+ );
222
+ console.log(
223
+ ' fetchDomainsByIndices(indices) → Specific positions [5, 10, 50, 100]'
224
+ );
225
+ }
226
+
227
+ // Run the example
228
+ main().catch((error) => {
229
+ console.error('\n❌ Error:', error);
230
+ if (error instanceof Error) {
231
+ console.error('Message:', error.message);
232
+ console.error('Stack:', error.stack);
233
+ }
234
+ process.exit(1);
235
+ });
@@ -0,0 +1,137 @@
1
+ import OlaresID from '../src/index';
2
+
3
+ /**
4
+ * Example: Using fetchDomain to fetch a single domain
5
+ *
6
+ * Usage:
7
+ *
8
+ * # Test on OP Sepolia (default)
9
+ * npx ts-node examples/fetch-domain-demo.ts
10
+ *
11
+ * # Fetch by domain name
12
+ * DOMAIN_NAME=alice.olares.com npx ts-node examples/fetch-domain-demo.ts
13
+ *
14
+ * # Fetch by tokenId
15
+ * TOKEN_ID=0x123... npx ts-node examples/fetch-domain-demo.ts
16
+ *
17
+ * # Test on Mainnet
18
+ * NETWORK=mainnet DOMAIN_NAME=alice.olares.com npx ts-node examples/fetch-domain-demo.ts
19
+ */
20
+
21
+ async function main() {
22
+ console.log('🚀 fetchDomain Demo\n');
23
+ console.log('='.repeat(80));
24
+
25
+ // Setup
26
+ const network = process.env.NETWORK || 'sepolia';
27
+ const domainName = process.env.DOMAIN_NAME || '1.com';
28
+ const tokenId = process.env.TOKEN_ID;
29
+
30
+ const nameOrTokenId = tokenId || domainName;
31
+
32
+ console.log('📝 Config:');
33
+ console.log(` Network: ${network}`);
34
+ console.log(` Query: ${nameOrTokenId}`);
35
+ console.log(` Type: ${tokenId ? 'tokenId' : 'domain name'}`);
36
+
37
+ // Create console based on network
38
+ const didConsole =
39
+ network === 'mainnet'
40
+ ? OlaresID.createMainnet()
41
+ : OlaresID.createTestnet();
42
+
43
+ console.log(
44
+ ` Using ${
45
+ network === 'mainnet' ? 'mainnet' : 'testnet (OP Sepolia)'
46
+ } configuration`
47
+ );
48
+ console.log(` RPC: ${didConsole.rpcNode}`);
49
+
50
+ // Verify query contract is configured
51
+ if (!didConsole.queryContractAddress) {
52
+ console.error(
53
+ `\n❌ Error: Query contract address not configured for ${network}`
54
+ );
55
+ console.error(' Please configure it in config.json');
56
+ process.exit(1);
57
+ }
58
+
59
+ console.log(` Query Contract: ${didConsole.queryContractAddress}`);
60
+ console.log('='.repeat(80));
61
+
62
+ try {
63
+ // Fetch single domain
64
+ console.log('\n📦 Fetching domain...\n');
65
+
66
+ const startTime = Date.now();
67
+ const domain = await didConsole.fetchDomain(nameOrTokenId);
68
+ const elapsed = Date.now() - startTime;
69
+
70
+ if (!domain) {
71
+ console.log('❌ Domain not found');
72
+ process.exit(0);
73
+ }
74
+
75
+ console.log(`✅ Fetched domain in ${elapsed}ms\n`);
76
+ console.log('='.repeat(80));
77
+
78
+ // Display domain info
79
+ console.log('\n📋 Domain Information:\n');
80
+ console.log(` ID: ${domain.id}`);
81
+ console.log(` Name: ${domain.name}`);
82
+ console.log(` DID: ${domain.did}`);
83
+ console.log(` Owner: ${domain.owner}`);
84
+ console.log(` Level: ${domain.level}`);
85
+ console.log(` Note: ${domain.note || '(empty)'}`);
86
+ console.log(` Allow Subdomain: ${domain.allowSubdomain}`);
87
+ console.log(` Parent ID: ${domain.parentId || 'none'}`);
88
+ console.log(` Tags: ${domain.tags.length}`);
89
+
90
+ // Display tags
91
+ if (domain.tags.length > 0) {
92
+ console.log('\n🏷️ Tags:\n');
93
+
94
+ for (const tag of domain.tags) {
95
+ console.log(` 📌 ${tag.name}`);
96
+ console.log(` From: ${tag.from || 'global'}`);
97
+ console.log(` Type: ${tag.abiType}`);
98
+ console.log(
99
+ ` Value (hex): ${tag.value.substring(0, 66)}...`
100
+ );
101
+
102
+ if (tag.valueFormatted) {
103
+ console.log(` Formatted:`);
104
+ const formatted =
105
+ typeof tag.valueFormatted === 'string'
106
+ ? tag.valueFormatted
107
+ : JSON.stringify(tag.valueFormatted, null, 6);
108
+
109
+ // Indent formatted output
110
+ const lines = formatted.split('\n');
111
+ lines.forEach((line) => {
112
+ console.log(` ${line}`);
113
+ });
114
+ }
115
+
116
+ if (tag.fieldNamesHash.length > 0) {
117
+ console.log(
118
+ ` Field Names Hash: ${tag.fieldNamesHash.length} hashes`
119
+ );
120
+ }
121
+ console.log();
122
+ }
123
+ }
124
+
125
+ console.log('='.repeat(80));
126
+ console.log('✅ Demo completed successfully!');
127
+ } catch (error) {
128
+ console.error('\n❌ Error:', error);
129
+ if (error instanceof Error) {
130
+ console.error('Message:', error.message);
131
+ console.error('Stack:', error.stack);
132
+ }
133
+ process.exit(1);
134
+ }
135
+ }
136
+
137
+ main().catch(console.error);