viz-js-lib 0.11.0 → 0.12.4

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 (60) hide show
  1. package/.qoder/docs/spec/viz-dns-nameserver-spec.md +982 -0
  2. package/.qoder/docs/viz-cpp-node-docs/data-types.md +322 -0
  3. package/.qoder/docs/viz-cpp-node-docs/index.md +160 -0
  4. package/.qoder/docs/viz-cpp-node-docs/op-account-market.md +236 -0
  5. package/.qoder/docs/viz-cpp-node-docs/op-account.md +199 -0
  6. package/.qoder/docs/viz-cpp-node-docs/op-award.md +162 -0
  7. package/.qoder/docs/viz-cpp-node-docs/op-committee.md +193 -0
  8. package/.qoder/docs/viz-cpp-node-docs/op-content.md +157 -0
  9. package/.qoder/docs/viz-cpp-node-docs/op-escrow.md +224 -0
  10. package/.qoder/docs/viz-cpp-node-docs/op-invite.md +219 -0
  11. package/.qoder/docs/viz-cpp-node-docs/op-proposal.md +229 -0
  12. package/.qoder/docs/viz-cpp-node-docs/op-recovery.md +188 -0
  13. package/.qoder/docs/viz-cpp-node-docs/op-subscription.md +146 -0
  14. package/.qoder/docs/viz-cpp-node-docs/op-transfer-vesting.md +224 -0
  15. package/.qoder/docs/viz-cpp-node-docs/op-witness.md +252 -0
  16. package/.qoder/docs/viz-cpp-node-docs/plugins.md +887 -0
  17. package/.qoder/docs/viz-cpp-node-docs/virtual-operations.md +513 -0
  18. package/.qoder/repowiki/en/content/API Reference/API Reference.md +724 -0
  19. package/.qoder/repowiki/en/content/API Reference/Configuration Options.md +410 -0
  20. package/.qoder/repowiki/en/content/API Reference/Core API Methods.md +547 -0
  21. package/.qoder/repowiki/en/content/API Reference/Streaming APIs.md +380 -0
  22. package/.qoder/repowiki/en/content/API Reference/Transport Layer.md +341 -0
  23. package/.qoder/repowiki/en/content/API Reference/VIZ Blockchain Operations Coverage Status.md +427 -0
  24. package/.qoder/repowiki/en/content/Authentication & Cryptography/Authentication & Cryptography.md +430 -0
  25. package/.qoder/repowiki/en/content/Authentication & Cryptography/Digital Signatures.md +462 -0
  26. package/.qoder/repowiki/en/content/Authentication & Cryptography/Key Management.md +456 -0
  27. package/.qoder/repowiki/en/content/Authentication & Cryptography/Memo Encryption.md +331 -0
  28. package/.qoder/repowiki/en/content/Authentication & Cryptography/Security Practices.md +488 -0
  29. package/.qoder/repowiki/en/content/Broadcast Transactions/Broadcast Transactions.md +432 -0
  30. package/.qoder/repowiki/en/content/Broadcast Transactions/Network Broadcasting.md +418 -0
  31. package/.qoder/repowiki/en/content/Broadcast Transactions/Operation Construction.md +352 -0
  32. package/.qoder/repowiki/en/content/Broadcast Transactions/Transaction Preparation.md +353 -0
  33. package/.qoder/repowiki/en/content/Broadcast Transactions/Transaction Signing.md +404 -0
  34. package/.qoder/repowiki/en/content/Data Serialization/Data Serialization.md +540 -0
  35. package/.qoder/repowiki/en/content/Data Serialization/Encoding & Decoding.md +463 -0
  36. package/.qoder/repowiki/en/content/Data Serialization/Object Templates.md +413 -0
  37. package/.qoder/repowiki/en/content/Data Serialization/Type System.md +514 -0
  38. package/.qoder/repowiki/en/content/Data Serialization/Validation Rules.md +439 -0
  39. package/.qoder/repowiki/en/content/Examples & Tutorials.md +485 -0
  40. package/.qoder/repowiki/en/content/Getting Started.md +345 -0
  41. package/.qoder/repowiki/en/content/Testing & Development.md +637 -0
  42. package/.qoder/repowiki/en/content/Utilities & Helpers.md +557 -0
  43. package/.qoder/repowiki/en/meta/repowiki-metadata.json +1 -0
  44. package/VIZ-JS-LIB-COVERAGE-STATUS.md +356 -0
  45. package/config.json +3 -1
  46. package/dist/statistics.html +1 -1
  47. package/dist/viz-tests.min.js +32 -42
  48. package/dist/viz-tests.min.js.gz +0 -0
  49. package/dist/viz.min.js +8 -18
  50. package/dist/viz.min.js.gz +0 -0
  51. package/lib/api/methods.js +24 -0
  52. package/lib/auth/serializer/src/ChainTypes.js +2 -1
  53. package/lib/auth/serializer/src/operations.js +35 -2
  54. package/lib/broadcast/index.js +29 -15
  55. package/lib/broadcast/operations.js +4 -0
  56. package/lib/dns.js +658 -0
  57. package/lib/index.js +3 -1
  58. package/package.json +3 -2
  59. package/test/dns.test.js +395 -0
  60. package/webpack/makeConfig.js +3 -0
@@ -0,0 +1,982 @@
1
+ # VIZ DNS Nameserver Specification
2
+
3
+ A simple tool for configuring A records and TXT (SSL) records in account metadata on the VIZ blockchain.
4
+
5
+ ## Overview
6
+
7
+ VIZ DNS is a decentralized domain name system that stores NS records directly in the VIZ blockchain. This enables:
8
+ - **Decentralized DNS**: No reliance on traditional DNS providers
9
+ - **Self-signed SSL verification**: Certificate public key hashes stored on-chain for validation
10
+ - **Censorship resistance**: Domain records cannot be seized or modified by third parties
11
+ - **Account-based domains**: VIZ account names serve as domain names
12
+
13
+ ## Data Format Specification
14
+
15
+ ### JSON Metadata Structure
16
+
17
+ NS data is stored in the `json_metadata` field of a VIZ account using the following JSON format:
18
+
19
+ ```json
20
+ {
21
+ "ns": [
22
+ ["A", "188.120.231.153"],
23
+ ["TXT", "ssl=4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2"]
24
+ ],
25
+ "ttl": 28800
26
+ }
27
+ ```
28
+
29
+ ### Field Definitions
30
+
31
+ | Field | Type | Description |
32
+ |-------|------|-------------|
33
+ | `ns` | Array | Array of DNS record tuples |
34
+ | `ns[n][0]` | String | Record type: `"A"` or `"TXT"` |
35
+ | `ns[n][1]` | String | Record value (IPv4 address or TXT content) |
36
+ | `ttl` | Integer | Time-to-live in seconds (default: 28800 = 8 hours) |
37
+
38
+ ### Supported Record Types
39
+
40
+ #### A Record
41
+ - **Purpose**: Maps domain to IPv4 address
42
+ - **Format**: `["A", "<IPv4_ADDRESS>"]`
43
+ - **Example**: `["A", "188.120.231.153"]`
44
+ - **Multiple A records**: Supported for Round Robin DNS
45
+
46
+ #### TXT Record (SSL)
47
+ - **Purpose**: Stores SHA256 hash of SSL certificate public key
48
+ - **Format**: `["TXT", "ssl=<SHA256_HASH>"]`
49
+ - **Example**: `["TXT", "ssl=4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2"]`
50
+ - **Max length**: 256 characters (per NS standard)
51
+
52
+ ### Round Robin DNS Support
53
+
54
+ Multiple A records can be specified for load balancing:
55
+
56
+ ```json
57
+ {
58
+ "ns": [
59
+ ["A", "188.120.231.153"],
60
+ ["A", "192.168.1.100"],
61
+ ["A", "10.0.0.50"],
62
+ ["TXT", "ssl=4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2"]
63
+ ],
64
+ "ttl": 28800
65
+ }
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Blockchain Operations
71
+
72
+ ### Operation: account_metadata
73
+
74
+ The `account_metadata` operation is used to set or update NS records in an account's metadata.
75
+
76
+ #### Operation Structure
77
+
78
+ ```json
79
+ ["account_metadata", {
80
+ "account": "<ACCOUNT_NAME>",
81
+ "json_metadata": "<ESCAPED_JSON_STRING>"
82
+ }]
83
+ ```
84
+
85
+ #### Parameters
86
+
87
+ | Parameter | Type | Required | Description |
88
+ |-----------|------|----------|-------------|
89
+ | `account` | String | Yes | VIZ account name (also serves as domain name) |
90
+ | `json_metadata` | String | Yes | JSON-encoded metadata containing NS records |
91
+
92
+ #### Required Authority
93
+
94
+ - **Regular key** is sufficient to update account metadata
95
+
96
+ #### JavaScript Example (viz-js-lib)
97
+
98
+ ```javascript
99
+ const viz = require('viz-js-lib');
100
+
101
+ // Set NS records using helpers
102
+ viz.api.getAccounts(['myaccount'], function(err, accounts) {
103
+ if (!err && accounts.length > 0) {
104
+ const account = accounts[0];
105
+
106
+ // Create NS metadata
107
+ const nsData = viz.dns.createNsMetadata({
108
+ aRecords: ['188.120.231.153'],
109
+ sslHash: '4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2',
110
+ ttl: 28800
111
+ });
112
+
113
+ // Merge with existing metadata (preserves other fields like profile)
114
+ const updatedMetadata = viz.dns.mergeNsMetadata(account.json_metadata, nsData);
115
+
116
+ // Broadcast transaction
117
+ viz.broadcast.accountMetadata(
118
+ regularKey,
119
+ 'myaccount',
120
+ JSON.stringify(updatedMetadata),
121
+ function(err, result) {
122
+ if (!err) {
123
+ console.log('NS records updated successfully');
124
+ }
125
+ }
126
+ );
127
+ }
128
+ });
129
+ ```
130
+
131
+ #### JavaScript Example (Manual - viz-world-js style)
132
+
133
+ ```javascript
134
+ // Set NS records
135
+ gate.api.getAccount('myaccount', '', function(err, response) {
136
+ if (!err) {
137
+ let metadata = {};
138
+ try {
139
+ metadata = JSON.parse(response.json_metadata);
140
+ } catch (e) {
141
+ metadata = {};
142
+ }
143
+
144
+ // Remove existing NS data
145
+ if (typeof metadata.ns !== 'undefined') delete metadata.ns;
146
+ if (typeof metadata.ttl !== 'undefined') delete metadata.ttl;
147
+
148
+ // Set new NS records
149
+ metadata.ns = [];
150
+ metadata.ns.push(['A', '188.120.231.153']);
151
+ metadata.ns.push(['TXT', 'ssl=4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2']);
152
+ metadata.ttl = 28800;
153
+
154
+ // Broadcast transaction
155
+ gate.broadcast.accountMetadata(
156
+ users[current_user].regular_key,
157
+ current_user,
158
+ JSON.stringify(metadata),
159
+ function(err, result) {
160
+ if (!err) {
161
+ console.log('NS records updated successfully');
162
+ }
163
+ }
164
+ );
165
+ }
166
+ });
167
+ ```
168
+
169
+ #### PHP Example
170
+
171
+ ```php
172
+ $tx = new Transaction($chain_id);
173
+
174
+ // Build operation
175
+ list($json, $raw) = $tx->build_account_metadata(
176
+ 'myaccount',
177
+ addslashes(json_encode([
178
+ 'ns' => [
179
+ ['A', '188.120.231.153'],
180
+ ['TXT', 'ssl=4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2']
181
+ ],
182
+ 'ttl' => 28800
183
+ ]))
184
+ );
185
+
186
+ // Sign and broadcast
187
+ $signed = $tx->sign($regular_private_key, $ref_block_num, $ref_block_prefix, $expiration, $json, $raw);
188
+ $api->execute_method('broadcast_transaction', [$signed]);
189
+ ```
190
+
191
+ ### Operation: Remove NS Records
192
+
193
+ To remove NS records, update metadata without the `ns` and `ttl` fields:
194
+
195
+ ```javascript
196
+ // Using viz-js-lib helpers
197
+ const cleanedMetadata = viz.dns.removeNsMetadata(account.json_metadata);
198
+ viz.broadcast.accountMetadata(
199
+ regularKey,
200
+ 'myaccount',
201
+ JSON.stringify(cleanedMetadata),
202
+ callback
203
+ );
204
+ ```
205
+
206
+ ```javascript
207
+ // Manual approach
208
+ delete metadata.ns;
209
+ delete metadata.ttl;
210
+ gate.broadcast.accountMetadata(
211
+ users[current_user].regular_key,
212
+ current_user,
213
+ JSON.stringify(metadata),
214
+ callback
215
+ );
216
+ ```
217
+
218
+ ---
219
+
220
+ ## API Reference
221
+
222
+ ### Get Account NS Data
223
+
224
+ Use the `get_account` or `get_accounts` API methods to retrieve account metadata containing NS records.
225
+
226
+ #### Method: get_accounts
227
+
228
+ ```json
229
+ {
230
+ "jsonrpc": "2.0",
231
+ "method": "call",
232
+ "params": ["database_api", "get_accounts", [["account_name"]]],
233
+ "id": 1
234
+ }
235
+ ```
236
+
237
+ #### Response Example
238
+
239
+ ```json
240
+ {
241
+ "id": 1,
242
+ "result": [{
243
+ "name": "on1x",
244
+ "json_metadata": "{\"ns\":[[\"A\",\"188.120.231.153\"],[\"TXT\",\"ssl=4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2\"]],\"ttl\":28800}",
245
+ ...
246
+ }]
247
+ }
248
+ ```
249
+
250
+ #### Method: get_account (custom_protocol_api)
251
+
252
+ ```json
253
+ {
254
+ "jsonrpc": "2.0",
255
+ "method": "call",
256
+ "params": ["custom_protocol_api", "get_account", ["account_name", ""]],
257
+ "id": 1
258
+ }
259
+ ```
260
+
261
+ ### Parse NS Data (JavaScript) - Using viz-js-lib Helpers
262
+
263
+ ```javascript
264
+ const viz = require('viz-js-lib');
265
+
266
+ viz.api.getAccounts(['on1x'], function(err, accounts) {
267
+ if (!err && accounts.length > 0) {
268
+ const account = accounts[0];
269
+
270
+ // Get complete NS summary in one call
271
+ const summary = viz.dns.getNsSummary(account.json_metadata);
272
+
273
+ console.log('IPv4 Addresses:', summary.aRecords); // ['188.120.231.153']
274
+ console.log('SSL Hash:', summary.sslHash); // '4a4613daef37...'
275
+ console.log('TTL:', summary.ttl); // 28800
276
+
277
+ // Or extract individual components
278
+ const ipAddresses = viz.dns.extractARecords(account.json_metadata);
279
+ const sslHash = viz.dns.extractSslHash(account.json_metadata);
280
+ const ttl = viz.dns.extractTtl(account.json_metadata);
281
+ }
282
+ });
283
+ ```
284
+
285
+ ### Parse NS Data (JavaScript) - Manual Parsing
286
+
287
+ ```javascript
288
+ gate.api.getAccount('on1x', '', function(err, response) {
289
+ if (!err) {
290
+ let metadata = {};
291
+ try {
292
+ metadata = JSON.parse(response.json_metadata);
293
+ } catch (e) {
294
+ metadata = {};
295
+ }
296
+
297
+ if (typeof metadata.ns !== 'undefined') {
298
+ for (let i in metadata.ns) {
299
+ if (metadata.ns[i][0] === 'A') {
300
+ console.log('IPv4:', metadata.ns[i][1]);
301
+ }
302
+ if (metadata.ns[i][0] === 'TXT') {
303
+ let txt_arr = metadata.ns[i][1].split('=');
304
+ if (txt_arr[0] === 'ssl') {
305
+ console.log('SSL Hash:', txt_arr[1]);
306
+ }
307
+ }
308
+ }
309
+ }
310
+
311
+ if (typeof metadata.ttl !== 'undefined') {
312
+ console.log('TTL:', metadata.ttl);
313
+ }
314
+ }
315
+ });
316
+ ```
317
+
318
+ ### Parse NS Data (PHP)
319
+
320
+ ```php
321
+ $api = new JsonRPC($endpoint);
322
+ $accounts = $api->execute_method('get_accounts', [['on1x']]);
323
+
324
+ if ($accounts && count($accounts) > 0) {
325
+ $metadata = json_decode($accounts[0]['json_metadata'], true);
326
+
327
+ if (isset($metadata['ns'])) {
328
+ foreach ($metadata['ns'] as $record) {
329
+ if ($record[0] === 'A') {
330
+ echo "IPv4: " . $record[1] . PHP_EOL;
331
+ }
332
+ if ($record[0] === 'TXT') {
333
+ $txt = explode('=', $record[1]);
334
+ if ($txt[0] === 'ssl') {
335
+ echo "SSL Hash: " . $txt[1] . PHP_EOL;
336
+ }
337
+ }
338
+ }
339
+ }
340
+
341
+ if (isset($metadata['ttl'])) {
342
+ echo "TTL: " . $metadata['ttl'] . PHP_EOL;
343
+ }
344
+ }
345
+ ```
346
+
347
+ ---
348
+
349
+ ## viz-js-lib DNS Helpers Module
350
+
351
+ The `viz-js-lib` library provides a dedicated `dns` module with helper functions for working with VIZ DNS NS records.
352
+
353
+ ### Installation
354
+
355
+ ```bash
356
+ npm install viz-js-lib
357
+ ```
358
+
359
+ ### Import
360
+
361
+ ```javascript
362
+ const viz = require('viz-js-lib');
363
+ // Access via viz.dns.*
364
+ ```
365
+
366
+ ### Constants
367
+
368
+ | Constant | Value | Description |
369
+ |----------|-------|-------------|
370
+ | `viz.dns.DEFAULT_TTL` | `28800` | Default TTL in seconds (8 hours) |
371
+ | `viz.dns.MAX_TXT_LENGTH` | `256` | Maximum TXT record length |
372
+ | `viz.dns.SHA256_HEX_LENGTH` | `64` | SHA256 hash length in hex characters |
373
+
374
+ ### Validation Functions
375
+
376
+ #### `isValidIPv4(ipv4)`
377
+ Validates an IPv4 address string.
378
+
379
+ ```javascript
380
+ viz.dns.isValidIPv4('188.120.231.153'); // true
381
+ viz.dns.isValidIPv4('256.0.0.1'); // false
382
+ viz.dns.isValidIPv4('invalid'); // false
383
+ ```
384
+
385
+ #### `isValidSHA256Hash(hash)`
386
+ Validates a SHA256 hash string (64 hex characters).
387
+
388
+ ```javascript
389
+ viz.dns.isValidSHA256Hash('4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2'); // true
390
+ viz.dns.isValidSHA256Hash('invalid'); // false
391
+ ```
392
+
393
+ #### `isValidTTL(ttl)`
394
+ Validates a TTL value (must be positive integer).
395
+
396
+ ```javascript
397
+ viz.dns.isValidTTL(28800); // true
398
+ viz.dns.isValidTTL(-1); // false
399
+ viz.dns.isValidTTL(1.5); // false
400
+ ```
401
+
402
+ #### `isValidSslTxtRecord(txt)`
403
+ Validates an SSL TXT record format (`ssl=<hash>`).
404
+
405
+ ```javascript
406
+ viz.dns.isValidSslTxtRecord('ssl=4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2'); // true
407
+ viz.dns.isValidSslTxtRecord('ssl=invalid'); // false
408
+ ```
409
+
410
+ #### `validateNsMetadata(nsData)`
411
+ Performs complete validation of NS metadata structure.
412
+
413
+ ```javascript
414
+ const result = viz.dns.validateNsMetadata({
415
+ ns: [['A', '188.120.231.153'], ['TXT', 'ssl=...']],
416
+ ttl: 28800
417
+ });
418
+ console.log(result.isValid); // true
419
+ console.log(result.errors); // []
420
+ ```
421
+
422
+ ### Record Creation Functions
423
+
424
+ #### `createARecord(ipv4)`
425
+ Creates an A record tuple.
426
+
427
+ ```javascript
428
+ viz.dns.createARecord('188.120.231.153');
429
+ // Returns: ['A', '188.120.231.153']
430
+ ```
431
+
432
+ #### `createSslTxtRecord(hash)`
433
+ Creates an SSL TXT record tuple from a SHA256 hash.
434
+
435
+ ```javascript
436
+ viz.dns.createSslTxtRecord('4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2');
437
+ // Returns: ['TXT', 'ssl=4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2']
438
+ ```
439
+
440
+ #### `createTxtRecord(value)`
441
+ Creates a generic TXT record tuple.
442
+
443
+ ```javascript
444
+ viz.dns.createTxtRecord('custom=value');
445
+ // Returns: ['TXT', 'custom=value']
446
+ ```
447
+
448
+ #### `createNsMetadata(options)`
449
+ Creates a complete NS metadata object.
450
+
451
+ ```javascript
452
+ const nsData = viz.dns.createNsMetadata({
453
+ aRecords: ['188.120.231.153', '192.168.1.100'],
454
+ sslHash: '4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2',
455
+ ttl: 28800 // optional, defaults to 28800
456
+ });
457
+ // Returns:
458
+ // {
459
+ // ns: [
460
+ // ['A', '188.120.231.153'],
461
+ // ['A', '192.168.1.100'],
462
+ // ['TXT', 'ssl=4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2']
463
+ // ],
464
+ // ttl: 28800
465
+ // }
466
+ ```
467
+
468
+ ### Parsing Functions
469
+
470
+ #### `parseNsMetadata(jsonMetadata)`
471
+ Parses NS metadata from account `json_metadata` (string or object).
472
+
473
+ ```javascript
474
+ const nsData = viz.dns.parseNsMetadata(account.json_metadata);
475
+ // Returns: { ns: [...], ttl: 28800 } or null if not found
476
+ ```
477
+
478
+ #### `extractARecords(jsonMetadata)`
479
+ Extracts all IPv4 addresses from A records.
480
+
481
+ ```javascript
482
+ const ips = viz.dns.extractARecords(account.json_metadata);
483
+ // Returns: ['188.120.231.153', '192.168.1.100']
484
+ ```
485
+
486
+ #### `extractSslHash(jsonMetadata)`
487
+ Extracts the SSL certificate hash from TXT records.
488
+
489
+ ```javascript
490
+ const hash = viz.dns.extractSslHash(account.json_metadata);
491
+ // Returns: '4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2' or null
492
+ ```
493
+
494
+ #### `extractTxtRecords(jsonMetadata)`
495
+ Extracts all TXT record values.
496
+
497
+ ```javascript
498
+ const txtRecords = viz.dns.extractTxtRecords(account.json_metadata);
499
+ // Returns: ['ssl=4a4613...', 'other=value']
500
+ ```
501
+
502
+ #### `extractTtl(jsonMetadata)`
503
+ Extracts the TTL value (returns default if not set).
504
+
505
+ ```javascript
506
+ const ttl = viz.dns.extractTtl(account.json_metadata);
507
+ // Returns: 28800
508
+ ```
509
+
510
+ #### `getNsSummary(jsonMetadata)`
511
+ Returns a complete summary of all NS data.
512
+
513
+ ```javascript
514
+ const summary = viz.dns.getNsSummary(account.json_metadata);
515
+ // Returns:
516
+ // {
517
+ // aRecords: ['188.120.231.153'],
518
+ // sslHash: '4a4613daef37...',
519
+ // txtRecords: ['ssl=4a4613daef37...'],
520
+ // ttl: 28800
521
+ // }
522
+ ```
523
+
524
+ #### `hasNsRecords(jsonMetadata)`
525
+ Checks if NS records exist in the metadata.
526
+
527
+ ```javascript
528
+ if (viz.dns.hasNsRecords(account.json_metadata)) {
529
+ console.log('Account has NS records configured');
530
+ }
531
+ ```
532
+
533
+ ### Metadata Manipulation Functions
534
+
535
+ #### `mergeNsMetadata(existingMetadata, nsData)`
536
+ Merges NS data into existing account metadata (preserves other fields).
537
+
538
+ ```javascript
539
+ const existingMetadata = { profile: { name: 'My Site' } };
540
+ const nsData = viz.dns.createNsMetadata({ aRecords: ['188.120.231.153'] });
541
+ const merged = viz.dns.mergeNsMetadata(existingMetadata, nsData);
542
+ // Returns:
543
+ // {
544
+ // profile: { name: 'My Site' },
545
+ // ns: [['A', '188.120.231.153']],
546
+ // ttl: 28800
547
+ // }
548
+ ```
549
+
550
+ #### `removeNsMetadata(existingMetadata)`
551
+ Removes NS data from metadata (preserves other fields).
552
+
553
+ ```javascript
554
+ const cleaned = viz.dns.removeNsMetadata(account.json_metadata);
555
+ // Returns metadata without ns and ttl fields
556
+ ```
557
+
558
+ #### `addARecord(jsonMetadata, ipv4)`
559
+ Adds an A record to existing metadata.
560
+
561
+ ```javascript
562
+ const updated = viz.dns.addARecord(account.json_metadata, '192.168.1.100');
563
+ ```
564
+
565
+ #### `removeARecord(jsonMetadata, ipv4)`
566
+ Removes a specific A record from metadata.
567
+
568
+ ```javascript
569
+ const updated = viz.dns.removeARecord(account.json_metadata, '192.168.1.100');
570
+ ```
571
+
572
+ #### `setSslHash(jsonMetadata, hash)`
573
+ Sets or updates the SSL hash (replaces existing if present).
574
+
575
+ ```javascript
576
+ const updated = viz.dns.setSslHash(account.json_metadata, 'new_hash_here...');
577
+ ```
578
+
579
+ #### `removeSslHash(jsonMetadata)`
580
+ Removes the SSL hash TXT record.
581
+
582
+ ```javascript
583
+ const updated = viz.dns.removeSslHash(account.json_metadata);
584
+ ```
585
+
586
+ #### `setTtl(jsonMetadata, ttl)`
587
+ Sets the TTL value.
588
+
589
+ ```javascript
590
+ const updated = viz.dns.setTtl(account.json_metadata, 3600); // 1 hour
591
+ ```
592
+
593
+ ### Complete Usage Examples
594
+
595
+ #### Setting NS Records with viz-js-lib
596
+
597
+ ```javascript
598
+ const viz = require('viz-js-lib');
599
+
600
+ // Get current account metadata
601
+ viz.api.getAccounts(['myaccount'], function(err, accounts) {
602
+ if (err) return console.error(err);
603
+
604
+ const account = accounts[0];
605
+
606
+ // Create NS data
607
+ const nsData = viz.dns.createNsMetadata({
608
+ aRecords: ['188.120.231.153'],
609
+ sslHash: '4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2',
610
+ ttl: 28800
611
+ });
612
+
613
+ // Merge with existing metadata
614
+ const updatedMetadata = viz.dns.mergeNsMetadata(account.json_metadata, nsData);
615
+
616
+ // Broadcast update
617
+ viz.broadcast.accountMetadata(
618
+ regularKey,
619
+ 'myaccount',
620
+ JSON.stringify(updatedMetadata),
621
+ function(err, result) {
622
+ if (!err) {
623
+ console.log('NS records updated successfully');
624
+ }
625
+ }
626
+ );
627
+ });
628
+ ```
629
+
630
+ #### Adding Round Robin A Records
631
+
632
+ ```javascript
633
+ let metadata = viz.dns.addARecord(account.json_metadata, '188.120.231.153');
634
+ metadata = viz.dns.addARecord(metadata, '192.168.1.100');
635
+ metadata = viz.dns.addARecord(metadata, '10.0.0.50');
636
+ metadata = viz.dns.setSslHash(metadata, 'your_ssl_hash_here');
637
+
638
+ // Broadcast the update...
639
+ ```
640
+
641
+ #### Removing NS Configuration
642
+
643
+ ```javascript
644
+ const cleanedMetadata = viz.dns.removeNsMetadata(account.json_metadata);
645
+
646
+ viz.broadcast.accountMetadata(
647
+ regularKey,
648
+ 'myaccount',
649
+ JSON.stringify(cleanedMetadata),
650
+ callback
651
+ );
652
+ ```
653
+
654
+ #### Validating NS Configuration Before Broadcast
655
+
656
+ ```javascript
657
+ const nsData = viz.dns.createNsMetadata({
658
+ aRecords: ['188.120.231.153'],
659
+ sslHash: 'your_hash_here'
660
+ });
661
+
662
+ const validation = viz.dns.validateNsMetadata(nsData);
663
+ if (!validation.isValid) {
664
+ console.error('Invalid NS configuration:', validation.errors);
665
+ return;
666
+ }
667
+
668
+ // Proceed with broadcast...
669
+ ```
670
+
671
+ ---
672
+
673
+ ## SSL Certificate Verification
674
+
675
+ ### Concept
676
+
677
+ VIZ DNS uses a self-signed certificate verification system where:
678
+ 1. The **SHA256 hash of the public key** is stored in the TXT record
679
+ 2. Clients connect to the server and extract the certificate's public key
680
+ 3. The hash is compared to verify authenticity
681
+
682
+ This approach works with:
683
+ - Self-signed certificates
684
+ - Let's Encrypt certificates
685
+ - Any CA-signed certificates
686
+
687
+ ### Generating SSL Hash
688
+
689
+ #### From Private Key (Server Side)
690
+
691
+ ```bash
692
+ # Get public key hash from private key
693
+ openssl rsa -in /etc/letsencrypt/live/example.com/privkey.pem -pubout | sha256sum
694
+
695
+ # Output: 4a4613daef37cbc5c4a5156cd7b24ea2e6ee2e5f1e7461262a2df2b63cbf17e2
696
+ ```
697
+
698
+ #### From Certificate (Server Side)
699
+
700
+ ```bash
701
+ # Get public key hash from certificate chain
702
+ openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -pubkey -nocert | sha256sum
703
+ ```
704
+
705
+ #### From Remote Server
706
+
707
+ ```bash
708
+ # Get certificate info from remote server
709
+ echo | openssl s_client -servername example.com -connect 188.120.231.153:443 | \
710
+ openssl x509 -noout -pubkey -dates
711
+
712
+ # Get just the public key hash
713
+ echo | openssl s_client -servername example.com -connect 188.120.231.153:443 2>/dev/null | \
714
+ openssl x509 -pubkey -nocert | sha256sum
715
+ ```
716
+
717
+ ### PHP Implementation for SSL Verification
718
+
719
+ ```php
720
+ /**
721
+ * Extract SSL public key hash from a domain
722
+ *
723
+ * @param string $domain Domain name or IP address
724
+ * @param string|null $ipv4 Optional IP address override
725
+ * @return array ['error' => bool, 'result' => [ipv4, hash]]
726
+ */
727
+ function get_ssl_hash($domain, $ipv4 = null) {
728
+ // Resolve IP if not provided
729
+ if ($ipv4 === null) {
730
+ $ipv4 = gethostbyname($domain);
731
+ if ($ipv4 === $domain) {
732
+ return ['error' => 'dns_resolution_failed'];
733
+ }
734
+ }
735
+
736
+ // Create SSL context
737
+ $streamContext = stream_context_create([
738
+ 'ssl' => [
739
+ 'peer_name' => $domain,
740
+ 'verify_peer' => false,
741
+ 'verify_peer_name' => false,
742
+ 'capture_peer_cert' => true,
743
+ ],
744
+ ]);
745
+
746
+ // Connect to server
747
+ $client = stream_socket_client(
748
+ 'ssl://' . $ipv4 . ':443',
749
+ $errorNumber,
750
+ $errorDescription,
751
+ 3,
752
+ STREAM_CLIENT_CONNECT,
753
+ $streamContext
754
+ );
755
+
756
+ if ($errorNumber !== 0) {
757
+ return ['error' => 'connection_failed: ' . $errorDescription];
758
+ }
759
+
760
+ $response = stream_context_get_params($client);
761
+
762
+ // Extract public key and compute hash
763
+ $public_key = openssl_pkey_get_public(
764
+ $response['options']['ssl']['peer_certificate']
765
+ );
766
+ $public_key_data = openssl_pkey_get_details($public_key);
767
+
768
+ // Hash the full PEM-encoded public key (including headers)
769
+ $hash = hash('sha256', $public_key_data['key'], false);
770
+
771
+ fclose($client);
772
+
773
+ return ['error' => false, 'result' => [$ipv4, $hash]];
774
+ }
775
+ ```
776
+
777
+ ### Complete SSL Verification Process
778
+
779
+ ```php
780
+ /**
781
+ * Verify SSL certificate against VIZ blockchain records
782
+ *
783
+ * @param string $account VIZ account name (domain)
784
+ * @param string $ipv4 Server IP address
785
+ * @return bool True if certificate is valid
786
+ */
787
+ function verify_viz_ssl($account, $ipv4) {
788
+ global $api;
789
+
790
+ // 1. Get account metadata from blockchain
791
+ $accounts = $api->execute_method('get_accounts', [[$account]]);
792
+ if (!$accounts || count($accounts) === 0) {
793
+ return false;
794
+ }
795
+
796
+ $metadata = json_decode($accounts[0]['json_metadata'], true);
797
+ if (!isset($metadata['ns'])) {
798
+ return false;
799
+ }
800
+
801
+ // 2. Extract expected SSL hash from TXT record
802
+ $expected_hash = null;
803
+ foreach ($metadata['ns'] as $record) {
804
+ if ($record[0] === 'TXT') {
805
+ $txt = explode('=', $record[1]);
806
+ if ($txt[0] === 'ssl') {
807
+ $expected_hash = $txt[1];
808
+ break;
809
+ }
810
+ }
811
+ }
812
+
813
+ if ($expected_hash === null) {
814
+ return false;
815
+ }
816
+
817
+ // 3. Get actual SSL hash from server
818
+ $ssl_result = get_ssl_hash($account, $ipv4);
819
+ if ($ssl_result['error'] !== false) {
820
+ return false;
821
+ }
822
+
823
+ $actual_hash = $ssl_result['result'][1];
824
+
825
+ // 4. Compare hashes
826
+ return hash_equals($expected_hash, $actual_hash);
827
+ }
828
+ ```
829
+
830
+ ---
831
+
832
+ ## Building a VIZ DNS System
833
+
834
+ ### Architecture Recommendations
835
+
836
+ #### 1. DNS Resolver Component
837
+
838
+ Build a custom DNS resolver that:
839
+ - Intercepts DNS queries for `.viz` domains (or custom TLD)
840
+ - Queries VIZ blockchain for account metadata
841
+ - Returns A records from the `ns` array
842
+ - Implements TTL caching based on the `ttl` field
843
+
844
+ ```
845
+ Client Request → VIZ DNS Resolver → VIZ Blockchain
846
+
847
+ Local DNS Cache (TTL-based)
848
+
849
+ DNS Response
850
+ ```
851
+
852
+ #### 2. SSL/TLS Proxy
853
+
854
+ Implement a reverse proxy that:
855
+ - Terminates TLS connections
856
+ - Validates certificate public key hash against blockchain records
857
+ - Forwards requests to the actual server
858
+
859
+ #### 3. Web Server Configuration (nginx)
860
+
861
+ Configure nginx to serve multiple domains from the same server:
862
+
863
+ ```nginx
864
+ server {
865
+ listen 443 ssl;
866
+ server_name example.com www.example.com example; # Include VIZ domain name
867
+
868
+ ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
869
+ ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
870
+
871
+ # ... rest of config
872
+ }
873
+
874
+ server {
875
+ listen 80;
876
+ server_name example.com www.example.com example;
877
+
878
+ # Redirect to HTTPS
879
+ return 301 https://$host$request_uri;
880
+ }
881
+ ```
882
+
883
+ ### Implementation Steps
884
+
885
+ #### Step 1: Register VIZ Account
886
+
887
+ The account name serves as the domain name:
888
+ - `on1x` → resolves to `on1x` domain
889
+ - `mysite` → resolves to `mysite` domain
890
+
891
+ #### Step 2: Configure Web Server
892
+
893
+ 1. Generate or obtain SSL certificate
894
+ 2. Configure nginx to accept connections for the VIZ domain name
895
+ 3. Restart nginx: `service nginx restart`
896
+
897
+ #### Step 3: Calculate SSL Hash
898
+
899
+ ```bash
900
+ # Calculate hash from your certificate
901
+ openssl x509 -in /etc/letsencrypt/live/yourdomain.com/fullchain.pem -pubkey -nocert | sha256sum
902
+ ```
903
+
904
+ #### Step 4: Set NS Records on Blockchain
905
+
906
+ Use the VIZ.World Control Panel (`/tools/ns/`) or programmatically:
907
+
908
+ ```javascript
909
+ // Via Control Panel UI or API
910
+ metadata.ns = [
911
+ ['A', 'YOUR_SERVER_IP'],
912
+ ['TXT', 'ssl=YOUR_CALCULATED_HASH']
913
+ ];
914
+ metadata.ttl = 28800;
915
+ ```
916
+
917
+ #### Step 5: Implement Client Verification
918
+
919
+ Clients should:
920
+ 1. Query VIZ blockchain for account metadata
921
+ 2. Extract IP from A record
922
+ 3. Connect to server via HTTPS
923
+ 4. Extract server's public key
924
+ 5. Hash and compare with TXT record
925
+ 6. If match, connection is trusted
926
+
927
+ ### Security Considerations
928
+
929
+ 1. **Hash Algorithm**: SHA256 is recommended for public key hashing
930
+ 2. **TTL Management**: Use appropriate TTL values (28800 seconds = 8 hours is default)
931
+ 3. **Certificate Rotation**: Update TXT record when certificates are renewed
932
+ 4. **Multiple A Records**: Ensure all servers share the same certificate (for Round Robin)
933
+
934
+ ### Verification Commands
935
+
936
+ ```bash
937
+ # Verify certificate from server
938
+ echo | openssl s_client -servername on1x -connect 188.120.231.153:443 | \
939
+ openssl x509 -noout -pubkey -dates
940
+
941
+ # Get certificate dates
942
+ openssl x509 -in /etc/letsencrypt/live/on1x.com/fullchain.pem -noout -startdate -enddate
943
+ # notBefore=Aug 26 11:17:39 2023 GMT
944
+ # notAfter=Nov 24 11:17:38 2023 GMT
945
+ ```
946
+
947
+ ---
948
+
949
+ ## Existing Implementation Reference
950
+
951
+ ### viz-js-lib DNS Module
952
+ - **JavaScript**: [src/dns.js](file:///d:/Work/viz-js-lib/src/dns.js) - DNS helpers module
953
+ - **Tests**: [test/dns.test.js](file:///d:/Work/viz-js-lib/test/dns.test.js) - Test suite
954
+ - **Export**: [src/index.js](file:///d:/Work/viz-js-lib/src/index.js) - Module export as `viz.dns`
955
+
956
+ ### VIZ.World Control Panel
957
+
958
+ #### UI Component Location
959
+ - **PHP**: [module/tools.php](file:///d:/Work/viz.world/backup-16-11-2024/control.viz.world/module/tools.php#L25-L34) - `/tools/ns/` route
960
+ - **JavaScript**: [js/app.js](file:///d:/Work/viz.world/backup-16-11-2024/control.viz.world/js/app.js#L2072-L2249) - `ns_control()` function
961
+
962
+ #### AJAX Handler
963
+ - **PHP**: [module/ajax.php](file:///d:/Work/viz.world/backup-16-11-2024/control.viz.world/module/ajax.php#L4-L79) - `/ajax/ns/` endpoint
964
+
965
+ #### Transaction Builder
966
+ - **PHP**: [class/VIZ/Transaction.php](file:///d:/Work/viz.world/backup-16-11-2024/control.viz.world/class/VIZ/Transaction.php#L665-L675) - `build_account_metadata()` method
967
+
968
+ ---
969
+
970
+ ## Summary
971
+
972
+ | Component | Description |
973
+ |-----------|-------------|
974
+ | **Data Storage** | Account `json_metadata` field |
975
+ | **Record Types** | A (IPv4), TXT (SSL hash) |
976
+ | **Operation** | `account_metadata` |
977
+ | **Authority** | Regular key |
978
+ | **Hash Algorithm** | SHA256 of PEM-encoded public key |
979
+ | **Default TTL** | 28800 seconds (8 hours) |
980
+ | **JavaScript Library** | `viz-js-lib` - `viz.dns.*` module |
981
+
982
+ This system provides a decentralized, blockchain-based alternative to traditional DNS with built-in SSL certificate verification capabilities.