smartledger-bsv 3.3.3 → 3.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -28
- package/README.md +55 -36
- package/bsv-covenant.min.js +6 -6
- package/bsv-gdaf.min.js +6 -6
- package/bsv-ltp.min.js +6 -6
- package/bsv-mnemonic.min.js +4 -4
- package/bsv-smartcontract.min.js +5 -5
- package/bsv.bundle.js +5 -5
- package/bsv.min.js +5 -5
- package/demos/README.md +188 -0
- package/demos/architecture_demo.js +247 -0
- package/demos/browser-test.html +1208 -0
- package/demos/bsv_wallet_demo.js +242 -0
- package/demos/complete_ltp_demo.js +511 -0
- package/demos/debug_tools_demo.js +87 -0
- package/demos/demo_features.js +123 -0
- package/demos/easy_interface_demo.js +109 -0
- package/demos/ecies_demo.js +182 -0
- package/demos/gdaf_core_test.js +131 -0
- package/demos/gdaf_demo.js +237 -0
- package/demos/ltp_demo.js +361 -0
- package/demos/ltp_primitives_demo.js +403 -0
- package/demos/message_demo.js +209 -0
- package/demos/preimage_separation_demo.js +383 -0
- package/demos/script_helper_demo.js +289 -0
- package/demos/security_demo.js +287 -0
- package/demos/shamir_demo.js +121 -0
- package/demos/simple_demo.js +204 -0
- package/demos/simple_p2pkh_demo.js +169 -0
- package/demos/simple_utxo_preimage_demo.js +196 -0
- package/demos/smart_contract_demo.html +1347 -0
- package/demos/smart_contract_demo.js +910 -0
- package/demos/utxo_generator_demo.js +244 -0
- package/demos/validation_pipeline_demo.js +155 -0
- package/demos/web3keys.html +740 -0
- package/docs/BUNDLE_UPDATE_SUMMARY.md +40 -0
- package/docs/DOCUMENTATION_REVIEW_REPORT.md +11 -11
- package/docs/FIX_CREATEHMAC_ISSUE.md +91 -0
- package/docs/MODULE_REFERENCE_COMPLETE.md +28 -28
- package/docs/SMARTLEDGER_BSV_USAGE_ANSWERS.md +477 -0
- package/docs/SMARTLEDGER_BSV_USAGE_EXAMPLES.js +372 -0
- package/docs/SMARTLEDGER_BSV_USAGE_GUIDE.md +555 -0
- package/docs/SMART_CONTRACT_DEVELOPMENT_GUIDE.md +1459 -0
- package/docs/advanced/UTXO_MANAGER_GUIDE.md +2 -2
- package/docs/getting-started/INSTALLATION.md +25 -25
- package/docs/getting-started/QUICK_START.md +7 -7
- package/docs/migration/FROM_BSV_1_5_6.md +5 -5
- package/examples/complete_workflow_demo.js +783 -0
- package/examples/definitive_working_demo.js +261 -0
- package/examples/final_working_contracts.js +338 -0
- package/examples/smart_contract_templates.js +718 -0
- package/examples/working_smart_contracts.js +348 -0
- package/index.js +7 -0
- package/lib/browser-utxo-manager-es5.js +316 -0
- package/lib/browser-utxo-manager.js +533 -0
- package/lib/mnemonic/pbkdf2.browser.js +69 -0
- package/lib/mnemonic/pbkdf2.js +2 -68
- package/lib/mnemonic/pbkdf2.node.js +68 -0
- package/package.json +19 -8
- package/tests/browser-compatibility/README.md +35 -0
- package/tests/browser-compatibility/test-cdn-vs-local.html +186 -0
- package/tests/browser-compatibility/test-pbkdf2.html +51 -0
|
@@ -0,0 +1,1208 @@
|
|
|
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.4/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>
|