@smartledger/bsv 3.4.3 → 3.4.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 (87) hide show
  1. package/CHANGELOG.md +321 -0
  2. package/README.md +72 -72
  3. package/SECURITY.md +88 -0
  4. package/bin/cli.js +13 -8
  5. package/bsv-covenant.min.js +4 -4
  6. package/bsv-gdaf.min.js +5 -5
  7. package/bsv-ltp.min.js +7 -7
  8. package/bsv-smartcontract.min.js +5 -5
  9. package/bsv.bundle.js +5 -5
  10. package/bsv.d.ts +486 -9
  11. package/bsv.min.js +5 -5
  12. package/docs/COVENANT_DEVELOPMENT_RESOLVED.md +2 -2
  13. package/docs/MODULE_REFERENCE_COMPLETE.md +60 -57
  14. package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
  15. package/docs/getting-started/INSTALLATION.md +30 -30
  16. package/docs/getting-started/QUICK_START.md +14 -14
  17. package/docs/migration/FROM_BSV_1_5_6.md +5 -5
  18. package/gdaf-entry.js +1 -2
  19. package/index.js +20 -7
  20. package/lib/smart_contract/covenant.js +10 -1
  21. package/lib/smartutxo.js +20 -12
  22. package/lib/transaction/transaction.js +7 -0
  23. package/ltp-entry.js +1 -2
  24. package/package.json +3 -3
  25. package/utilities/blockchain-state.js +32 -23
  26. package/demos/README.md +0 -188
  27. package/demos/architecture_demo.js +0 -247
  28. package/demos/browser-test.html +0 -1208
  29. package/demos/bsv_wallet_demo.js +0 -242
  30. package/demos/complete_ltp_demo.js +0 -511
  31. package/demos/debug_tools_demo.js +0 -87
  32. package/demos/demo_features.js +0 -123
  33. package/demos/easy_interface_demo.js +0 -109
  34. package/demos/ecies_demo.js +0 -182
  35. package/demos/gdaf_demo.js +0 -237
  36. package/demos/ltp_demo.js +0 -361
  37. package/demos/ltp_primitives_demo.js +0 -403
  38. package/demos/message_demo.js +0 -209
  39. package/demos/preimage_separation_demo.js +0 -383
  40. package/demos/script_helper_demo.js +0 -289
  41. package/demos/security_demo.js +0 -287
  42. package/demos/shamir_demo.js +0 -121
  43. package/demos/simple_demo.js +0 -204
  44. package/demos/simple_p2pkh_demo.js +0 -169
  45. package/demos/simple_utxo_preimage_demo.js +0 -196
  46. package/demos/smart_contract_demo.html +0 -1347
  47. package/demos/smart_contract_demo.js +0 -910
  48. package/demos/utxo_generator_demo.js +0 -244
  49. package/demos/validation_pipeline_demo.js +0 -155
  50. package/demos/web3keys.html +0 -740
  51. package/examples/README.md +0 -200
  52. package/examples/basic/transaction-creation.js +0 -534
  53. package/examples/basic/transaction_signature_api_gap.js +0 -178
  54. package/examples/complete_workflow_demo.js +0 -783
  55. package/examples/covenants/advanced_covenant_demo.js +0 -219
  56. package/examples/covenants/covenant_interface_demo.js +0 -270
  57. package/examples/covenants/covenant_manual_signature_resolved.js +0 -212
  58. package/examples/covenants/covenant_signature_template.js +0 -117
  59. package/examples/covenants2/covenant_bidirectional_example.js +0 -262
  60. package/examples/covenants2/covenant_utils_demo.js +0 -120
  61. package/examples/covenants2/preimage_covenant_utils.js +0 -287
  62. package/examples/covenants2/production_integration.js +0 -256
  63. package/examples/data/covenant_utxos.json +0 -28
  64. package/examples/data/utxos.json +0 -26
  65. package/examples/definitive_working_demo.js +0 -261
  66. package/examples/final_working_contracts.js +0 -338
  67. package/examples/legacy/README.md +0 -11
  68. package/examples/legacy/smart_contract_test_integration.js +0 -269
  69. package/examples/legacy/test_builtin_verify.js +0 -117
  70. package/examples/legacy/test_debug_integration.js +0 -71
  71. package/examples/legacy/test_ecdsa_little.js +0 -70
  72. package/examples/legacy/test_shamir.js +0 -221
  73. package/examples/legacy/test_smartverify_der.js +0 -110
  74. package/examples/preimage/README.md +0 -178
  75. package/examples/preimage/extract_preimage_bidirectional.js +0 -421
  76. package/examples/preimage/generate_sample_preimage.js +0 -208
  77. package/examples/preimage/generate_sighash_examples.js +0 -152
  78. package/examples/preimage/parse_preimage.js +0 -117
  79. package/examples/preimage/test_preimage_extractor.js +0 -53
  80. package/examples/preimage/test_varint_extraction.js +0 -95
  81. package/examples/scripts/custom_script_helper_example.js +0 -273
  82. package/examples/scripts/script_interpreter.js +0 -193
  83. package/examples/smart_contract/complete_workflow_demo.js +0 -343
  84. package/examples/smart_contract/covenant_builder_demo.js +0 -176
  85. package/examples/smart_contract/script_testing_integration.js +0 -198
  86. package/examples/smart_contract_templates.js +0 -718
  87. package/examples/working_smart_contracts.js +0 -348
@@ -1,1208 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>SmartLedger-BSV Browser Test</title>
7
- <style>
8
- body {
9
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
10
- max-width: 1200px;
11
- margin: 0 auto;
12
- padding: 20px;
13
- background-color: #f5f5f5;
14
- }
15
- .container {
16
- background: white;
17
- padding: 30px;
18
- border-radius: 10px;
19
- box-shadow: 0 2px 10px rgba(0,0,0,0.1);
20
- }
21
- h1 {
22
- color: #333;
23
- border-bottom: 3px solid #007acc;
24
- padding-bottom: 10px;
25
- }
26
- h2 {
27
- color: #444;
28
- margin-top: 30px;
29
- }
30
- .test-section {
31
- background: #f8f9fa;
32
- padding: 15px;
33
- margin: 15px 0;
34
- border-radius: 5px;
35
- border-left: 4px solid #007acc;
36
- }
37
- .result {
38
- background: #e8f5e8;
39
- padding: 10px;
40
- margin: 10px 0;
41
- border-radius: 4px;
42
- font-family: monospace;
43
- white-space: pre-wrap;
44
- overflow-x: auto;
45
- }
46
- .error {
47
- background: #ffe8e8;
48
- color: #d32f2f;
49
- }
50
- .success {
51
- background: #e8f5e8;
52
- color: #2e7d32;
53
- }
54
- button {
55
- background: #007acc;
56
- color: white;
57
- border: none;
58
- padding: 10px 20px;
59
- border-radius: 5px;
60
- cursor: pointer;
61
- margin: 5px;
62
- font-size: 14px;
63
- }
64
- button:hover {
65
- background: #005a9e;
66
- }
67
- button:disabled {
68
- background: #ccc;
69
- cursor: not-allowed;
70
- }
71
- .status {
72
- margin: 10px 0;
73
- padding: 10px;
74
- border-radius: 4px;
75
- }
76
- .loading {
77
- background: #fff3cd;
78
- color: #856404;
79
- }
80
- .loaded {
81
- background: #d4edda;
82
- color: #155724;
83
- }
84
- .failed {
85
- background: #f8d7da;
86
- color: #721c24;
87
- }
88
- .key-pair {
89
- background: #e3f2fd;
90
- padding: 15px;
91
- margin: 10px 0;
92
- border-radius: 5px;
93
- border: 1px solid #bbdefb;
94
- }
95
- .key-pair h4 {
96
- margin: 0 0 10px 0;
97
- color: #1976d2;
98
- }
99
- .key-item {
100
- margin: 5px 0;
101
- font-family: monospace;
102
- font-size: 12px;
103
- word-break: break-all;
104
- }
105
- </style>
106
- </head>
107
- <body>
108
- <div class="container">
109
- <h1>🔧 SmartLedger-BSV Browser Integration Test</h1>
110
-
111
- <div id="loadStatus" class="status loading">
112
- 📡 Loading SmartLedger-BSV from CDN...
113
- </div>
114
-
115
- <div class="test-section">
116
- <h2>📋 Library Information</h2>
117
- <button onclick="testLibraryInfo()">Test Library Info</button>
118
- <div id="libraryInfo" class="result"></div>
119
- </div>
120
-
121
- <div class="test-section">
122
- <h2>🎲 Mnemonic & Seed Generation</h2>
123
- <button onclick="testMnemonicGeneration()">Test Mnemonic Features</button>
124
- <input type="text" id="customPassphrase" placeholder="Enter custom passphrase (optional)" style="width: 300px; margin: 5px;">
125
- <button onclick="testCustomPassphrase()">Test with Custom Passphrase</button>
126
- <br>
127
- <textarea id="importMnemonic" placeholder="Enter existing mnemonic words (12-24 words)" style="width: 100%; height: 60px; margin: 5px; font-family: monospace; padding: 8px;" rows="3"></textarea>
128
- <button onclick="testImportedMnemonic()">Test Imported Mnemonic</button>
129
- <button onclick="clearMnemonicInput()">Clear</button>
130
- <div id="mnemonicTesting" class="result"></div>
131
- </div>
132
-
133
- <div class="test-section">
134
- <h2>🔑 Key Generation & Derivation</h2>
135
- <button onclick="testKeyGeneration()">Generate Test Keys</button>
136
- <button onclick="generateMnemonic()">Generate New Mnemonic</button>
137
- <div id="keyGeneration" class="result"></div>
138
- <div id="generatedKeys"></div>
139
- </div>
140
-
141
- <div class="test-section">
142
- <h2>🖊️ Digital Signatures</h2>
143
- <button onclick="testSignatures()">Test Signing & Verification</button>
144
- <div id="signatures" class="result"></div>
145
- </div>
146
-
147
- <div class="test-section">
148
- <h2>🆔 DID Generation</h2>
149
- <button onclick="testDIDGeneration()">Generate DIDs</button>
150
- <div id="didGeneration" class="result"></div>
151
- </div>
152
-
153
- <div class="test-section">
154
- <h2>💰 Address Generation</h2>
155
- <button onclick="testAddressGeneration()">Generate Addresses</button>
156
- <div id="addressGeneration" class="result"></div>
157
- </div>
158
-
159
- <div class="test-section">
160
- <h2>� Browser UTXO Manager</h2>
161
- <button onclick="testBrowserUTXOManager()">Test UTXO Management</button>
162
- <select id="storageTypeSelect" style="margin: 5px;">
163
- <option value="memory">Memory Storage</option>
164
- <option value="session">Session Storage</option>
165
- <option value="local">Local Storage</option>
166
- </select>
167
- <button onclick="testDifferentStorageTypes()">Test Storage Types</button>
168
- <div id="utxoManager" class="result"></div>
169
- </div>
170
-
171
- <div class="test-section">
172
- <h2>�🔐 SmartLedger Enhanced Features</h2>
173
- <button onclick="testSmartFeatures()">Test SmartVerify & Security</button>
174
- <div id="smartFeatures" class="result"></div>
175
- </div>
176
-
177
- <div class="test-section">
178
- <h2>🧪 Full Web3Keys Simulation</h2>
179
- <button onclick="runFullSimulation()">Run Complete Web3Keys Test</button>
180
- <div id="fullSimulation" class="result"></div>
181
- </div>
182
- </div>
183
-
184
- <!-- Load SmartLedger-BSV from CDN -->
185
- <script src="https://unpkg.com/smartledger-bsv@3.3.5/bsv.bundle.js"></script>
186
-
187
- <script>
188
- let bsv;
189
- let Buffer; // Browser Buffer support
190
- let testMnemonic = '';
191
-
192
- // Wait for library to load
193
- window.addEventListener('load', function() {
194
- setTimeout(() => {
195
- if (window.bsv) {
196
- bsv = window.bsv;
197
- Buffer = bsv.deps.Buffer; // Use SmartLedger's Buffer implementation
198
-
199
- document.getElementById('loadStatus').className = 'status loaded';
200
- document.getElementById('loadStatus').innerHTML = '✅ SmartLedger-BSV loaded successfully!';
201
-
202
- // Display available modules
203
- const availableModules = Object.keys(bsv);
204
- document.getElementById('loadStatus').innerHTML +=
205
- `<br><strong>Available modules:</strong> ${availableModules.join(', ')}`;
206
- } else {
207
- document.getElementById('loadStatus').className = 'status failed';
208
- document.getElementById('loadStatus').innerHTML = '❌ Failed to load SmartLedger-BSV';
209
- }
210
- }, 1000);
211
- });
212
-
213
- function testLibraryInfo() {
214
- try {
215
- const info = {
216
- availableModules: Object.keys(bsv),
217
- version: bsv.version || 'Unknown',
218
- hasHDPrivateKey: typeof bsv.HDPrivateKey,
219
- hasPublicKey: typeof bsv.PublicKey,
220
- hasAddress: typeof bsv.Address,
221
- hasTransaction: typeof bsv.Transaction,
222
- hasScript: typeof bsv.Script,
223
- hasCrypto: typeof bsv.crypto,
224
- hasSmartLedger: typeof bsv.SmartLedger,
225
- hasSmartVerify: typeof bsv.SmartVerify
226
- };
227
-
228
- document.getElementById('libraryInfo').className = 'result success';
229
- document.getElementById('libraryInfo').textContent = JSON.stringify(info, null, 2);
230
- } catch (error) {
231
- document.getElementById('libraryInfo').className = 'result error';
232
- document.getElementById('libraryInfo').textContent = 'Error: ' + error.message;
233
- }
234
- }
235
-
236
- function generateMnemonic() {
237
- try {
238
- // Check if Buffer is available
239
- if (!Buffer) {
240
- Buffer = bsv.deps.Buffer;
241
- }
242
-
243
- let results = [];
244
-
245
- if (bsv.Mnemonic) {
246
- // Generate 24-word mnemonic (256-bit entropy)
247
- const mnemonic = bsv.Mnemonic.fromRandom(256);
248
- const mnemonicString = mnemonic.toString();
249
- const wordCount = mnemonicString.split(' ').length;
250
-
251
- results.push(`Generated 24-word Mnemonic (${wordCount} words):`);
252
- results.push(mnemonicString);
253
- results.push('');
254
-
255
- // Test different entropy levels
256
- const entropies = [
257
- { bits: 128, words: 12, name: '12-word' },
258
- { bits: 160, words: 15, name: '15-word' },
259
- { bits: 192, words: 18, name: '18-word' },
260
- { bits: 224, words: 21, name: '21-word' },
261
- { bits: 256, words: 24, name: '24-word' }
262
- ];
263
-
264
- results.push('📊 Mnemonic Entropy Options:');
265
- entropies.forEach(entropy => {
266
- try {
267
- const testMnemonic = bsv.Mnemonic.fromRandom(entropy.bits);
268
- const testWords = testMnemonic.toString().split(' ').length;
269
- results.push(` ✅ ${entropy.name} (${entropy.bits}-bit): ${testWords} words generated`);
270
- } catch (e) {
271
- results.push(` ❌ ${entropy.name} (${entropy.bits}-bit): ${e.message}`);
272
- }
273
- });
274
- results.push('');
275
-
276
- // Test passphrase functionality
277
- results.push('🔐 Passphrase Testing:');
278
- const testPassphrase = 'Web3Keys-secure-passphrase-2025';
279
- const seedWithPassphrase = mnemonic.toSeed(testPassphrase);
280
- const seedWithoutPassphrase = mnemonic.toSeed();
281
-
282
- results.push(` ✅ Seed with passphrase: ${seedWithPassphrase.toString('hex').substring(0, 32)}...`);
283
- results.push(` ✅ Seed without passphrase: ${seedWithoutPassphrase.toString('hex').substring(0, 32)}...`);
284
- results.push(` ✅ Different seeds: ${!seedWithPassphrase.equals(seedWithoutPassphrase) ? 'YES' : 'NO'}`);
285
- results.push('');
286
-
287
- // Validate mnemonic
288
- const isValid = bsv.Mnemonic.isValid(mnemonicString);
289
- results.push(`✅ Mnemonic validation: ${isValid ? 'VALID' : 'INVALID'}`);
290
-
291
- testMnemonic = mnemonicString;
292
- } else if (bsv.crypto && bsv.crypto.Random) {
293
- // Fallback: Generate using crypto.Random
294
- const entropy = bsv.crypto.Random.getRandomBuffer(32); // 256 bits
295
- results.push('Generated entropy (256-bit):');
296
- results.push(entropy.toString('hex'));
297
- results.push('⚠️ Note: Mnemonic class not available, showing raw entropy');
298
- } else {
299
- results.push('❌ Mnemonic generation not available in browser version');
300
- }
301
-
302
- document.getElementById('keyGeneration').className = 'result success';
303
- document.getElementById('keyGeneration').textContent = results.join('\n');
304
- } catch (error) {
305
- document.getElementById('keyGeneration').className = 'result error';
306
- document.getElementById('keyGeneration').textContent = 'Mnemonic Error: ' + error.message;
307
- }
308
- }
309
-
310
- function testKeyGeneration() {
311
- try {
312
- const results = [];
313
-
314
- // Test 1: Generate random HD private key
315
- if (bsv.HDPrivateKey && bsv.HDPrivateKey.fromRandom) {
316
- const hdPrivateKey = bsv.HDPrivateKey.fromRandom();
317
- results.push('✅ HDPrivateKey generation: SUCCESS');
318
- results.push(` Master key: ${hdPrivateKey.toString().substring(0, 50)}...`);
319
-
320
- // Test key derivation
321
- const derivedKey = hdPrivateKey.deriveChild("m/44'/236'/0'/0/0");
322
- results.push('✅ Key derivation: SUCCESS');
323
- results.push(` Derived key: ${derivedKey.toString().substring(0, 50)}...`);
324
-
325
- // Generate address
326
- const publicKey = derivedKey.privateKey.toPublicKey();
327
- const address = bsv.Address.fromPublicKey(publicKey);
328
- results.push('✅ Address generation: SUCCESS');
329
- results.push(` Address: ${address.toString()}`);
330
-
331
- // Create key pairs display
332
- createKeyPairDisplay(hdPrivateKey);
333
-
334
- } else {
335
- results.push('❌ HDPrivateKey not available or fromRandom method missing');
336
- }
337
-
338
- document.getElementById('keyGeneration').className = 'result success';
339
- document.getElementById('keyGeneration').textContent = results.join('\n');
340
-
341
- } catch (error) {
342
- document.getElementById('keyGeneration').className = 'result error';
343
- document.getElementById('keyGeneration').textContent = 'Key Generation Error: ' + error.message;
344
- }
345
- }
346
-
347
- function createKeyPairDisplay(masterKey) {
348
- const purposes = [
349
- { name: 'IDENTITY', path: "m/44'/236'/0'/0/0" },
350
- { name: 'FINANCIAL', path: "m/44'/0'/0'/0/0" },
351
- { name: 'ATTESTATION', path: "m/44'/236'/4'/0/0" },
352
- { name: 'ORGANIZATION', path: "m/44'/236'/6'/0/0" }
353
- ];
354
-
355
- let html = '<h3>Generated Key Pairs:</h3>';
356
-
357
- purposes.forEach(purpose => {
358
- try {
359
- const derivedKey = masterKey.deriveChild(purpose.path);
360
- const publicKey = derivedKey.privateKey.toPublicKey();
361
- const address = bsv.Address.fromPublicKey(publicKey);
362
-
363
- html += `
364
- <div class="key-pair">
365
- <h4>${purpose.name} Key</h4>
366
- <div class="key-item"><strong>Path:</strong> ${purpose.path}</div>
367
- <div class="key-item"><strong>Address:</strong> ${address.toString()}</div>
368
- <div class="key-item"><strong>PubKey:</strong> ${publicKey.toString().substring(0, 40)}...</div>
369
- </div>
370
- `;
371
- } catch (e) {
372
- html += `<div class="key-pair"><h4>${purpose.name} Key</h4><div class="error">Error: ${e.message}</div></div>`;
373
- }
374
- });
375
-
376
- document.getElementById('generatedKeys').innerHTML = html;
377
- }
378
-
379
- function testSignatures() {
380
- try {
381
- // Ensure Buffer is available
382
- if (!Buffer) {
383
- Buffer = bsv.deps.Buffer;
384
- }
385
-
386
- const results = [];
387
-
388
- // Generate test key
389
- const privateKey = bsv.PrivateKey.fromRandom();
390
- const publicKey = privateKey.toPublicKey();
391
-
392
- // Test data
393
- const testData = 'Web3Keys browser signature test';
394
- const dataBuffer = Buffer.from(testData, 'utf8');
395
- const hash = bsv.crypto.Hash.sha256(dataBuffer);
396
-
397
- // Sign data
398
- const signature = bsv.crypto.ECDSA.sign(hash, privateKey);
399
- results.push('✅ Signature creation: SUCCESS');
400
- results.push(` Signature: ${signature.toString().substring(0, 50)}...`);
401
-
402
- // Verify signature
403
- const isValid = bsv.crypto.ECDSA.verify(hash, signature, publicKey);
404
- results.push(`✅ Signature verification: ${isValid ? 'VALID' : 'INVALID'}`);
405
-
406
- // Test SmartVerify if available
407
- if (bsv.SmartVerify && bsv.SmartVerify.smartVerify) {
408
- const smartValid = bsv.SmartVerify.smartVerify(hash, signature, publicKey);
409
- results.push(`✅ SmartVerify enhanced: ${smartValid ? 'VALID' : 'INVALID'}`);
410
-
411
- // Test canonical signature
412
- const isCanonical = bsv.SmartVerify.isCanonical(signature);
413
- results.push(`✅ Signature canonical: ${isCanonical ? 'YES' : 'NO'}`);
414
- }
415
-
416
- document.getElementById('signatures').className = 'result success';
417
- document.getElementById('signatures').textContent = results.join('\n');
418
-
419
- } catch (error) {
420
- document.getElementById('signatures').className = 'result error';
421
- document.getElementById('signatures').textContent = 'Signature Error: ' + error.message;
422
- }
423
- }
424
-
425
- function testDIDGeneration() {
426
- try {
427
- const results = [];
428
-
429
- // Generate multiple DIDs
430
- for (let i = 0; i < 3; i++) {
431
- const privateKey = bsv.PrivateKey.fromRandom();
432
- const publicKey = privateKey.toPublicKey();
433
-
434
- // Generate DID using public key hash
435
- const pubKeyHash = bsv.crypto.Hash.sha256(publicKey.toBuffer()).toString('hex').substring(0, 16);
436
- const did = `did:web:web3keys.org:${pubKeyHash}`;
437
-
438
- const address = bsv.Address.fromPublicKey(publicKey);
439
-
440
- results.push(`✅ DID ${i + 1}: ${did}`);
441
- results.push(` Address: ${address.toString()}`);
442
- results.push(` PubKey: ${publicKey.toString().substring(0, 40)}...`);
443
- results.push('');
444
- }
445
-
446
- document.getElementById('didGeneration').className = 'result success';
447
- document.getElementById('didGeneration').textContent = results.join('\n');
448
-
449
- } catch (error) {
450
- document.getElementById('didGeneration').className = 'result error';
451
- document.getElementById('didGeneration').textContent = 'DID Generation Error: ' + error.message;
452
- }
453
- }
454
-
455
- function testAddressGeneration() {
456
- try {
457
- const results = [];
458
-
459
- // Test different address types
460
- const privateKey = bsv.PrivateKey.fromRandom();
461
- const publicKey = privateKey.toPublicKey();
462
-
463
- // Standard address
464
- const address = bsv.Address.fromPublicKey(publicKey);
465
- results.push('✅ Standard Address Generation: SUCCESS');
466
- results.push(` Address: ${address.toString()}`);
467
- results.push(` Type: ${address.type || 'pubkeyhash'}`);
468
-
469
- // Validate address
470
- const isValid = bsv.Address.isValid(address.toString());
471
- results.push(`✅ Address validation: ${isValid ? 'VALID' : 'INVALID'}`);
472
-
473
- // Test multiple addresses for Paymail simulation
474
- results.push('\n📧 Paymail Address Simulation:');
475
- for (let i = 0; i < 3; i++) {
476
- const paymailKey = bsv.PrivateKey.fromRandom();
477
- const paymailPubKey = paymailKey.toPublicKey();
478
- const paymailAddress = bsv.Address.fromPublicKey(paymailPubKey);
479
-
480
- results.push(` user${i + 1}@web3keys.org → ${paymailAddress.toString()}`);
481
- }
482
-
483
- document.getElementById('addressGeneration').className = 'result success';
484
- document.getElementById('addressGeneration').textContent = results.join('\n');
485
-
486
- } catch (error) {
487
- document.getElementById('addressGeneration').className = 'result error';
488
- document.getElementById('addressGeneration').textContent = 'Address Generation Error: ' + error.message;
489
- }
490
- }
491
-
492
- function testSmartFeatures() {
493
- try {
494
- // Ensure Buffer is available
495
- if (!Buffer) {
496
- Buffer = bsv.deps.Buffer;
497
- }
498
-
499
- const results = [];
500
-
501
- // Test SmartLedger info if available
502
- if (bsv.SmartLedger) {
503
- results.push('🔐 SmartLedger Information:');
504
- results.push(` Version: ${bsv.SmartLedger.version || 'Unknown'}`);
505
- results.push(` Base Version: ${bsv.SmartLedger.baseVersion || 'Unknown'}`);
506
- results.push(` Hardened By: ${bsv.SmartLedger.hardenedBy || 'Unknown'}`);
507
- if (bsv.SmartLedger.securityFeatures) {
508
- results.push(` Security Features: ${bsv.SmartLedger.securityFeatures.join(', ')}`);
509
- }
510
- results.push('');
511
- }
512
-
513
- // Test SmartVerify features
514
- if (bsv.SmartVerify) {
515
- results.push('🛡️ SmartVerify Features:');
516
- results.push(` smartVerify function: ${typeof bsv.SmartVerify.smartVerify}`);
517
- results.push(` isCanonical function: ${typeof bsv.SmartVerify.isCanonical}`);
518
- results.push(` canonicalize function: ${typeof bsv.SmartVerify.canonicalize}`);
519
-
520
- // Test canonical signature checking
521
- const testKey = bsv.PrivateKey.fromRandom();
522
- const testPubKey = testKey.toPublicKey();
523
- const testHash = bsv.crypto.Hash.sha256(Buffer.from('test', 'utf8'));
524
- const testSig = bsv.crypto.ECDSA.sign(testHash, testKey);
525
-
526
- const isCanonical = bsv.SmartVerify.isCanonical(testSig);
527
- results.push(` Test signature canonical: ${isCanonical ? 'YES' : 'NO'}`);
528
- results.push('');
529
- }
530
-
531
- // Test other Smart modules
532
- const smartModules = [
533
- { name: 'SmartContract', browserCompatible: true },
534
- { name: 'SmartUTXO', browserCompatible: false },
535
- { name: 'SmartMiner', browserCompatible: false }
536
- ];
537
- smartModules.forEach(module => {
538
- if (bsv[module.name]) {
539
- results.push(`✅ ${module.name}: Available (${typeof bsv[module.name]})`);
540
- } else if (!module.browserCompatible) {
541
- results.push(`ℹ️ ${module.name}: Node.js-only (expected)`);
542
- } else {
543
- results.push(`❌ ${module.name}: Not available`);
544
- }
545
- });
546
-
547
- results.push('');
548
- results.push('📝 Note: SmartUTXO and SmartMiner are Node.js-only development tools');
549
- results.push(' They require file system access and are not included in browser bundles');
550
- results.push(' Use manual UTXO management and external APIs for browser applications');
551
-
552
- document.getElementById('smartFeatures').className = 'result success';
553
- document.getElementById('smartFeatures').textContent = results.join('\n');
554
-
555
- } catch (error) {
556
- document.getElementById('smartFeatures').className = 'result error';
557
- document.getElementById('smartFeatures').textContent = 'Smart Features Error: ' + error.message;
558
- }
559
- }
560
-
561
- function testMnemonicGeneration() {
562
- try {
563
- if (!Buffer) {
564
- Buffer = bsv.deps.Buffer;
565
- }
566
-
567
- const results = [];
568
-
569
- if (!bsv.Mnemonic) {
570
- results.push('❌ Mnemonic class not available in browser');
571
- document.getElementById('mnemonicTesting').className = 'result error';
572
- document.getElementById('mnemonicTesting').textContent = results.join('\n');
573
- return;
574
- }
575
-
576
- results.push('🎲 Comprehensive Mnemonic Testing\n');
577
-
578
- // Test 1: Different entropy levels
579
- results.push('1️⃣ Testing Different Entropy Levels:');
580
- const entropies = [
581
- { bits: 128, expectedWords: 12 },
582
- { bits: 160, expectedWords: 15 },
583
- { bits: 192, expectedWords: 18 },
584
- { bits: 224, expectedWords: 21 },
585
- { bits: 256, expectedWords: 24 }
586
- ];
587
-
588
- entropies.forEach(entropy => {
589
- try {
590
- const mnemonic = bsv.Mnemonic.fromRandom(entropy.bits);
591
- const words = mnemonic.toString().split(' ');
592
- const isCorrectLength = words.length === entropy.expectedWords;
593
- results.push(` ${isCorrectLength ? '✅' : '❌'} ${entropy.bits}-bit: ${words.length}/${entropy.expectedWords} words`);
594
-
595
- if (entropy.bits === 256) {
596
- results.push(` Example: ${words.slice(0, 6).join(' ')}...`);
597
- }
598
- } catch (e) {
599
- results.push(` ❌ ${entropy.bits}-bit: Error - ${e.message}`);
600
- }
601
- });
602
-
603
- // Test 2: Mnemonic validation
604
- results.push('\n2️⃣ Testing Mnemonic Validation:');
605
- const validMnemonic = bsv.Mnemonic.fromRandom(256);
606
- const validString = validMnemonic.toString();
607
- results.push(` ✅ Valid mnemonic: ${bsv.Mnemonic.isValid(validString) ? 'PASS' : 'FAIL'}`);
608
-
609
- const invalidMnemonic = 'invalid word list test fake mnemonic';
610
- results.push(` ✅ Invalid mnemonic: ${!bsv.Mnemonic.isValid(invalidMnemonic) ? 'PASS' : 'FAIL'}`);
611
-
612
- // Test 3: Seed generation with/without passphrase
613
- results.push('\n3️⃣ Testing Seed Generation:');
614
- const testMnemonic = bsv.Mnemonic.fromRandom(256);
615
- const seedDefault = testMnemonic.toSeed();
616
- const seedWithPass = testMnemonic.toSeed('test-passphrase');
617
- const seedWithDiffPass = testMnemonic.toSeed('different-passphrase');
618
-
619
- results.push(` ✅ Default seed: ${seedDefault.toString('hex').substring(0, 32)}...`);
620
- results.push(` ✅ With passphrase: ${seedWithPass.toString('hex').substring(0, 32)}...`);
621
- results.push(` ✅ Seeds different: ${!seedDefault.equals(seedWithPass) ? 'YES' : 'NO'}`);
622
- results.push(` ✅ Different passphrases create different seeds: ${!seedWithPass.equals(seedWithDiffPass) ? 'YES' : 'NO'}`);
623
-
624
- // Test 4: HD key derivation from mnemonic
625
- results.push('\n4️⃣ Testing HD Key Derivation:');
626
- const hdKey = bsv.HDPrivateKey.fromSeed(seedDefault);
627
- const hdKeyWithPass = bsv.HDPrivateKey.fromSeed(seedWithPass);
628
-
629
- results.push(` ✅ HD key from seed: ${hdKey.toString().substring(0, 40)}...`);
630
- results.push(` ✅ HD key with passphrase: ${hdKeyWithPass.toString().substring(0, 40)}...`);
631
- results.push(` ✅ HD keys different: ${hdKey.toString() !== hdKeyWithPass.toString() ? 'YES' : 'NO'}`);
632
-
633
- // Test 5: Web3Keys purpose derivation
634
- results.push('\n5️⃣ Testing Web3Keys Purpose Derivation:');
635
- const purposes = [
636
- { name: 'Identity', path: "m/44'/236'/0'/0/0" },
637
- { name: 'Financial', path: "m/44'/0'/0'/0/0" },
638
- { name: 'Attestation', path: "m/44'/236'/4'/0/0" }
639
- ];
640
-
641
- purposes.forEach(purpose => {
642
- try {
643
- const derivedKey = hdKey.deriveChild(purpose.path);
644
- const address = bsv.Address.fromPublicKey(derivedKey.privateKey.toPublicKey());
645
- results.push(` ✅ ${purpose.name}: ${address.toString()}`);
646
- } catch (e) {
647
- results.push(` ❌ ${purpose.name}: ${e.message}`);
648
- }
649
- });
650
-
651
- results.push('\n🎯 Mnemonic Testing Complete!');
652
- document.getElementById('mnemonicTesting').className = 'result success';
653
- document.getElementById('mnemonicTesting').textContent = results.join('\n');
654
-
655
- } catch (error) {
656
- document.getElementById('mnemonicTesting').className = 'result error';
657
- document.getElementById('mnemonicTesting').textContent = 'Mnemonic Testing Error: ' + error.message;
658
- }
659
- }
660
-
661
- function testCustomPassphrase() {
662
- try {
663
- if (!Buffer) {
664
- Buffer = bsv.deps.Buffer;
665
- }
666
-
667
- const results = [];
668
- const customPassphrase = document.getElementById('customPassphrase').value;
669
-
670
- if (!bsv.Mnemonic) {
671
- results.push('❌ Mnemonic class not available');
672
- document.getElementById('mnemonicTesting').className = 'result error';
673
- document.getElementById('mnemonicTesting').textContent = results.join('\n');
674
- return;
675
- }
676
-
677
- results.push('🔐 Custom Passphrase Testing\n');
678
-
679
- // Generate test mnemonic
680
- const mnemonic = bsv.Mnemonic.fromRandom(256);
681
- results.push(`Test Mnemonic: ${mnemonic.toString()}\n`);
682
-
683
- // Test different passphrase scenarios
684
- const passphrases = [
685
- { name: 'No passphrase', value: '' },
686
- { name: 'Empty string', value: '' },
687
- { name: 'Custom passphrase', value: customPassphrase || 'Web3Keys-default-test' },
688
- { name: 'Unicode passphrase', value: '🔐🌍Web3Keys测试密码🚀' },
689
- { name: 'Long passphrase', value: 'This is a very long passphrase for testing purposes with many words and characters 123456789' }
690
- ];
691
-
692
- const seeds = [];
693
- passphrases.forEach((pp, index) => {
694
- try {
695
- const seed = mnemonic.toSeed(pp.value);
696
- const hdKey = bsv.HDPrivateKey.fromSeed(seed);
697
- const identityKey = hdKey.deriveChild("m/44'/236'/0'/0/0");
698
- const address = bsv.Address.fromPublicKey(identityKey.privateKey.toPublicKey());
699
-
700
- seeds.push(seed);
701
- results.push(`${index + 1}️⃣ ${pp.name}:`);
702
- results.push(` Seed: ${seed.toString('hex').substring(0, 32)}...`);
703
- results.push(` Identity Address: ${address.toString()}`);
704
- results.push('');
705
- } catch (e) {
706
- results.push(`${index + 1}️⃣ ${pp.name}: Error - ${e.message}\n`);
707
- }
708
- });
709
-
710
- // Verify all seeds are different (except identical passphrases)
711
- results.push('🔍 Seed Uniqueness Check:');
712
- for (let i = 0; i < seeds.length; i++) {
713
- for (let j = i + 1; j < seeds.length; j++) {
714
- const isDifferent = !seeds[i].equals(seeds[j]);
715
- const shouldBeDifferent = passphrases[i].value !== passphrases[j].value;
716
- const status = isDifferent === shouldBeDifferent ? '✅' : '❌';
717
- results.push(` ${status} ${passphrases[i].name} vs ${passphrases[j].name}: ${isDifferent ? 'Different' : 'Same'}`);
718
- }
719
- }
720
-
721
- results.push('\n🎯 Custom Passphrase Testing Complete!');
722
- document.getElementById('mnemonicTesting').className = 'result success';
723
- document.getElementById('mnemonicTesting').textContent = results.join('\n');
724
-
725
- } catch (error) {
726
- document.getElementById('mnemonicTesting').className = 'result error';
727
- document.getElementById('mnemonicTesting').textContent = 'Custom Passphrase Error: ' + error.message;
728
- }
729
- }
730
-
731
- function clearMnemonicInput() {
732
- document.getElementById('importMnemonic').value = '';
733
- document.getElementById('mnemonicTesting').innerHTML = '';
734
- }
735
-
736
- function testImportedMnemonic() {
737
- try {
738
- if (!Buffer) {
739
- Buffer = bsv.deps.Buffer;
740
- }
741
-
742
- const results = [];
743
- const importedMnemonicText = document.getElementById('importMnemonic').value.trim();
744
-
745
- if (!importedMnemonicText) {
746
- results.push('❌ Please enter a mnemonic to import');
747
- document.getElementById('mnemonicTesting').className = 'result error';
748
- document.getElementById('mnemonicTesting').textContent = results.join('\n');
749
- return;
750
- }
751
-
752
- if (!bsv.Mnemonic) {
753
- results.push('❌ Mnemonic class not available in browser');
754
- document.getElementById('mnemonicTesting').className = 'result error';
755
- document.getElementById('mnemonicTesting').textContent = results.join('\n');
756
- return;
757
- }
758
-
759
- results.push('📥 Imported Mnemonic Testing\n');
760
-
761
- // Test 1: Validate imported mnemonic
762
- results.push('1️⃣ Validating Imported Mnemonic:');
763
- const words = importedMnemonicText.split(/\s+/);
764
- const wordCount = words.length;
765
- results.push(` Word count: ${wordCount}`);
766
-
767
- const isValidFormat = [12, 15, 18, 21, 24].includes(wordCount);
768
- results.push(` ✅ Valid word count: ${isValidFormat ? 'YES' : 'NO'}`);
769
-
770
- if (!isValidFormat) {
771
- results.push(' ❌ Mnemonic must be 12, 15, 18, 21, or 24 words');
772
- document.getElementById('mnemonicTesting').className = 'result error';
773
- document.getElementById('mnemonicTesting').textContent = results.join('\n');
774
- return;
775
- }
776
-
777
- // Test 2: Create mnemonic object and validate
778
- let mnemonic;
779
- try {
780
- mnemonic = bsv.Mnemonic.fromString(importedMnemonicText);
781
- results.push(` ✅ Mnemonic object created successfully`);
782
-
783
- const isValid = bsv.Mnemonic.isValid(importedMnemonicText);
784
- results.push(` ✅ Mnemonic validation: ${isValid ? 'VALID' : 'INVALID'}`);
785
-
786
- if (!isValid) {
787
- results.push(' ❌ Invalid mnemonic - check for typos or invalid words');
788
- document.getElementById('mnemonicTesting').className = 'result error';
789
- document.getElementById('mnemonicTesting').textContent = results.join('\n');
790
- return;
791
- }
792
- } catch (error) {
793
- results.push(` ❌ Error creating mnemonic: ${error.message}`);
794
- document.getElementById('mnemonicTesting').className = 'result error';
795
- document.getElementById('mnemonicTesting').textContent = results.join('\n');
796
- return;
797
- }
798
-
799
- // Test 3: Generate seeds with different passphrases
800
- results.push('\n2️⃣ Testing Seed Generation:');
801
- const customPassphrase = document.getElementById('customPassphrase').value;
802
-
803
- const passphrases = [
804
- { name: 'No passphrase', value: '' },
805
- { name: 'Custom passphrase', value: customPassphrase || 'Web3Keys-test' },
806
- { name: 'Test passphrase', value: 'imported-mnemonic-test-2025' }
807
- ];
808
-
809
- const seeds = [];
810
- passphrases.forEach((pp, index) => {
811
- try {
812
- const seed = mnemonic.toSeed(pp.value);
813
- seeds.push(seed);
814
- results.push(` ${index + 1}. ${pp.name}:`);
815
- results.push(` Seed: ${seed.toString('hex').substring(0, 32)}...`);
816
- } catch (e) {
817
- results.push(` ${index + 1}. ${pp.name}: Error - ${e.message}`);
818
- }
819
- });
820
-
821
- // Test 4: Generate HD keys and addresses
822
- results.push('\n3️⃣ Testing Key Derivation:');
823
- try {
824
- const seedDefault = mnemonic.toSeed();
825
- const hdKey = bsv.HDPrivateKey.fromSeed(seedDefault);
826
-
827
- results.push(` Master Key: ${hdKey.toString().substring(0, 50)}...`);
828
-
829
- // Generate Web3Keys purpose keys
830
- const purposes = [
831
- { name: 'Identity', path: "m/44'/236'/0'/0/0", color: '🆔' },
832
- { name: 'Financial', path: "m/44'/0'/0'/0/0", color: '💰' },
833
- { name: 'Attestation', path: "m/44'/236'/4'/0/0", color: '📋' },
834
- { name: 'Organization', path: "m/44'/236'/6'/0/0", color: '🏢' }
835
- ];
836
-
837
- purposes.forEach(purpose => {
838
- try {
839
- const derivedKey = hdKey.deriveChild(purpose.path);
840
- const address = bsv.Address.fromPublicKey(derivedKey.privateKey.toPublicKey());
841
- const pubKey = derivedKey.privateKey.toPublicKey().toString();
842
-
843
- results.push(` ${purpose.color} ${purpose.name}:`);
844
- results.push(` Path: ${purpose.path}`);
845
- results.push(` Address: ${address.toString()}`);
846
- results.push(` PubKey: ${pubKey.substring(0, 40)}...`);
847
- results.push('');
848
- } catch (e) {
849
- results.push(` ❌ ${purpose.name}: ${e.message}`);
850
- }
851
- });
852
- } catch (error) {
853
- results.push(` ❌ Key derivation error: ${error.message}`);
854
- }
855
-
856
- // Test 5: Generate DID from imported mnemonic
857
- results.push('4️⃣ Testing DID Generation:');
858
- try {
859
- const seedDefault = mnemonic.toSeed();
860
- const hdKey = bsv.HDPrivateKey.fromSeed(seedDefault);
861
- const identityKey = hdKey.deriveChild("m/44'/236'/0'/0/0");
862
- const identityPublicKey = identityKey.privateKey.toPublicKey();
863
- const pubKeyHash = bsv.crypto.Hash.sha256(identityPublicKey.toBuffer()).toString('hex').substring(0, 16);
864
- const did = `did:web:web3keys.org:${pubKeyHash}`;
865
-
866
- results.push(` ✅ Generated DID: ${did}`);
867
- results.push(` ✅ Identity Address: ${bsv.Address.fromPublicKey(identityPublicKey).toString()}`);
868
- } catch (error) {
869
- results.push(` ❌ DID generation error: ${error.message}`);
870
- }
871
-
872
- // Test 6: Test signature with imported mnemonic
873
- results.push('\n5️⃣ Testing Digital Signatures:');
874
- try {
875
- const seedDefault = mnemonic.toSeed();
876
- const hdKey = bsv.HDPrivateKey.fromSeed(seedDefault);
877
- const signingKey = hdKey.deriveChild("m/44'/236'/0'/0/0");
878
- const privateKey = signingKey.privateKey;
879
- const publicKey = privateKey.toPublicKey();
880
-
881
- // Sign test data
882
- const testData = `Web3Keys imported mnemonic test - ${Date.now()}`;
883
- const dataBuffer = Buffer.from(testData, 'utf8');
884
- const hash = bsv.crypto.Hash.sha256(dataBuffer);
885
- const signature = bsv.crypto.ECDSA.sign(hash, privateKey);
886
-
887
- results.push(` ✅ Test data: "${testData}"`);
888
- results.push(` ✅ Signature: ${signature.toString().substring(0, 50)}...`);
889
-
890
- // Verify signature
891
- const isValid = bsv.crypto.ECDSA.verify(hash, signature, publicKey);
892
- results.push(` ✅ Signature verification: ${isValid ? 'VALID' : 'INVALID'}`);
893
-
894
- // Test SmartVerify if available
895
- if (bsv.SmartVerify && bsv.SmartVerify.smartVerify) {
896
- const smartValid = bsv.SmartVerify.smartVerify(hash, signature, publicKey);
897
- const isCanonical = bsv.SmartVerify.isCanonical(signature);
898
- results.push(` ✅ SmartVerify: ${smartValid ? 'VALID' : 'INVALID'}`);
899
- results.push(` ✅ Canonical: ${isCanonical ? 'YES' : 'NO'}`);
900
- }
901
- } catch (error) {
902
- results.push(` ❌ Signature test error: ${error.message}`);
903
- }
904
-
905
- // Summary
906
- results.push('\n🎯 Imported Mnemonic Testing Complete!');
907
- results.push(`✅ Words: ${wordCount} (${wordCount * 32 / 3} bits entropy)`);
908
- results.push('✅ Validation: PASSED');
909
- results.push('✅ Key derivation: SUCCESS');
910
- results.push('✅ Address generation: SUCCESS');
911
- results.push('✅ DID generation: SUCCESS');
912
- results.push('✅ Digital signatures: SUCCESS');
913
-
914
- document.getElementById('mnemonicTesting').className = 'result success';
915
- document.getElementById('mnemonicTesting').textContent = results.join('\n');
916
-
917
- } catch (error) {
918
- document.getElementById('mnemonicTesting').className = 'result error';
919
- document.getElementById('mnemonicTesting').textContent = 'Imported Mnemonic Error: ' + error.message + '\n\nStack: ' + error.stack;
920
- }
921
- }
922
-
923
- function testBrowserUTXOManager() {
924
- try {
925
- const results = [];
926
- results.push('💰 Browser UTXO Manager Testing\n');
927
-
928
- if (!bsv.BrowserUTXOManager) {
929
- results.push('❌ BrowserUTXOManager not available');
930
- document.getElementById('utxoManager').className = 'result error';
931
- document.getElementById('utxoManager').textContent = results.join('\n');
932
- return;
933
- }
934
-
935
- // Test 1: Create manager with memory storage
936
- results.push('1️⃣ Testing Memory Storage:');
937
- const memoryManager = new bsv.BrowserUTXOManager({
938
- storage: 'memory',
939
- maxUTXOs: 100
940
- });
941
-
942
- results.push(` ✅ Manager created with ${memoryManager.options.storage} storage`);
943
- results.push(` ✅ Max UTXOs: ${memoryManager.options.maxUTXOs}`);
944
-
945
- // Test 2: Create mock UTXOs
946
- results.push('\n2️⃣ Creating Mock UTXOs:');
947
- const testAddress = '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'; // Genesis block address
948
- const mockUTXOs = memoryManager.createMockUTXOs(testAddress, 5, 50000);
949
-
950
- results.push(` ✅ Created ${mockUTXOs.length} mock UTXOs`);
951
- results.push(` ✅ Total value: ${mockUTXOs.reduce((sum, utxo) => sum + utxo.satoshis, 0)} satoshis`);
952
-
953
- // Test 3: Query UTXOs
954
- results.push('\n3️⃣ Querying UTXOs:');
955
- const utxosForAddress = memoryManager.getUTXOsForAddress(testAddress);
956
- const balance = memoryManager.getBalance(testAddress);
957
-
958
- results.push(` ✅ UTXOs for address: ${utxosForAddress.length}`);
959
- results.push(` ✅ Total balance: ${balance} satoshis (${balance / 100000000} BSV)`);
960
-
961
- // Test 4: Spend some UTXOs
962
- results.push('\n4️⃣ Testing UTXO Spending:');
963
- const utxosToSpend = utxosForAddress.slice(0, 2);
964
- const spentInputs = utxosToSpend.map(utxo => ({ txid: utxo.txid, vout: utxo.vout }));
965
- const spentUTXOs = memoryManager.spendUTXOs(spentInputs, 'test-transaction-123');
966
-
967
- results.push(` ✅ Spent ${spentUTXOs.length} UTXOs`);
968
- results.push(` ✅ New balance: ${memoryManager.getBalance(testAddress)} satoshis`);
969
-
970
- // Test 5: Check UTXO availability
971
- results.push('\n5️⃣ Testing UTXO Availability:');
972
- const firstUTXO = utxosForAddress[0];
973
- const availability = memoryManager.getUTXO(firstUTXO.txid, firstUTXO.vout);
974
- results.push(` ✅ First UTXO status: ${availability.status}`);
975
-
976
- const availableCount = memoryManager.getUTXOsForAddress(testAddress).length;
977
- results.push(` ✅ Remaining available UTXOs: ${availableCount}`);
978
-
979
- // Test 6: Statistics
980
- results.push('\n6️⃣ Manager Statistics:');
981
- const stats = memoryManager.getStats();
982
- results.push(` ✅ Total UTXOs: ${stats.totalUTXOs}`);
983
- results.push(` ✅ Total spent: ${stats.totalSpent}`);
984
- results.push(` ✅ Total value: ${stats.totalValue} satoshis`);
985
- results.push(` ✅ Storage type: ${stats.storageType}`);
986
- results.push(` ✅ Addresses tracked: ${stats.totalAddresses}`);
987
-
988
- results.push('\n🎯 Browser UTXO Manager Test Complete!');
989
- document.getElementById('utxoManager').className = 'result success';
990
- document.getElementById('utxoManager').textContent = results.join('\n');
991
-
992
- } catch (error) {
993
- document.getElementById('utxoManager').className = 'result error';
994
- document.getElementById('utxoManager').textContent = 'Browser UTXO Manager Error: ' + error.message + '\n\nStack: ' + error.stack;
995
- }
996
- }
997
-
998
- function testDifferentStorageTypes() {
999
- try {
1000
- const results = [];
1001
- const selectedStorage = document.getElementById('storageTypeSelect').value;
1002
- results.push(`🔧 Testing ${selectedStorage.toUpperCase()} Storage Type\n`);
1003
-
1004
- if (!bsv.BrowserUTXOManager) {
1005
- results.push('❌ BrowserUTXOManager not available');
1006
- document.getElementById('utxoManager').className = 'result error';
1007
- document.getElementById('utxoManager').textContent = results.join('\n');
1008
- return;
1009
- }
1010
-
1011
- // Test storage type
1012
- results.push('1️⃣ Creating Manager:');
1013
- const manager = new bsv.BrowserUTXOManager({
1014
- storage: selectedStorage,
1015
- storageKey: `test-utxos-${Date.now()}`,
1016
- autoSave: true
1017
- });
1018
-
1019
- results.push(` ✅ Created with ${selectedStorage} storage`);
1020
- results.push(` ✅ Storage key: ${manager.options.storageKey}`);
1021
-
1022
- // Test persistence
1023
- results.push('\n2️⃣ Testing Persistence:');
1024
- const testAddress = '1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2';
1025
-
1026
- // Create UTXOs and save
1027
- const mockUTXOs = manager.createMockUTXOs(testAddress, 3, 75000);
1028
- results.push(` ✅ Created ${mockUTXOs.length} UTXOs`);
1029
-
1030
- // Export data
1031
- const exportedData = manager.exportData();
1032
- results.push(` ✅ Exported data size: ${exportedData.length} characters`);
1033
-
1034
- // Test import/export
1035
- results.push('\n3️⃣ Testing Import/Export:');
1036
- const newManager = new bsv.BrowserUTXOManager({
1037
- storage: 'memory' // Start with empty memory
1038
- });
1039
-
1040
- const importSuccess = newManager.importData(exportedData);
1041
- results.push(` ✅ Import success: ${importSuccess}`);
1042
- results.push(` ✅ Imported UTXOs: ${newManager.getStats().totalUTXOs}`);
1043
- results.push(` ✅ Imported balance: ${newManager.getBalance(testAddress)} satoshis`);
1044
-
1045
- // Test storage availability
1046
- results.push('\n4️⃣ Storage Compatibility:');
1047
- const storageTests = {
1048
- 'localStorage': typeof localStorage !== 'undefined',
1049
- 'sessionStorage': typeof sessionStorage !== 'undefined',
1050
- 'WebCrypto': typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues
1051
- };
1052
-
1053
- Object.entries(storageTests).forEach(([feature, available]) => {
1054
- results.push(` ${available ? '✅' : '❌'} ${feature}: ${available ? 'Available' : 'Not available'}`);
1055
- });
1056
-
1057
- // Storage-specific notes
1058
- results.push('\n📝 Storage Type Information:');
1059
- switch (selectedStorage) {
1060
- case 'memory':
1061
- results.push(' • Memory: Fast, lost on page reload');
1062
- results.push(' • Best for: Temporary UTXO tracking, testing');
1063
- break;
1064
- case 'session':
1065
- results.push(' • Session: Persists until tab closes');
1066
- results.push(' • Best for: Single-session applications');
1067
- break;
1068
- case 'local':
1069
- results.push(' • Local: Persists until manually cleared');
1070
- results.push(' • Best for: Long-term wallet state');
1071
- break;
1072
- }
1073
-
1074
- results.push(`\n🎯 ${selectedStorage.toUpperCase()} Storage Test Complete!`);
1075
- document.getElementById('utxoManager').className = 'result success';
1076
- document.getElementById('utxoManager').textContent = results.join('\n');
1077
-
1078
- } catch (error) {
1079
- document.getElementById('utxoManager').className = 'result error';
1080
- document.getElementById('utxoManager').textContent = 'Storage Test Error: ' + error.message + '\n\nStack: ' + error.stack;
1081
- }
1082
- }
1083
-
1084
- function runFullSimulation() {
1085
- try {
1086
- // Ensure Buffer is available
1087
- if (!Buffer) {
1088
- Buffer = bsv.deps.Buffer;
1089
- }
1090
-
1091
- const results = [];
1092
- results.push('🚀 Running Complete Web3Keys Browser Simulation...\n');
1093
-
1094
- // Step 1: Create identity
1095
- results.push('1️⃣ Creating Web3Keys Identity:');
1096
- const masterKey = bsv.HDPrivateKey.fromRandom();
1097
- const identityKey = masterKey.deriveChild("m/44'/236'/0'/0/0");
1098
- const financialKey = masterKey.deriveChild("m/44'/0'/0'/0/0");
1099
-
1100
- const identityPrivateKey = identityKey.privateKey;
1101
- const identityPublicKey = identityPrivateKey.toPublicKey();
1102
- const identityAddress = bsv.Address.fromPublicKey(identityPublicKey);
1103
-
1104
- const financialPrivateKey = financialKey.privateKey;
1105
- const financialPublicKey = financialPrivateKey.toPublicKey();
1106
- const financialAddress = bsv.Address.fromPublicKey(financialPublicKey);
1107
-
1108
- results.push(` ✅ Identity Address: ${identityAddress.toString()}`);
1109
- results.push(` ✅ Financial Address: ${financialAddress.toString()}`);
1110
-
1111
- // Step 2: Generate DID
1112
- results.push('\n2️⃣ Generating DID:');
1113
- const pubKeyHash = bsv.crypto.Hash.sha256(identityPublicKey.toBuffer()).toString('hex').substring(0, 16);
1114
- const did = `did:web:web3keys.org:${pubKeyHash}`;
1115
- results.push(` ✅ DID: ${did}`);
1116
-
1117
- // Step 3: Create attestation
1118
- results.push('\n3️⃣ Creating Identity Attestation:');
1119
- const attestationData = {
1120
- did: did,
1121
- timestamp: Date.now(),
1122
- purpose: 'Web3Keys identity verification',
1123
- address: identityAddress.toString()
1124
- };
1125
-
1126
- const dataString = JSON.stringify(attestationData);
1127
- const dataHash = bsv.crypto.Hash.sha256(Buffer.from(dataString, 'utf8'));
1128
- const signature = bsv.crypto.ECDSA.sign(dataHash, identityPrivateKey);
1129
-
1130
- results.push(` ✅ Attestation created and signed`);
1131
- results.push(` ✅ Data hash: ${dataHash.toString('hex').substring(0, 32)}...`);
1132
- results.push(` ✅ Signature: ${signature.toString().substring(0, 40)}...`);
1133
-
1134
- // Step 4: Verify attestation
1135
- results.push('\n4️⃣ Verifying Attestation:');
1136
- const isValid = bsv.crypto.ECDSA.verify(dataHash, signature, identityPublicKey);
1137
- results.push(` ✅ Basic verification: ${isValid ? 'VALID' : 'INVALID'}`);
1138
-
1139
- if (bsv.SmartVerify && bsv.SmartVerify.smartVerify) {
1140
- const smartValid = bsv.SmartVerify.smartVerify(dataHash, signature, identityPublicKey);
1141
- results.push(` ✅ SmartVerify: ${smartValid ? 'VALID' : 'INVALID'}`);
1142
-
1143
- const isCanonical = bsv.SmartVerify.isCanonical(signature);
1144
- results.push(` ✅ Canonical: ${isCanonical ? 'YES' : 'NO'}`);
1145
- }
1146
-
1147
- // Step 5: Simulate Paymail
1148
- results.push('\n5️⃣ Simulating Paymail Resolution:');
1149
- const paymailAlias = 'testuser@web3keys.org';
1150
- results.push(` ✅ Paymail: ${paymailAlias}`);
1151
- results.push(` ✅ Resolves to: ${financialAddress.toString()}`);
1152
- results.push(` ✅ Public Key: ${financialPublicKey.toString().substring(0, 40)}...`);
1153
-
1154
- // Step 6: Test Mnemonic if available
1155
- results.push('\n6️⃣ Testing Mnemonic Generation:');
1156
- if (bsv.Mnemonic) {
1157
- // Generate 24-word mnemonic (256-bit entropy)
1158
- const testMnemonic = bsv.Mnemonic.fromRandom(256);
1159
- const mnemonicWords = testMnemonic.toString();
1160
- const wordCount = mnemonicWords.split(' ').length;
1161
-
1162
- results.push(` ✅ 24-word Mnemonic (${wordCount} words): ${mnemonicWords}`);
1163
-
1164
- // Test with passphrase
1165
- const passphrase = 'Web3Keys-test-passphrase';
1166
- const seedWithPassphrase = testMnemonic.toSeed(passphrase);
1167
- const seedWithoutPassphrase = testMnemonic.toSeed();
1168
-
1169
- results.push(` ✅ Seed with passphrase: ${seedWithPassphrase.toString('hex').substring(0, 32)}...`);
1170
- results.push(` ✅ Seed without passphrase: ${seedWithoutPassphrase.toString('hex').substring(0, 32)}...`);
1171
- results.push(` ✅ Seeds are different: ${!seedWithPassphrase.equals(seedWithoutPassphrase) ? 'YES' : 'NO'}`);
1172
-
1173
- // Create HD keys from both seeds
1174
- const hdKeyWithPassphrase = bsv.HDPrivateKey.fromSeed(seedWithPassphrase);
1175
- const hdKeyWithoutPassphrase = bsv.HDPrivateKey.fromSeed(seedWithoutPassphrase);
1176
-
1177
- results.push(` ✅ HD Key (with passphrase): ${hdKeyWithPassphrase.toString().substring(0, 40)}...`);
1178
- results.push(` ✅ HD Key (no passphrase): ${hdKeyWithoutPassphrase.toString().substring(0, 40)}...`);
1179
-
1180
- // Test mnemonic validation
1181
- const isValidMnemonic = bsv.Mnemonic.isValid(mnemonicWords);
1182
- results.push(` ✅ Mnemonic validation: ${isValidMnemonic ? 'VALID' : 'INVALID'}`);
1183
- } else {
1184
- results.push(` ⚠️ Mnemonic not available in browser`);
1185
- }
1186
-
1187
- // Step 7: Summary
1188
- results.push('\n🎉 Web3Keys Browser Simulation Complete!');
1189
- results.push('✅ Identity key generation');
1190
- results.push('✅ DID creation');
1191
- results.push('✅ Digital attestation');
1192
- results.push('✅ Signature verification');
1193
- results.push('✅ Paymail simulation');
1194
- results.push('✅ SmartLedger integration');
1195
- results.push('✅ Buffer compatibility resolved');
1196
-
1197
- document.getElementById('fullSimulation').className = 'result success';
1198
- document.getElementById('fullSimulation').textContent = results.join('\n');
1199
-
1200
- } catch (error) {
1201
- document.getElementById('fullSimulation').className = 'result error';
1202
- document.getElementById('fullSimulation').textContent = 'Full Simulation Error: ' + error.message + '\n\nStack: ' + error.stack;
1203
- }
1204
- }
1205
-
1206
- </script>
1207
- </body>
1208
- </html>