smartledger-bsv 3.4.0 → 3.4.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.
Files changed (119) hide show
  1. package/CHANGELOG.md +446 -0
  2. package/README.md +112 -84
  3. package/SECURITY.md +88 -0
  4. package/bin/cli.js +13 -8
  5. package/bsv-anchor.min.js +12 -0
  6. package/bsv-covenant.min.js +8 -8
  7. package/bsv-didweb.min.js +12 -0
  8. package/bsv-gdaf.min.js +9 -9
  9. package/bsv-ltp.min.js +9 -9
  10. package/bsv-mnemonic.min.js +2 -2
  11. package/bsv-shamir.min.js +3 -3
  12. package/bsv-smartcontract.min.js +5 -5
  13. package/bsv-statuslist.min.js +18 -0
  14. package/bsv-vcjwt.min.js +12 -0
  15. package/bsv.bundle.js +9 -9
  16. package/bsv.d.ts +486 -9
  17. package/bsv.min.js +5 -5
  18. package/build/webpack.anchor.config.js +9 -13
  19. package/build/webpack.didweb.config.js +10 -14
  20. package/build/webpack.statuslist.config.js +9 -14
  21. package/build/webpack.vcjwt.config.js +9 -13
  22. package/docs/COVENANT_DEVELOPMENT_RESOLVED.md +2 -2
  23. package/docs/MODULE_REFERENCE_COMPLETE.md +61 -58
  24. package/docs/advanced/LEGAL_TOKEN_PROTOCOL.md +3 -3
  25. package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
  26. package/docs/getting-started/INSTALLATION.md +30 -30
  27. package/docs/getting-started/QUICK_START.md +18 -18
  28. package/docs/migration/FROM_BSV_1_5_6.md +16 -10
  29. package/gdaf-entry.js +1 -2
  30. package/index.js +44 -13
  31. package/lib/browser-utxo-manager-es5.js +11 -4
  32. package/lib/browser-utxo-manager.js +15 -8
  33. package/lib/ltp/claim.js +1 -0
  34. package/lib/ltp/obligation.js +1 -0
  35. package/lib/ltp/registry.js +2 -0
  36. package/lib/ltp/right.js +1 -0
  37. package/lib/script/script.js +19 -0
  38. package/lib/smart_contract/covenant.js +10 -1
  39. package/lib/smartutxo.js +20 -12
  40. package/lib/transaction/input/publickeyhash.js +6 -1
  41. package/lib/transaction/transaction.js +13 -2
  42. package/lib/util/_.js +7 -1
  43. package/ltp-entry.js +1 -2
  44. package/package.json +11 -13
  45. package/utilities/blockchain-state.js +32 -23
  46. package/demos/README.md +0 -188
  47. package/demos/architecture_demo.js +0 -247
  48. package/demos/browser-test.html +0 -1208
  49. package/demos/bsv_wallet_demo.js +0 -242
  50. package/demos/complete_ltp_demo.js +0 -511
  51. package/demos/debug_tools_demo.js +0 -87
  52. package/demos/demo_features.js +0 -123
  53. package/demos/easy_interface_demo.js +0 -109
  54. package/demos/ecies_demo.js +0 -182
  55. package/demos/gdaf_core_test.js +0 -131
  56. package/demos/gdaf_demo.js +0 -237
  57. package/demos/ltp_demo.js +0 -361
  58. package/demos/ltp_primitives_demo.js +0 -403
  59. package/demos/message_demo.js +0 -209
  60. package/demos/preimage_separation_demo.js +0 -383
  61. package/demos/script_helper_demo.js +0 -289
  62. package/demos/security_demo.js +0 -287
  63. package/demos/shamir_demo.js +0 -121
  64. package/demos/simple_demo.js +0 -204
  65. package/demos/simple_p2pkh_demo.js +0 -169
  66. package/demos/simple_utxo_preimage_demo.js +0 -196
  67. package/demos/smart_contract_demo.html +0 -1347
  68. package/demos/smart_contract_demo.js +0 -910
  69. package/demos/utxo_generator_demo.js +0 -244
  70. package/demos/validation_pipeline_demo.js +0 -155
  71. package/demos/web3keys.html +0 -740
  72. package/examples/README.md +0 -200
  73. package/examples/basic/transaction-creation.js +0 -534
  74. package/examples/basic/transaction_signature_api_gap.js +0 -178
  75. package/examples/complete_workflow_demo.js +0 -783
  76. package/examples/covenants/advanced_covenant_demo.js +0 -219
  77. package/examples/covenants/covenant_interface_demo.js +0 -270
  78. package/examples/covenants/covenant_manual_signature_resolved.js +0 -212
  79. package/examples/covenants/covenant_signature_template.js +0 -117
  80. package/examples/covenants2/covenant_bidirectional_example.js +0 -262
  81. package/examples/covenants2/covenant_utils_demo.js +0 -120
  82. package/examples/covenants2/preimage_covenant_utils.js +0 -287
  83. package/examples/covenants2/production_integration.js +0 -256
  84. package/examples/data/covenant_utxos.json +0 -28
  85. package/examples/data/utxos.json +0 -26
  86. package/examples/definitive_working_demo.js +0 -261
  87. package/examples/final_working_contracts.js +0 -338
  88. package/examples/preimage/README.md +0 -178
  89. package/examples/preimage/extract_preimage_bidirectional.js +0 -421
  90. package/examples/preimage/generate_sample_preimage.js +0 -208
  91. package/examples/preimage/generate_sighash_examples.js +0 -152
  92. package/examples/preimage/parse_preimage.js +0 -117
  93. package/examples/preimage/test_preimage_extractor.js +0 -53
  94. package/examples/preimage/test_varint_extraction.js +0 -95
  95. package/examples/scripts/custom_script_helper_example.js +0 -273
  96. package/examples/scripts/custom_script_signature_test.js +0 -344
  97. package/examples/scripts/script_interpreter.js +0 -193
  98. package/examples/smart_contract/complete_workflow_demo.js +0 -343
  99. package/examples/smart_contract/covenant_builder_demo.js +0 -176
  100. package/examples/smart_contract/script_testing_integration.js +0 -198
  101. package/examples/smart_contract_templates.js +0 -718
  102. package/examples/working_smart_contracts.js +0 -348
  103. package/lib/smart_contract/test_integration.js +0 -269
  104. package/tests/browser-compatibility/README.md +0 -35
  105. package/tests/browser-compatibility/test-cdn-vs-local.html +0 -186
  106. package/tests/browser-compatibility/test-pbkdf2.html +0 -51
  107. package/tests/bundle-completeness-test.html +0 -131
  108. package/tests/bundle-demo.html +0 -476
  109. package/tests/smartcontract-test.html +0 -239
  110. package/tests/standalone-modules-test.html +0 -260
  111. package/tests/test.html +0 -612
  112. package/tests/test_builtin_verify.js +0 -117
  113. package/tests/test_debug_integration.js +0 -71
  114. package/tests/test_ecdsa_little.js +0 -70
  115. package/tests/test_shamir.js +0 -221
  116. package/tests/test_smartverify_der.js +0 -110
  117. package/tests/test_standalone_shamir.html +0 -83
  118. package/tests/unpkg-demo.html +0 -194
  119. package/utilities/blockchain-state.json +0 -118565
@@ -1,1347 +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>BSV Smart Contract Library Demo</title>
7
- <style>
8
- body {
9
- font-family: 'Monaco', 'Courier New', monospace;
10
- background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
11
- color: #fff;
12
- margin: 0;
13
- padding: 20px;
14
- line-height: 1.6;
15
- }
16
-
17
- .container {
18
- max-width: 1200px;
19
- margin: 0 auto;
20
- background: rgba(0, 0, 0, 0.2);
21
- border-radius: 15px;
22
- padding: 30px;
23
- backdrop-filter: blur(10px);
24
- box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
25
- }
26
-
27
- h1 {
28
- text-align: center;
29
- font-size: 2.5em;
30
- margin-bottom: 30px;
31
- text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
32
- background: linear-gradient(45deg, #ffd700, #ffed4e);
33
- -webkit-background-clip: text;
34
- -webkit-text-fill-color: transparent;
35
- background-clip: text;
36
- }
37
-
38
- .demo-section {
39
- background: rgba(255, 255, 255, 0.1);
40
- border-radius: 10px;
41
- padding: 20px;
42
- margin: 20px 0;
43
- border-left: 4px solid #ffd700;
44
- }
45
-
46
- .demo-section h2 {
47
- color: #ffd700;
48
- margin-top: 0;
49
- font-size: 1.5em;
50
- }
51
-
52
- .button-group {
53
- display: flex;
54
- gap: 10px;
55
- flex-wrap: wrap;
56
- margin: 15px 0;
57
- }
58
-
59
- button {
60
- background: linear-gradient(45deg, #007bff, #0056b3);
61
- color: white;
62
- border: none;
63
- padding: 12px 20px;
64
- border-radius: 8px;
65
- cursor: pointer;
66
- font-family: inherit;
67
- font-weight: bold;
68
- transition: all 0.3s ease;
69
- box-shadow: 0 4px 15px rgba(0, 123, 255, 0.3);
70
- }
71
-
72
- button:hover {
73
- transform: translateY(-2px);
74
- box-shadow: 0 6px 20px rgba(0, 123, 255, 0.4);
75
- }
76
-
77
- button:active {
78
- transform: translateY(0);
79
- }
80
-
81
- button.success {
82
- background: linear-gradient(45deg, #28a745, #1e7e34);
83
- }
84
-
85
- button.warning {
86
- background: linear-gradient(45deg, #ffc107, #e0a800);
87
- }
88
-
89
- button.danger {
90
- background: linear-gradient(45deg, #dc3545, #c82333);
91
- }
92
-
93
- .output {
94
- background: rgba(0, 0, 0, 0.4);
95
- border-radius: 8px;
96
- padding: 15px;
97
- margin: 15px 0;
98
- border: 1px solid rgba(255, 255, 255, 0.2);
99
- font-size: 0.9em;
100
- line-height: 1.4;
101
- max-height: 300px;
102
- overflow-y: auto;
103
- }
104
-
105
- .output pre {
106
- margin: 0;
107
- white-space: pre-wrap;
108
- word-wrap: break-word;
109
- }
110
-
111
- .status {
112
- padding: 10px;
113
- border-radius: 5px;
114
- margin: 10px 0;
115
- font-weight: bold;
116
- }
117
-
118
- .status.success {
119
- background: rgba(40, 167, 69, 0.2);
120
- border: 1px solid #28a745;
121
- color: #d4edda;
122
- }
123
-
124
- .status.error {
125
- background: rgba(220, 53, 69, 0.2);
126
- border: 1px solid #dc3545;
127
- color: #f8d7da;
128
- }
129
-
130
- .status.info {
131
- background: rgba(23, 162, 184, 0.2);
132
- border: 1px solid #17a2b8;
133
- color: #d1ecf1;
134
- }
135
-
136
- .feature-grid {
137
- display: grid;
138
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
139
- gap: 20px;
140
- margin: 20px 0;
141
- }
142
-
143
- .feature-card {
144
- background: rgba(255, 255, 255, 0.05);
145
- padding: 20px;
146
- border-radius: 10px;
147
- border: 1px solid rgba(255, 255, 255, 0.1);
148
- }
149
-
150
- .feature-card h3 {
151
- color: #ffd700;
152
- margin-top: 0;
153
- }
154
-
155
- .code-block {
156
- background: rgba(0, 0, 0, 0.6);
157
- border-radius: 5px;
158
- padding: 15px;
159
- margin: 10px 0;
160
- border-left: 3px solid #ffd700;
161
- font-family: 'Monaco', 'Courier New', monospace;
162
- font-size: 0.85em;
163
- overflow-x: auto;
164
- }
165
-
166
- .loading {
167
- display: inline-block;
168
- width: 20px;
169
- height: 20px;
170
- border: 3px solid rgba(255, 255, 255, 0.3);
171
- border-radius: 50%;
172
- border-top-color: #ffd700;
173
- animation: spin 1s ease-in-out infinite;
174
- }
175
-
176
- @keyframes spin {
177
- to { transform: rotate(360deg); }
178
- }
179
-
180
- .tab-container {
181
- margin: 20px 0;
182
- }
183
-
184
- .tab-buttons {
185
- display: flex;
186
- border-bottom: 2px solid rgba(255, 255, 255, 0.1);
187
- margin-bottom: 20px;
188
- }
189
-
190
- .tab-button {
191
- background: transparent;
192
- border: none;
193
- padding: 10px 20px;
194
- color: rgba(255, 255, 255, 0.7);
195
- cursor: pointer;
196
- border-bottom: 2px solid transparent;
197
- transition: all 0.3s ease;
198
- }
199
-
200
- .tab-button.active {
201
- color: #ffd700;
202
- border-bottom-color: #ffd700;
203
- }
204
-
205
- .tab-content {
206
- display: none;
207
- }
208
-
209
- .tab-content.active {
210
- display: block;
211
- }
212
-
213
- .input-group {
214
- margin: 15px 0;
215
- }
216
-
217
- .input-group label {
218
- display: block;
219
- margin-bottom: 5px;
220
- color: #ffd700;
221
- font-weight: bold;
222
- }
223
-
224
- .input-group input, .input-group textarea, .input-group select {
225
- width: 100%;
226
- padding: 10px;
227
- border: 1px solid rgba(255, 255, 255, 0.3);
228
- border-radius: 5px;
229
- background: rgba(0, 0, 0, 0.3);
230
- color: #fff;
231
- font-family: inherit;
232
- box-sizing: border-box;
233
- }
234
-
235
- .input-group input:focus, .input-group textarea:focus, .input-group select:focus {
236
- outline: none;
237
- border-color: #ffd700;
238
- box-shadow: 0 0 10px rgba(255, 215, 0, 0.3);
239
- }
240
- </style>
241
- </head>
242
- <body>
243
- <div class="container">
244
- <h1>🚀 BSV Smart Contract Library Demo</h1>
245
-
246
- <div class="demo-section">
247
- <h2>🌟 SmartLedger BSV Smart Contract Framework</h2>
248
- <p>This interactive demo showcases the powerful smart contract capabilities of the SmartLedger BSV library.
249
- Explore covenant creation, preimage parsing, script building, and UTXO management with real Bitcoin SV functionality.</p>
250
-
251
- <div class="feature-grid">
252
- <div class="feature-card">
253
- <h3>🔒 Covenant Builder</h3>
254
- <p>Create complex Bitcoin Script covenants with JavaScript syntax</p>
255
- </div>
256
- <div class="feature-card">
257
- <h3>🧾 Preimage Parser</h3>
258
- <p>Extract and validate BIP-143 transaction preimage fields</p>
259
- </div>
260
- <div class="feature-card">
261
- <h3>🛠️ Script Tools</h3>
262
- <p>Build, test, and debug Bitcoin Scripts locally</p>
263
- </div>
264
- <div class="feature-card">
265
- <h3>💎 UTXO Generator</h3>
266
- <p>Generate authentic test UTXOs for development</p>
267
- </div>
268
- </div>
269
- </div>
270
-
271
- <div class="tab-container">
272
- <div class="tab-buttons">
273
- <button class="tab-button active" onclick="switchTab('basics')">📚 Basics</button>
274
- <button class="tab-button" onclick="switchTab('covenant')">🔒 Covenant Builder</button>
275
- <button class="tab-button" onclick="switchTab('preimage')">🧾 Preimage Parser</button>
276
- <button class="tab-button" onclick="switchTab('utxo')">💎 UTXO Generator</button>
277
- <button class="tab-button" onclick="switchTab('scripts')">🛠️ Script Tools</button>
278
- </div>
279
-
280
- <!-- Basics Tab -->
281
- <div id="basics" class="tab-content active">
282
- <div class="demo-section">
283
- <h2>📚 Smart Contract Basics</h2>
284
- <div class="button-group">
285
- <button onclick="loadLibrary()">📦 Load BSV Smart Contract Library</button>
286
- <button onclick="showFeatures()" class="success">🌟 Show Available Features</button>
287
- <button onclick="runBasicTests()" class="warning">🧪 Run Basic Tests</button>
288
- </div>
289
- <div id="basics-output" class="output"></div>
290
- </div>
291
- </div>
292
-
293
- <!-- Covenant Builder Tab -->
294
- <div id="covenant" class="tab-content">
295
- <div class="demo-section">
296
- <h2>🔒 Covenant Builder Demo</h2>
297
- <p>Create Bitcoin Script covenants using JavaScript syntax. Covenants enforce spending conditions on future transactions.</p>
298
-
299
- <div class="input-group">
300
- <label>Covenant Type:</label>
301
- <select id="covenant-type">
302
- <option value="simple">Simple Amount Lock</option>
303
- <option value="timelock">Time Lock Covenant</option>
304
- <option value="multisig">Multi-Signature Covenant</option>
305
- <option value="conditional">Conditional Spending</option>
306
- </select>
307
- </div>
308
-
309
- <div class="input-group">
310
- <label>Amount (satoshis):</label>
311
- <input type="number" id="covenant-amount" value="100000" min="546">
312
- </div>
313
-
314
- <div class="input-group">
315
- <label>Recipient Address:</label>
316
- <input type="text" id="covenant-address" placeholder="1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa">
317
- </div>
318
-
319
- <div class="button-group">
320
- <button onclick="generateCovenant()">🏗️ Generate Covenant</button>
321
- <button onclick="testCovenant()" class="success">✅ Test Covenant</button>
322
- <button onclick="showCovenantScript()" class="warning">📜 Show Script ASM</button>
323
- </div>
324
- <div id="covenant-output" class="output"></div>
325
- </div>
326
- </div>
327
-
328
- <!-- Preimage Parser Tab -->
329
- <div id="preimage" class="tab-content">
330
- <div class="demo-section">
331
- <h2>🧾 BIP-143 Preimage Parser</h2>
332
- <p>Parse and extract fields from Bitcoin transaction preimages for covenant validation.</p>
333
-
334
- <div class="input-group">
335
- <label>Transaction Hex (or use sample):</label>
336
- <textarea id="tx-hex" rows="4" placeholder="Paste transaction hex here or click 'Generate Sample'"></textarea>
337
- </div>
338
-
339
- <div class="button-group">
340
- <button onclick="generateSampleTx()">🎲 Generate Sample Transaction</button>
341
- <button onclick="parsePreimage()" class="success">🔍 Parse Preimage</button>
342
- <button onclick="extractSighash()" class="warning">📊 Extract SIGHASH</button>
343
- <button onclick="validatePreimage()" class="danger">✅ Validate Fields</button>
344
- </div>
345
- <div id="preimage-output" class="output"></div>
346
- </div>
347
- </div>
348
-
349
- <!-- UTXO Generator Tab -->
350
- <div id="utxo" class="tab-content">
351
- <div class="demo-section">
352
- <h2>💎 Mock UTXO Generator</h2>
353
- <p>Generate authentic test UTXOs for smart contract development and testing.</p>
354
-
355
- <div class="input-group">
356
- <label>Private Key (WIF) - leave blank for random:</label>
357
- <input type="text" id="utxo-wif" placeholder="L1234... (leave blank for random generation)">
358
- </div>
359
-
360
- <div class="input-group">
361
- <label>UTXO Value (satoshis):</label>
362
- <input type="number" id="utxo-amount" value="100000" min="546">
363
- </div>
364
-
365
- <div class="input-group">
366
- <label>Network:</label>
367
- <select id="utxo-network">
368
- <option value="livenet">Mainnet</option>
369
- <option value="testnet">Testnet</option>
370
- <option value="regtest">Regtest</option>
371
- </select>
372
- </div>
373
-
374
- <div class="button-group">
375
- <button onclick="generateUTXO()">💎 Generate UTXO</button>
376
- <button onclick="createSpendingTx()" class="success">💸 Create Spending TX</button>
377
- <button onclick="showUTXODetails()" class="warning">📋 Show UTXO Details</button>
378
- </div>
379
- <div id="utxo-output" class="output"></div>
380
- </div>
381
- </div>
382
-
383
- <!-- Script Tools Tab -->
384
- <div id="scripts" class="tab-content">
385
- <div class="demo-section">
386
- <h2>🛠️ Script Development Tools</h2>
387
- <p>Build, test, and debug Bitcoin Scripts with comprehensive tooling.</p>
388
-
389
- <div class="input-group">
390
- <label>Script ASM:</label>
391
- <textarea id="script-asm" rows="3" placeholder="OP_DUP OP_HASH160 OP_PUSHDATA1 0x14 0x... OP_EQUALVERIFY OP_CHECKSIG">OP_DUP OP_HASH160 OP_PUSHDATA1 0x14 0x1234567890123456789012345678901234567890 OP_EQUALVERIFY OP_CHECKSIG</textarea>
392
- </div>
393
-
394
- <div class="input-group">
395
- <label>Script Type:</label>
396
- <select id="script-type">
397
- <option value="p2pkh">Pay-to-Public-Key-Hash</option>
398
- <option value="p2sh">Pay-to-Script-Hash</option>
399
- <option value="covenant">Covenant Script</option>
400
- <option value="custom">Custom Script</option>
401
- </select>
402
- </div>
403
-
404
- <div class="button-group">
405
- <button onclick="buildScript()">🏗️ Build Script</button>
406
- <button onclick="analyzeScript()" class="success">🔍 Analyze Script</button>
407
- <button onclick="debugScript()" class="warning">🐛 Debug Execution</button>
408
- <button onclick="optimizeScript()" class="danger">⚡ Optimize Script</button>
409
- </div>
410
- <div id="scripts-output" class="output"></div>
411
- </div>
412
- </div>
413
- </div>
414
-
415
- <div class="demo-section">
416
- <h2>🎯 Real-World Use Cases</h2>
417
- <div class="feature-grid">
418
- <div class="feature-card">
419
- <h3>🏦 Escrow Contracts</h3>
420
- <p>Multi-party escrow with timeout conditions</p>
421
- <button onclick="showEscrowExample()">View Example</button>
422
- </div>
423
- <div class="feature-card">
424
- <h3>⏰ Time-locked Payments</h3>
425
- <p>Payments that unlock after specific time</p>
426
- <button onclick="showTimelockExample()">View Example</button>
427
- </div>
428
- <div class="feature-card">
429
- <h3>🔄 Recurring Payments</h3>
430
- <p>Automated recurring payment covenants</p>
431
- <button onclick="showRecurringExample()">View Example</button>
432
- </div>
433
- <div class="feature-card">
434
- <h3>🎲 Gaming Contracts</h3>
435
- <p>Provably fair gaming and betting</p>
436
- <button onclick="showGamingExample()">View Example</button>
437
- </div>
438
- </div>
439
- </div>
440
-
441
- <div class="demo-section">
442
- <h2>📖 Quick Start Guide</h2>
443
- <div class="code-block">
444
- <pre>// BSV bundle is already loaded - access directly
445
- // Core BSV functionality
446
- const privateKey = new bsv.PrivateKey();
447
- const address = privateKey.toAddress();
448
-
449
- // Create a basic transaction
450
- const tx = new bsv.Transaction()
451
- .from(utxo) // Add input UTXO
452
- .to('recipient-address', 50000) // Add output
453
- .change(address) // Change back to sender
454
- .sign(privateKey); // Sign transaction
455
-
456
- // Build custom scripts
457
- const script = new bsv.Script()
458
- .add(bsv.Opcode.OP_DUP)
459
- .add(bsv.Opcode.OP_HASH160)
460
- .add(address.hashBuffer)
461
- .add(bsv.Opcode.OP_EQUALVERIFY)
462
- .add(bsv.Opcode.OP_CHECKSIG);
463
-
464
- // SmartLedger-BSV Covenant Example
465
- if (bsv.SmartContract) {
466
- // Create preimage-based covenant
467
- const covenant = new bsv.SmartContract.Covenant(privateKey);
468
-
469
- // Generate preimage for transaction validation
470
- const preimage = bsv.Transaction.sighash.sighash(
471
- tx, sighashType, inputIndex, lockingScript, satoshis
472
- );
473
-
474
- // OP_PUSH_TX method (not an opcode, but a signing technique)
475
- const covenantInterface = new bsv.CovenantInterface();
476
- const pushtxCovenant = covenantInterface.createPushtxCovenant({
477
- publicKey: privateKey.publicKey.toString(),
478
- enforceOutputs: true
479
- });
480
- }</pre>
481
- </div>
482
- </div>
483
-
484
- <div class="demo-section">
485
- <h2>🔗 Additional Resources</h2>
486
- <div class="button-group">
487
- <button onclick="window.open('https://github.com/codenlighten/smartledger-bsv', '_blank')" class="success">
488
- 📚 Documentation
489
- </button>
490
- <button onclick="window.open('https://github.com/codenlighten/smartledger-bsv/tree/main/examples', '_blank')" class="warning">
491
- 💡 More Examples
492
- </button>
493
- <button onclick="window.open('https://npmjs.com/package/@smartledger/bsv', '_blank')" class="danger">
494
- 📦 NPM Package
495
- </button>
496
- </div>
497
- </div>
498
- </div>
499
-
500
- <!-- Load complete BSV bundle (includes all modules) -->
501
- <script src="../bsv.bundle.js"></script>
502
-
503
- <script>
504
- // Global variables
505
- let SmartContract = null;
506
- let currentUTXO = null;
507
- let currentCovenant = null;
508
-
509
- // Tab switching functionality
510
- function switchTab(tabName) {
511
- // Hide all tab contents
512
- const tabContents = document.querySelectorAll('.tab-content');
513
- tabContents.forEach(tab => tab.classList.remove('active'));
514
-
515
- // Remove active class from all buttons
516
- const tabButtons = document.querySelectorAll('.tab-button');
517
- tabButtons.forEach(button => button.classList.remove('active'));
518
-
519
- // Show selected tab and mark button as active
520
- document.getElementById(tabName).classList.add('active');
521
- event.target.classList.add('active');
522
- }
523
-
524
- // Utility functions
525
- function log(elementId, message, type = 'info') {
526
- const output = document.getElementById(elementId);
527
- const timestamp = new Date().toLocaleTimeString();
528
- const className = type === 'error' ? 'status error' :
529
- type === 'success' ? 'status success' : 'status info';
530
-
531
- const logEntry = `<div class="${className}">[${timestamp}] ${message}</div>`;
532
- output.innerHTML += logEntry;
533
- output.scrollTop = output.scrollHeight;
534
- }
535
-
536
- function clearOutput(elementId) {
537
- document.getElementById(elementId).innerHTML = '';
538
- }
539
-
540
- // Load library function
541
- function loadLibrary() {
542
- clearOutput('basics-output');
543
- log('basics-output', '📦 Loading BSV Smart Contract Library...', 'info');
544
-
545
- try {
546
- // Check if BSV bundle is available
547
- if (typeof bsv === 'undefined') {
548
- throw new Error('BSV bundle not loaded. Please ensure bsv.bundle.js is included.');
549
- }
550
-
551
- log('basics-output', '✅ BSV library loaded successfully!', 'success');
552
- log('basics-output', `📊 BSV version: ${bsv.version || 'Bundle v3.3.4'}`, 'info');
553
-
554
- // Check available SmartLedger modules
555
- const availableModules = [];
556
- if (bsv.SmartContract) availableModules.push('SmartContract');
557
- if (bsv.LTP) availableModules.push('LTP');
558
- if (bsv.Security) availableModules.push('Security');
559
- if (bsv.GDAF) availableModules.push('GDAF');
560
- if (bsv.Shamir) availableModules.push('Shamir');
561
-
562
- log('basics-output', `🔧 Available modules: ${availableModules.join(', ')}`, 'info');
563
- log('basics-output', `🎯 Core BSV classes: Transaction, Script, PrivateKey, Address`, 'info');
564
-
565
- // Initialize SmartContract reference
566
- if (bsv.SmartContract) {
567
- SmartContract = bsv.SmartContract;
568
- log('basics-output', '🚀 SmartContract module ready!', 'success');
569
- } else {
570
- log('basics-output', '⚠️ SmartContract module not found in bundle', 'error');
571
- SmartContract = null;
572
- }
573
-
574
- log('basics-output', '� Ready for smart contract development!', 'success');
575
-
576
- } catch (error) {
577
- log('basics-output', `❌ Error loading library: ${error.message}`, 'error');
578
- }
579
- }
580
-
581
- function showFeatures() {
582
- clearOutput('basics-output');
583
- log('basics-output', '🌟 BSV Smart Contract Features:', 'info');
584
-
585
- const features = [
586
- '🔒 Covenant Builder - Create complex spending conditions',
587
- '🧾 Preimage Parser - Extract BIP-143 transaction fields',
588
- '🛠️ Script Tools - Build and debug Bitcoin Scripts',
589
- '💎 UTXO Generator - Create test UTXOs for development',
590
- '📊 SIGHASH Analysis - Understand signature hash types',
591
- '🏗️ ASM Generator - Convert JavaScript to Bitcoin Script',
592
- '🔍 Script Debugger - Step-through script execution',
593
- '⚡ Script Optimizer - Minimize script size and cost',
594
- '🧪 Local Testing - Verify scripts without blockchain',
595
- '📦 Production Ready - Deploy to BSV mainnet'
596
- ];
597
-
598
- features.forEach(feature => {
599
- log('basics-output', feature, 'success');
600
- });
601
-
602
- log('basics-output', '🚀 All features available in @smartledger/bsv package!', 'info');
603
- }
604
-
605
- function runBasicTests() {
606
- clearOutput('basics-output');
607
- log('basics-output', '🧪 Running Basic Smart Contract Tests...', 'info');
608
-
609
- try {
610
- // Test 1: Private Key Generation
611
- log('basics-output', '📝 Test 1: Private Key Generation', 'info');
612
- const privateKey = new bsv.PrivateKey();
613
- const address = privateKey.toAddress();
614
- log('basics-output', `✅ Generated address: ${address.toString()}`, 'success');
615
-
616
- // Test 2: Transaction Creation
617
- log('basics-output', '📝 Test 2: Transaction Creation', 'info');
618
- const tx = new bsv.Transaction();
619
- log('basics-output', `✅ Created transaction: ${tx.id || 'empty'}`, 'success');
620
-
621
- // Test 3: Script Building
622
- log('basics-output', '📝 Test 3: Script Building', 'info');
623
- const script = bsv.Script.buildPublicKeyHashOut(address);
624
- log('basics-output', `✅ Built P2PKH script: ${script.toString().substring(0, 50)}...`, 'success');
625
-
626
- // Test 4: Mock UTXO
627
- log('basics-output', '📝 Test 4: Mock UTXO Creation', 'info');
628
- const utxo = {
629
- txId: 'mock_' + Date.now(),
630
- outputIndex: 0,
631
- address: address.toString(),
632
- script: script.toString(),
633
- satoshis: 100000
634
- };
635
- log('basics-output', `✅ Created mock UTXO: ${utxo.satoshis} satoshis`, 'success');
636
-
637
- log('basics-output', '🎉 All basic tests passed! Smart contract functionality ready.', 'success');
638
-
639
- } catch (error) {
640
- log('basics-output', `❌ Test failed: ${error.message}`, 'error');
641
- }
642
- }
643
-
644
- // Covenant Builder Functions
645
- function generateCovenant() {
646
- clearOutput('covenant-output');
647
- log('covenant-output', '🏗️ Generating Covenant...', 'info');
648
-
649
- try {
650
- const type = document.getElementById('covenant-type').value;
651
- const amount = parseInt(document.getElementById('covenant-amount').value);
652
- const address = document.getElementById('covenant-address').value;
653
-
654
- // Generate keys for covenant
655
- const covenantKey = new bsv.PrivateKey();
656
- const covenantAddress = covenantKey.toAddress();
657
-
658
- log('covenant-output', `📋 Covenant Type: ${type}`, 'info');
659
- log('covenant-output', `💰 Amount: ${amount} satoshis`, 'info');
660
- log('covenant-output', `🏠 Covenant Address: ${covenantAddress.toString()}`, 'info');
661
-
662
- // Build covenant script based on type
663
- let script;
664
- switch (type) {
665
- case 'simple':
666
- script = buildSimpleCovenant(amount, address);
667
- break;
668
- case 'timelock':
669
- script = buildTimelockCovenant(amount, address, 144); // 144 blocks ≈ 24 hours
670
- break;
671
- case 'multisig':
672
- script = buildMultisigCovenant(amount, address, 2, 3); // 2-of-3 multisig
673
- break;
674
- case 'conditional':
675
- script = buildConditionalCovenant(amount, address);
676
- break;
677
- default:
678
- throw new Error('Unknown covenant type');
679
- }
680
-
681
- currentCovenant = {
682
- type: type,
683
- amount: amount,
684
- address: address,
685
- script: script,
686
- covenantKey: covenantKey,
687
- covenantAddress: covenantAddress
688
- };
689
-
690
- log('covenant-output', '✅ Covenant generated successfully!', 'success');
691
- log('covenant-output', `📜 Script length: ${script.toBuffer().length} bytes`, 'info');
692
-
693
- } catch (error) {
694
- log('covenant-output', `❌ Covenant generation failed: ${error.message}`, 'error');
695
- }
696
- }
697
-
698
- function buildSimpleCovenant(amount, recipientAddress) {
699
- // Simple covenant: can only be spent to specific address with exact amount
700
- const script = new bsv.Script();
701
-
702
- // Add covenant logic (simplified for demo)
703
- script.add(bsv.Opcode.OP_DUP)
704
- .add(bsv.Opcode.OP_HASH160)
705
- .add(bsv.Address.fromString(recipientAddress || '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa').hashBuffer)
706
- .add(bsv.Opcode.OP_EQUALVERIFY)
707
- .add(bsv.Opcode.OP_CHECKSIG);
708
-
709
- return script;
710
- }
711
-
712
- function buildTimelockCovenant(amount, recipientAddress, blocks) {
713
- // SmartLedger-BSV timelock using preimage validation
714
- const script = new bsv.Script();
715
-
716
- // Preimage-based timelock logic (SmartLedger-BSV method)
717
- // 1. Duplicate preimage for validation
718
- script.add(bsv.Opcode.OP_DUP)
719
- // 2. Extract nLockTime field from preimage (bytes 36-40)
720
- .add(36) // Start position for nLockTime
721
- .add(4) // Length of nLockTime field
722
- .add(bsv.Opcode.OP_SUBSTR)
723
- // 3. Convert to number and compare with required block height
724
- .add(bsv.Opcode.OP_BIN2NUM)
725
- .add(blocks) // Required block height
726
- .add(bsv.Opcode.OP_GREATERTHANOREQUAL)
727
- .add(bsv.Opcode.OP_VERIFY)
728
- // 4. Hash preimage and verify
729
- .add(bsv.Opcode.OP_HASH256)
730
- .add('placeholder_preimage_hash') // Will be replaced with actual hash
731
- .add(bsv.Opcode.OP_EQUALVERIFY)
732
- // 5. Standard P2PKH check
733
- .add(bsv.Opcode.OP_DROP)
734
- .add(bsv.Address.fromString(recipientAddress || '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa').hashBuffer)
735
- .add(bsv.Opcode.OP_CHECKSIG);
736
-
737
- return script;
738
- }
739
-
740
- function buildMultisigCovenant(amount, recipientAddress, m, n) {
741
- // Multisig covenant: requires m-of-n signatures
742
- const script = new bsv.Script();
743
-
744
- // Generate dummy public keys for demo
745
- const pubkeys = [];
746
- for (let i = 0; i < n; i++) {
747
- pubkeys.push(new bsv.PrivateKey().publicKey);
748
- }
749
-
750
- script.add(bsv.Opcode.OP_0); // Bug in CHECKMULTISIG requires extra value
751
- for (let i = 0; i < m; i++) {
752
- script.add(bsv.Opcode.OP_0); // Placeholder for signatures
753
- }
754
- script.add(m);
755
- pubkeys.forEach(pubkey => script.add(pubkey.toBuffer()));
756
- script.add(n);
757
- script.add(bsv.Opcode.OP_CHECKMULTISIG);
758
-
759
- return script;
760
- }
761
-
762
- function buildConditionalCovenant(amount, recipientAddress) {
763
- // SmartLedger-BSV conditional covenant using preimage validation
764
- const script = new bsv.Script();
765
-
766
- // Conditional logic using preimage field validation
767
- script.add(bsv.Opcode.OP_IF)
768
- // Path 1: Direct spending with signature
769
- .add(bsv.Opcode.OP_DUP)
770
- .add(bsv.Opcode.OP_HASH256)
771
- .add('placeholder_preimage_hash_1') // First valid preimage hash
772
- .add(bsv.Opcode.OP_EQUALVERIFY)
773
- .add(bsv.Opcode.OP_DROP)
774
- .add(bsv.Address.fromString(recipientAddress || '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa').hashBuffer)
775
- .add(bsv.Opcode.OP_CHECKSIG)
776
- .add(bsv.Opcode.OP_ELSE)
777
- // Path 2: Alternative spending with different preimage constraints
778
- .add(bsv.Opcode.OP_DUP)
779
- .add(bsv.Opcode.OP_HASH256)
780
- .add('placeholder_preimage_hash_2') // Alternative preimage hash
781
- .add(bsv.Opcode.OP_EQUALVERIFY)
782
- .add(bsv.Opcode.OP_DROP)
783
- .add(bsv.Address.fromString(recipientAddress || '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa').hashBuffer)
784
- .add(bsv.Opcode.OP_CHECKSIG)
785
- .add(bsv.Opcode.OP_ENDIF);
786
-
787
- return script;
788
- }
789
-
790
- function testCovenant() {
791
- if (!currentCovenant) {
792
- log('covenant-output', '❌ No covenant generated. Please generate a covenant first.', 'error');
793
- return;
794
- }
795
-
796
- log('covenant-output', '🧪 Testing Covenant...', 'info');
797
-
798
- try {
799
- // Create a test transaction
800
- const tx = new bsv.Transaction();
801
-
802
- // Add input (mock UTXO)
803
- tx.from({
804
- txId: 'mock_covenant_input_' + Date.now(),
805
- outputIndex: 0,
806
- script: currentCovenant.script.toString(),
807
- satoshis: currentCovenant.amount
808
- });
809
-
810
- // Add output
811
- tx.to(currentCovenant.address || currentCovenant.covenantAddress.toString(), currentCovenant.amount - 1000); // minus fee
812
-
813
- log('covenant-output', '✅ Test transaction created successfully!', 'success');
814
- log('covenant-output', `📊 Transaction ID: ${tx.id}`, 'info');
815
- log('covenant-output', `💰 Input amount: ${currentCovenant.amount} satoshis`, 'info');
816
- log('covenant-output', `💸 Output amount: ${currentCovenant.amount - 1000} satoshis`, 'info');
817
- log('covenant-output', `🏦 Fee: 1000 satoshis`, 'info');
818
-
819
- } catch (error) {
820
- log('covenant-output', `❌ Covenant test failed: ${error.message}`, 'error');
821
- }
822
- }
823
-
824
- function showCovenantScript() {
825
- if (!currentCovenant) {
826
- log('covenant-output', '❌ No covenant generated. Please generate a covenant first.', 'error');
827
- return;
828
- }
829
-
830
- log('covenant-output', '📜 Covenant Script ASM:', 'info');
831
- log('covenant-output', `<pre>${currentCovenant.script.toString()}</pre>`, 'success');
832
- log('covenant-output', `📏 Script size: ${currentCovenant.script.toBuffer().length} bytes`, 'info');
833
- log('covenant-output', `🔢 Script hex: ${currentCovenant.script.toBuffer().toString('hex')}`, 'info');
834
- }
835
-
836
- // Preimage Parser Functions
837
- function generateSampleTx() {
838
- clearOutput('preimage-output');
839
- log('preimage-output', '🎲 Generating Sample Transaction...', 'info');
840
-
841
- try {
842
- const privateKey = new bsv.PrivateKey();
843
- const address = privateKey.toAddress();
844
-
845
- const tx = new bsv.Transaction()
846
- .from({
847
- txId: 'sample_' + Date.now(),
848
- outputIndex: 0,
849
- script: bsv.Script.buildPublicKeyHashOut(address).toString(),
850
- satoshis: 100000
851
- })
852
- .to('1BitcoinEaterAddressDontSendf59kuE', 50000)
853
- .change(address)
854
- .sign(privateKey);
855
-
856
- document.getElementById('tx-hex').value = tx.toString();
857
- log('preimage-output', '✅ Sample transaction generated!', 'success');
858
- log('preimage-output', `📊 Transaction ID: ${tx.id}`, 'info');
859
- log('preimage-output', `📏 Transaction size: ${tx.toString().length / 2} bytes`, 'info');
860
-
861
- } catch (error) {
862
- log('preimage-output', `❌ Failed to generate sample: ${error.message}`, 'error');
863
- }
864
- }
865
-
866
- function parsePreimage() {
867
- const txHex = document.getElementById('tx-hex').value.trim();
868
- if (!txHex) {
869
- log('preimage-output', '❌ Please provide transaction hex or generate a sample.', 'error');
870
- return;
871
- }
872
-
873
- clearOutput('preimage-output');
874
- log('preimage-output', '🔍 Parsing Preimage...', 'info');
875
-
876
- try {
877
- const tx = new bsv.Transaction(txHex);
878
-
879
- // Extract preimage components (BIP-143)
880
- log('preimage-output', '📋 BIP-143 Preimage Components:', 'info');
881
- log('preimage-output', `📝 Version: ${tx.version}`, 'success');
882
- log('preimage-output', `🔗 Input Count: ${tx.inputs.length}`, 'success');
883
- log('preimage-output', `📤 Output Count: ${tx.outputs.length}`, 'success');
884
- log('preimage-output', `⏰ Lock Time: ${tx.nLockTime}`, 'success');
885
-
886
- // Show input details
887
- tx.inputs.forEach((input, index) => {
888
- log('preimage-output', `🔍 Input ${index}: ${input.prevTxId}:${input.outputIndex}`, 'info');
889
- });
890
-
891
- // Show output details
892
- tx.outputs.forEach((output, index) => {
893
- log('preimage-output', `📤 Output ${index}: ${output.satoshis} sats to ${output.script.toString().substring(0, 50)}...`, 'info');
894
- });
895
-
896
- } catch (error) {
897
- log('preimage-output', `❌ Preimage parsing failed: ${error.message}`, 'error');
898
- }
899
- }
900
-
901
- function extractSighash() {
902
- const txHex = document.getElementById('tx-hex').value.trim();
903
- if (!txHex) {
904
- log('preimage-output', '❌ Please provide transaction hex first.', 'error');
905
- return;
906
- }
907
-
908
- log('preimage-output', '📊 Extracting SIGHASH information...', 'info');
909
-
910
- try {
911
- const tx = new bsv.Transaction(txHex);
912
-
913
- // SIGHASH flags
914
- const sighashTypes = {
915
- 0x01: 'SIGHASH_ALL',
916
- 0x02: 'SIGHASH_NONE',
917
- 0x03: 'SIGHASH_SINGLE',
918
- 0x81: 'SIGHASH_ALL | ANYONECANPAY',
919
- 0x82: 'SIGHASH_NONE | ANYONECANPAY',
920
- 0x83: 'SIGHASH_SINGLE | ANYONECANPAY'
921
- };
922
-
923
- log('preimage-output', '🔒 SIGHASH Analysis:', 'success');
924
- log('preimage-output', '📋 Available SIGHASH types:', 'info');
925
-
926
- Object.entries(sighashTypes).forEach(([flag, name]) => {
927
- log('preimage-output', ` ${flag}: ${name}`, 'info');
928
- });
929
-
930
- log('preimage-output', '💡 Most common: SIGHASH_ALL (0x01) - signs all inputs and outputs', 'success');
931
-
932
- } catch (error) {
933
- log('preimage-output', `❌ SIGHASH extraction failed: ${error.message}`, 'error');
934
- }
935
- }
936
-
937
- function validatePreimage() {
938
- const txHex = document.getElementById('tx-hex').value.trim();
939
- if (!txHex) {
940
- log('preimage-output', '❌ Please provide transaction hex first.', 'error');
941
- return;
942
- }
943
-
944
- log('preimage-output', '✅ Validating Preimage Fields...', 'info');
945
-
946
- try {
947
- const tx = new bsv.Transaction(txHex);
948
-
949
- // Validation checks
950
- const validations = [
951
- { name: 'Version', check: tx.version >= 1, value: tx.version },
952
- { name: 'Input Count', check: tx.inputs.length > 0, value: tx.inputs.length },
953
- { name: 'Output Count', check: tx.outputs.length > 0, value: tx.outputs.length },
954
- { name: 'Lock Time', check: tx.nLockTime >= 0, value: tx.nLockTime },
955
- { name: 'Transaction Size', check: txHex.length <= 200000, value: `${txHex.length / 2} bytes` }
956
- ];
957
-
958
- validations.forEach(validation => {
959
- const status = validation.check ? '✅' : '❌';
960
- const type = validation.check ? 'success' : 'error';
961
- log('preimage-output', `${status} ${validation.name}: ${validation.value}`, type);
962
- });
963
-
964
- const allValid = validations.every(v => v.check);
965
- log('preimage-output', allValid ? '🎉 All validations passed!' : '⚠️ Some validations failed!',
966
- allValid ? 'success' : 'error');
967
-
968
- } catch (error) {
969
- log('preimage-output', `❌ Validation failed: ${error.message}`, 'error');
970
- }
971
- }
972
-
973
- // UTXO Generator Functions
974
- function generateUTXO() {
975
- clearOutput('utxo-output');
976
- log('utxo-output', '💎 Generating Mock UTXO...', 'info');
977
-
978
- try {
979
- const wif = document.getElementById('utxo-wif').value.trim();
980
- const amount = parseInt(document.getElementById('utxo-amount').value);
981
- const network = document.getElementById('utxo-network').value;
982
-
983
- // Generate or use provided private key
984
- let privateKey;
985
- if (wif) {
986
- privateKey = bsv.PrivateKey.fromWIF(wif);
987
- log('utxo-output', '🔑 Using provided private key', 'info');
988
- } else {
989
- privateKey = new bsv.PrivateKey(undefined, network);
990
- log('utxo-output', '🎲 Generated new random private key', 'info');
991
- }
992
-
993
- const address = privateKey.toAddress(network);
994
- const script = bsv.Script.buildPublicKeyHashOut(address);
995
-
996
- // Create mock UTXO
997
- currentUTXO = {
998
- txId: 'mock_utxo_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9),
999
- outputIndex: 0,
1000
- address: address.toString(),
1001
- script: script.toString(),
1002
- satoshis: amount,
1003
- privateKey: privateKey,
1004
- network: network
1005
- };
1006
-
1007
- log('utxo-output', '✅ Mock UTXO generated successfully!', 'success');
1008
- log('utxo-output', `🆔 UTXO ID: ${currentUTXO.txId}:${currentUTXO.outputIndex}`, 'info');
1009
- log('utxo-output', `🏠 Address: ${currentUTXO.address}`, 'info');
1010
- log('utxo-output', `💰 Value: ${currentUTXO.satoshis} satoshis`, 'info');
1011
- log('utxo-output', `🌐 Network: ${currentUTXO.network}`, 'info');
1012
- log('utxo-output', `🔑 Private Key (WIF): ${currentUTXO.privateKey.toWIF()}`, 'info');
1013
-
1014
- } catch (error) {
1015
- log('utxo-output', `❌ UTXO generation failed: ${error.message}`, 'error');
1016
- }
1017
- }
1018
-
1019
- function createSpendingTx() {
1020
- if (!currentUTXO) {
1021
- log('utxo-output', '❌ No UTXO available. Please generate a UTXO first.', 'error');
1022
- return;
1023
- }
1024
-
1025
- log('utxo-output', '💸 Creating Spending Transaction...', 'info');
1026
-
1027
- try {
1028
- const recipientAddress = '1BitcoinEaterAddressDontSendf59kuE'; // Burn address for demo
1029
- const fee = 1000;
1030
- const outputAmount = currentUTXO.satoshis - fee;
1031
-
1032
- if (outputAmount <= 0) {
1033
- throw new Error('Insufficient funds for transaction fee');
1034
- }
1035
-
1036
- const tx = new bsv.Transaction()
1037
- .from(currentUTXO)
1038
- .to(recipientAddress, outputAmount)
1039
- .sign(currentUTXO.privateKey);
1040
-
1041
- log('utxo-output', '✅ Spending transaction created!', 'success');
1042
- log('utxo-output', `📊 Transaction ID: ${tx.id}`, 'info');
1043
- log('utxo-output', `💰 Input: ${currentUTXO.satoshis} satoshis`, 'info');
1044
- log('utxo-output', `💸 Output: ${outputAmount} satoshis`, 'info');
1045
- log('utxo-output', `🏦 Fee: ${fee} satoshis`, 'info');
1046
- log('utxo-output', `📏 Transaction size: ${tx.toString().length / 2} bytes`, 'info');
1047
- log('utxo-output', `🔗 Raw transaction: ${tx.toString().substring(0, 100)}...`, 'info');
1048
-
1049
- } catch (error) {
1050
- log('utxo-output', `❌ Spending transaction failed: ${error.message}`, 'error');
1051
- }
1052
- }
1053
-
1054
- function showUTXODetails() {
1055
- if (!currentUTXO) {
1056
- log('utxo-output', '❌ No UTXO available. Please generate a UTXO first.', 'error');
1057
- return;
1058
- }
1059
-
1060
- log('utxo-output', '📋 Detailed UTXO Information:', 'info');
1061
- log('utxo-output', `<pre>
1062
- UTXO Details:
1063
- ============
1064
- Transaction ID: ${currentUTXO.txId}
1065
- Output Index: ${currentUTXO.outputIndex}
1066
- Address: ${currentUTXO.address}
1067
- Value: ${currentUTXO.satoshis} satoshis (${(currentUTXO.satoshis / 100000000).toFixed(8)} BSV)
1068
- Network: ${currentUTXO.network}
1069
-
1070
- Script Details:
1071
- ==============
1072
- Script ASM: ${currentUTXO.script}
1073
- Script Size: ${Buffer.from(currentUTXO.script, 'hex').length} bytes
1074
-
1075
- Private Key:
1076
- ===========
1077
- WIF: ${currentUTXO.privateKey.toWIF()}
1078
- Hex: ${currentUTXO.privateKey.toString()}
1079
- Compressed: ${currentUTXO.privateKey.compressed}
1080
-
1081
- Address Details:
1082
- ===============
1083
- Hash160: ${bsv.Address.fromString(currentUTXO.address).hashBuffer.toString('hex')}
1084
- Version: ${bsv.Address.fromString(currentUTXO.address).network.pubkeyhash}
1085
- </pre>`, 'success');
1086
- }
1087
-
1088
- // Script Tools Functions
1089
- function buildScript() {
1090
- clearOutput('scripts-output');
1091
- log('scripts-output', '🏗️ Building Script...', 'info');
1092
-
1093
- try {
1094
- const asmCode = document.getElementById('script-asm').value.trim();
1095
- const scriptType = document.getElementById('script-type').value;
1096
-
1097
- if (!asmCode) {
1098
- throw new Error('Please provide script ASM code');
1099
- }
1100
-
1101
- const script = bsv.Script.fromASM(asmCode);
1102
-
1103
- log('scripts-output', `✅ Script built successfully!`, 'success');
1104
- log('scripts-output', `📝 Script type: ${scriptType}`, 'info');
1105
- log('scripts-output', `📏 Script size: ${script.toBuffer().length} bytes`, 'info');
1106
- log('scripts-output', `🔢 Script hex: ${script.toBuffer().toString('hex')}`, 'info');
1107
- log('scripts-output', `📜 Script ASM: ${script.toString()}`, 'info');
1108
-
1109
- // Analyze script opcodes
1110
- const opcodes = script.chunks.map(chunk => {
1111
- if (chunk.opcodenum !== undefined) {
1112
- return `OP_${bsv.Opcode.reverseMap[chunk.opcodenum] || chunk.opcodenum}`;
1113
- } else if (chunk.buf) {
1114
- return `DATA(${chunk.buf.length} bytes)`;
1115
- }
1116
- return 'UNKNOWN';
1117
- });
1118
-
1119
- log('scripts-output', `🔍 Opcodes: ${opcodes.join(', ')}`, 'info');
1120
-
1121
- } catch (error) {
1122
- log('scripts-output', `❌ Script building failed: ${error.message}`, 'error');
1123
- }
1124
- }
1125
-
1126
- function analyzeScript() {
1127
- const asmCode = document.getElementById('script-asm').value.trim();
1128
- if (!asmCode) {
1129
- log('scripts-output', '❌ Please provide script ASM code first.', 'error');
1130
- return;
1131
- }
1132
-
1133
- log('scripts-output', '🔍 Analyzing Script...', 'info');
1134
-
1135
- try {
1136
- const script = bsv.Script.fromASM(asmCode);
1137
-
1138
- // Script analysis
1139
- const analysis = {
1140
- size: script.toBuffer().length,
1141
- chunks: script.chunks.length,
1142
- isPushOnly: script.isPushOnly(),
1143
- isStandard: true, // Simplified check
1144
- hasTimelock: asmCode.includes('CHECKLOCKTIMEVERIFY') || asmCode.includes('CHECKSEQUENCEVERIFY'),
1145
- hasMultisig: asmCode.includes('CHECKMULTISIG'),
1146
- hasHash: asmCode.includes('HASH160') || asmCode.includes('HASH256'),
1147
- complexity: 'Medium' // Simplified assessment
1148
- };
1149
-
1150
- log('scripts-output', '📊 Script Analysis Results:', 'success');
1151
- log('scripts-output', `📏 Size: ${analysis.size} bytes`, 'info');
1152
- log('scripts-output', `🧩 Chunks: ${analysis.chunks}`, 'info');
1153
- log('scripts-output', `📌 Push-only: ${analysis.isPushOnly ? 'Yes' : 'No'}`, 'info');
1154
- log('scripts-output', `✅ Standard: ${analysis.isStandard ? 'Yes' : 'No'}`, 'info');
1155
- log('scripts-output', `⏰ Has timelock: ${analysis.hasTimelock ? 'Yes' : 'No'}`, 'info');
1156
- log('scripts-output', `👥 Has multisig: ${analysis.hasMultisig ? 'Yes' : 'No'}`, 'info');
1157
- log('scripts-output', `🔐 Has hash ops: ${analysis.hasHash ? 'Yes' : 'No'}`, 'info');
1158
- log('scripts-output', `🎯 Complexity: ${analysis.complexity}`, 'info');
1159
-
1160
- // Fee estimation
1161
- const feePerByte = 1; // satoshis per byte
1162
- const estimatedFee = analysis.size * feePerByte;
1163
- log('scripts-output', `💰 Estimated fee: ${estimatedFee} satoshis (at ${feePerByte} sat/byte)`, 'info');
1164
-
1165
- } catch (error) {
1166
- log('scripts-output', `❌ Script analysis failed: ${error.message}`, 'error');
1167
- }
1168
- }
1169
-
1170
- function debugScript() {
1171
- const asmCode = document.getElementById('script-asm').value.trim();
1172
- if (!asmCode) {
1173
- log('scripts-output', '❌ Please provide script ASM code first.', 'error');
1174
- return;
1175
- }
1176
-
1177
- log('scripts-output', '🐛 Debug Mode: Step-by-step execution', 'info');
1178
-
1179
- try {
1180
- const script = bsv.Script.fromASM(asmCode);
1181
-
1182
- log('scripts-output', '🔍 Script Debug Information:', 'success');
1183
- log('scripts-output', '📋 Execution Steps:', 'info');
1184
-
1185
- script.chunks.forEach((chunk, index) => {
1186
- if (chunk.opcodenum !== undefined) {
1187
- const opname = bsv.Opcode.reverseMap[chunk.opcodenum] || `OP_${chunk.opcodenum}`;
1188
- log('scripts-output', ` Step ${index + 1}: Execute ${opname}`, 'info');
1189
- } else if (chunk.buf) {
1190
- log('scripts-output', ` Step ${index + 1}: Push data (${chunk.buf.length} bytes): ${chunk.buf.toString('hex')}`, 'info');
1191
- }
1192
- });
1193
-
1194
- log('scripts-output', '💡 Debug complete! For full verification, create a transaction and use bsv.Script.Interpreter', 'success');
1195
-
1196
- } catch (error) {
1197
- log('scripts-output', `❌ Script debugging failed: ${error.message}`, 'error');
1198
- }
1199
- }
1200
-
1201
- function optimizeScript() {
1202
- const asmCode = document.getElementById('script-asm').value.trim();
1203
- if (!asmCode) {
1204
- log('scripts-output', '❌ Please provide script ASM code first.', 'error');
1205
- return;
1206
- }
1207
-
1208
- log('scripts-output', '⚡ Optimizing Script...', 'info');
1209
-
1210
- try {
1211
- const script = bsv.Script.fromASM(asmCode);
1212
- const originalSize = script.toBuffer().length;
1213
-
1214
- // Simple optimization suggestions
1215
- const optimizations = [];
1216
-
1217
- if (asmCode.includes('OP_1 OP_ADD')) {
1218
- optimizations.push('Replace "OP_1 OP_ADD" with "OP_1ADD" (saves 1 byte)');
1219
- }
1220
-
1221
- if (asmCode.includes('OP_0')) {
1222
- optimizations.push('OP_0 is efficiently encoded');
1223
- }
1224
-
1225
- if (asmCode.includes('OP_1') && !asmCode.includes('OP_1ADD')) {
1226
- optimizations.push('OP_1-OP_16 are more efficient than pushing the number');
1227
- }
1228
-
1229
- const redundantOps = asmCode.match(/OP_DUP OP_DROP/g);
1230
- if (redundantOps) {
1231
- optimizations.push(`Remove redundant OP_DUP OP_DROP sequences (${redundantOps.length} found)`);
1232
- }
1233
-
1234
- log('scripts-output', `📊 Original size: ${originalSize} bytes`, 'info');
1235
-
1236
- if (optimizations.length > 0) {
1237
- log('scripts-output', '💡 Optimization suggestions:', 'success');
1238
- optimizations.forEach(opt => {
1239
- log('scripts-output', ` • ${opt}`, 'info');
1240
- });
1241
- } else {
1242
- log('scripts-output', '✅ Script appears to be well optimized!', 'success');
1243
- }
1244
-
1245
- log('scripts-output', '🎯 General optimization tips:', 'info');
1246
- log('scripts-output', ' • Use OP_1-OP_16 instead of pushing small numbers', 'info');
1247
- log('scripts-output', ' • Minimize stack operations', 'info');
1248
- log('scripts-output', ' • Avoid redundant DUP/DROP sequences', 'info');
1249
- log('scripts-output', ' • Use more efficient opcodes when available', 'info');
1250
-
1251
- } catch (error) {
1252
- log('scripts-output', `❌ Script optimization failed: ${error.message}`, 'error');
1253
- }
1254
- }
1255
-
1256
- // Use Case Examples
1257
- function showEscrowExample() {
1258
- alert(`🏦 Escrow Contract Example:
1259
-
1260
- A 2-of-3 escrow where buyer, seller, and arbiter each hold a key.
1261
- - Buyer and seller can complete transaction normally
1262
- - If dispute, buyer+arbiter or seller+arbiter can resolve
1263
- - Includes timeout clause for refund after 30 days
1264
-
1265
- Script structure:
1266
- IF
1267
- 2 <buyer_pubkey> <seller_pubkey> <arbiter_pubkey> 3 CHECKMULTISIG
1268
- ELSE
1269
- <30_days> CHECKLOCKTIMEVERIFY DROP
1270
- <buyer_pubkey> CHECKSIG
1271
- ENDIF
1272
-
1273
- Click "Covenant Builder" tab to create your own!`);
1274
- }
1275
-
1276
- function showTimelockExample() {
1277
- alert(`⏰ SmartLedger-BSV Timelock Covenant:
1278
-
1279
- Uses preimage validation instead of OP_CHECKLOCKTIMEVERIFY.
1280
- The covenant validates nLockTime field from BIP-143 preimage.
1281
-
1282
- SmartLedger-BSV Script Structure:
1283
- DUP # Duplicate preimage
1284
- 36 4 OP_SUBSTR # Extract nLockTime (bytes 36-40)
1285
- OP_BIN2NUM # Convert to number
1286
- <block_height> # Required minimum block
1287
- OP_GREATERTHANOREQUAL # Check if time passed
1288
- OP_VERIFY # Enforce constraint
1289
- OP_HASH256 # Hash preimage
1290
- <preimage_hash> # Expected hash
1291
- OP_EQUALVERIFY # Validate preimage
1292
- OP_DROP # Clean stack
1293
- <pubkey> OP_CHECKSIG # Signature check
1294
-
1295
- This uses OP_PUSH_TX methods and preimage parsing!
1296
-
1297
- Try the "Covenant Builder" to see real implementation!`);
1298
- }
1299
-
1300
- function showRecurringExample() {
1301
- alert(`🔄 Recurring Payment Example:
1302
-
1303
- Automated payments that renew themselves on-chain.
1304
- Each payment creates a new UTXO for the next payment.
1305
-
1306
- Key features:
1307
- - Self-perpetuating contract
1308
- - Fixed payment amounts and intervals
1309
- - Automatic recipient payment
1310
- - Remaining balance rolls over
1311
-
1312
- Implementation requires covenant logic to:
1313
- 1. Send payment to recipient
1314
- 2. Create new UTXO with remaining funds
1315
- 3. Enforce timing constraints
1316
-
1317
- Explore covenant building for implementation!`);
1318
- }
1319
-
1320
- function showGamingExample() {
1321
- alert(`🎲 Gaming Contract Example:
1322
-
1323
- Provably fair games using on-chain randomness and covenants.
1324
-
1325
- Features:
1326
- - Commit-reveal schemes for fairness
1327
- - Automatic payout based on results
1328
- - Time limits for player actions
1329
- - House edge enforcement
1330
-
1331
- Example: Coin Flip
1332
- 1. Player commits hash(choice + nonce)
1333
- 2. House commits hash(choice + nonce)
1334
- 3. Both reveal - contract determines winner
1335
- 4. Automatic payout to winner
1336
-
1337
- Perfect for trustless gambling and games!`);
1338
- }
1339
-
1340
- // Initialize demo on page load
1341
- window.onload = function() {
1342
- log('basics-output', '🌟 Welcome to BSV Smart Contract Demo!', 'info');
1343
- log('basics-output', '👆 Click "Load BSV Smart Contract Library" to begin', 'info');
1344
- };
1345
- </script>
1346
- </body>
1347
- </html>