@smartledger/bsv 3.4.2 → 3.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/CHANGELOG.md +336 -0
  2. package/README.md +72 -72
  3. package/SECURITY.md +88 -0
  4. package/bin/cli.js +13 -8
  5. package/bsv-covenant.min.js +4 -4
  6. package/bsv-gdaf.min.js +5 -5
  7. package/bsv-ltp.min.js +7 -7
  8. package/bsv-smartcontract.min.js +5 -5
  9. package/bsv.bundle.js +5 -5
  10. package/bsv.d.ts +486 -9
  11. package/bsv.min.js +5 -5
  12. package/docs/COVENANT_DEVELOPMENT_RESOLVED.md +2 -2
  13. package/docs/MODULE_REFERENCE_COMPLETE.md +61 -58
  14. package/docs/advanced/LEGAL_TOKEN_PROTOCOL.md +3 -3
  15. package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
  16. package/docs/getting-started/INSTALLATION.md +30 -30
  17. package/docs/getting-started/QUICK_START.md +18 -18
  18. package/docs/migration/FROM_BSV_1_5_6.md +16 -10
  19. package/gdaf-entry.js +1 -2
  20. package/index.js +20 -7
  21. package/lib/smart_contract/covenant.js +10 -1
  22. package/lib/smartutxo.js +20 -12
  23. package/lib/transaction/transaction.js +7 -0
  24. package/ltp-entry.js +1 -2
  25. package/package.json +3 -3
  26. package/utilities/blockchain-state.js +32 -23
  27. package/demos/README.md +0 -188
  28. package/demos/architecture_demo.js +0 -247
  29. package/demos/browser-test.html +0 -1208
  30. package/demos/bsv_wallet_demo.js +0 -242
  31. package/demos/complete_ltp_demo.js +0 -511
  32. package/demos/debug_tools_demo.js +0 -87
  33. package/demos/demo_features.js +0 -123
  34. package/demos/easy_interface_demo.js +0 -109
  35. package/demos/ecies_demo.js +0 -182
  36. package/demos/gdaf_demo.js +0 -237
  37. package/demos/ltp_demo.js +0 -361
  38. package/demos/ltp_primitives_demo.js +0 -403
  39. package/demos/message_demo.js +0 -209
  40. package/demos/preimage_separation_demo.js +0 -383
  41. package/demos/script_helper_demo.js +0 -289
  42. package/demos/security_demo.js +0 -287
  43. package/demos/shamir_demo.js +0 -121
  44. package/demos/simple_demo.js +0 -204
  45. package/demos/simple_p2pkh_demo.js +0 -169
  46. package/demos/simple_utxo_preimage_demo.js +0 -196
  47. package/demos/smart_contract_demo.html +0 -1347
  48. package/demos/smart_contract_demo.js +0 -910
  49. package/demos/utxo_generator_demo.js +0 -244
  50. package/demos/validation_pipeline_demo.js +0 -155
  51. package/demos/web3keys.html +0 -740
  52. package/examples/README.md +0 -200
  53. package/examples/basic/transaction-creation.js +0 -534
  54. package/examples/basic/transaction_signature_api_gap.js +0 -178
  55. package/examples/complete_workflow_demo.js +0 -783
  56. package/examples/covenants/advanced_covenant_demo.js +0 -219
  57. package/examples/covenants/covenant_interface_demo.js +0 -270
  58. package/examples/covenants/covenant_manual_signature_resolved.js +0 -212
  59. package/examples/covenants/covenant_signature_template.js +0 -117
  60. package/examples/covenants2/covenant_bidirectional_example.js +0 -262
  61. package/examples/covenants2/covenant_utils_demo.js +0 -120
  62. package/examples/covenants2/preimage_covenant_utils.js +0 -287
  63. package/examples/covenants2/production_integration.js +0 -256
  64. package/examples/data/covenant_utxos.json +0 -28
  65. package/examples/data/utxos.json +0 -26
  66. package/examples/definitive_working_demo.js +0 -261
  67. package/examples/final_working_contracts.js +0 -338
  68. package/examples/legacy/README.md +0 -11
  69. package/examples/legacy/smart_contract_test_integration.js +0 -269
  70. package/examples/legacy/test_builtin_verify.js +0 -117
  71. package/examples/legacy/test_debug_integration.js +0 -71
  72. package/examples/legacy/test_ecdsa_little.js +0 -70
  73. package/examples/legacy/test_shamir.js +0 -221
  74. package/examples/legacy/test_smartverify_der.js +0 -110
  75. package/examples/preimage/README.md +0 -178
  76. package/examples/preimage/extract_preimage_bidirectional.js +0 -421
  77. package/examples/preimage/generate_sample_preimage.js +0 -208
  78. package/examples/preimage/generate_sighash_examples.js +0 -152
  79. package/examples/preimage/parse_preimage.js +0 -117
  80. package/examples/preimage/test_preimage_extractor.js +0 -53
  81. package/examples/preimage/test_varint_extraction.js +0 -95
  82. package/examples/scripts/custom_script_helper_example.js +0 -273
  83. package/examples/scripts/script_interpreter.js +0 -193
  84. package/examples/smart_contract/complete_workflow_demo.js +0 -343
  85. package/examples/smart_contract/covenant_builder_demo.js +0 -176
  86. package/examples/smart_contract/script_testing_integration.js +0 -198
  87. package/examples/smart_contract_templates.js +0 -718
  88. package/examples/working_smart_contracts.js +0 -348
@@ -1,910 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * SmartLedger-BSV Smart Contract Demo (Node.js Version)
4
- * ====================================================
5
- *
6
- * Interactive command-line demo showcasing the powerful smart contract
7
- * capabilities of the SmartLedger BSV library. This is the Node.js equivalent
8
- * of the HTML demo, perfect for developers and automated testing.
9
- *
10
- * Usage:
11
- * node smart_contract_demo.js
12
- * node smart_contract_demo.js --help
13
- * node smart_contract_demo.js --feature covenant
14
- * node smart_contract_demo.js --feature preimage
15
- * node smart_contract_demo.js --feature utxo
16
- * node smart_contract_demo.js --feature scripts
17
- */
18
-
19
- const bsv = require('../index');
20
- const readline = require('readline');
21
-
22
- // Try to load chalk for colored output, fallback to plain text
23
- let chalk;
24
- try {
25
- chalk = require('chalk');
26
- } catch (error) {
27
- // Fallback for systems without chalk
28
- chalk = {
29
- cyan: (str) => str,
30
- green: (str) => str,
31
- red: (str) => str,
32
- yellow: (str) => str,
33
- blue: (str) => str,
34
- magenta: (str) => str,
35
- white: (str) => str,
36
- gray: (str) => str,
37
- bold: (str) => str
38
- };
39
- // Chain methods
40
- Object.keys(chalk).forEach(color => {
41
- chalk[color].bold = chalk[color];
42
- });
43
- }
44
-
45
- // ASCII Art Header
46
- const HEADER = `
47
- ╔═══════════════════════════════════════════════════════════════════════════════╗
48
- ā•‘ ā•‘
49
- ā•‘ šŸš€ SmartLedger-BSV Smart Contract Framework Demo (Node.js) ā•‘
50
- ā•‘ ā•‘
51
- ā•‘ Explore covenant creation, preimage parsing, script building, ā•‘
52
- ā•‘ and UTXO management with real Bitcoin SV functionality. ā•‘
53
- ā•‘ ā•‘
54
- ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•
55
- `;
56
-
57
- // Global state
58
- let currentUTXO = null;
59
- let currentCovenant = null;
60
- let SmartContract = null;
61
-
62
- // CLI Interface
63
- const rl = readline.createInterface({
64
- input: process.stdin,
65
- output: process.stdout,
66
- prompt: chalk.cyan('smartledger-bsv> ')
67
- });
68
-
69
- /**
70
- * Utility Functions
71
- */
72
- function log(message, type = 'info') {
73
- const timestamp = new Date().toLocaleTimeString();
74
- const prefix = `[${timestamp}]`;
75
-
76
- switch (type) {
77
- case 'success':
78
- console.log(chalk.green(`${prefix} āœ… ${message}`));
79
- break;
80
- case 'error':
81
- console.log(chalk.red(`${prefix} āŒ ${message}`));
82
- break;
83
- case 'warning':
84
- console.log(chalk.yellow(`${prefix} āš ļø ${message}`));
85
- break;
86
- case 'info':
87
- default:
88
- console.log(chalk.blue(`${prefix} ā„¹ļø ${message}`));
89
- break;
90
- }
91
- }
92
-
93
- function logHeader(title) {
94
- console.log('\n' + chalk.cyan('═'.repeat(80)));
95
- console.log(chalk.cyan.bold(`šŸ”¹ ${title}`));
96
- console.log(chalk.cyan('═'.repeat(80)));
97
- }
98
-
99
- function logSubHeader(title) {
100
- console.log('\n' + chalk.magenta('─'.repeat(60)));
101
- console.log(chalk.magenta.bold(`šŸ“Œ ${title}`));
102
- console.log(chalk.magenta('─'.repeat(60)));
103
- }
104
-
105
- /**
106
- * Feature 1: BSV Library Basics
107
- */
108
- function loadLibrary() {
109
- logHeader('Loading BSV Smart Contract Library');
110
-
111
- try {
112
- // Check if BSV library is available
113
- if (typeof bsv === 'undefined') {
114
- throw new Error('BSV library not loaded. Please ensure the module is properly installed.');
115
- }
116
-
117
- log('BSV library loaded successfully!', 'success');
118
- log(`BSV version: ${bsv.version || 'v3.3.4'}`, 'info');
119
-
120
- // Check available SmartLedger modules
121
- const availableModules = [];
122
- if (bsv.SmartContract) availableModules.push('SmartContract');
123
- if (bsv.LTP) availableModules.push('LTP');
124
- if (bsv.Security) availableModules.push('Security');
125
- if (bsv.GDAF) availableModules.push('GDAF');
126
- if (bsv.Shamir) availableModules.push('Shamir');
127
-
128
- log(`Available modules: ${availableModules.join(', ')}`, 'info');
129
- log('Core BSV classes: Transaction, Script, PrivateKey, Address', 'info');
130
-
131
- // Initialize SmartContract reference
132
- if (bsv.SmartContract) {
133
- SmartContract = bsv.SmartContract;
134
- log('SmartContract module ready!', 'success');
135
- } else {
136
- log('SmartContract module not found in bundle', 'warning');
137
- SmartContract = null;
138
- }
139
-
140
- log('Ready for smart contract development!', 'success');
141
-
142
- } catch (error) {
143
- log(`Error loading library: ${error.message}`, 'error');
144
- }
145
- }
146
-
147
- function showFeatures() {
148
- logHeader('BSV Smart Contract Features');
149
-
150
- const features = [
151
- 'šŸ”’ Covenant Builder - Create complex spending conditions',
152
- '🧾 Preimage Parser - Extract BIP-143 transaction fields',
153
- 'šŸ› ļø Script Tools - Build and debug Bitcoin Scripts',
154
- 'šŸ’Ž UTXO Generator - Create test UTXOs for development',
155
- 'šŸ“Š SIGHASH Analysis - Understand signature hash types',
156
- 'šŸ—ļø ASM Generator - Convert JavaScript to Bitcoin Script',
157
- 'šŸ” Script Debugger - Step-through script execution',
158
- '⚔ Script Optimizer - Minimize script size and cost',
159
- '🧪 Local Testing - Verify scripts without blockchain',
160
- 'šŸ“¦ Production Ready - Deploy to BSV mainnet'
161
- ];
162
-
163
- features.forEach(feature => {
164
- log(feature, 'success');
165
- });
166
-
167
- log('All features available in @smartledger/bsv package!', 'info');
168
- }
169
-
170
- function runBasicTests() {
171
- logHeader('Running Basic Smart Contract Tests');
172
-
173
- try {
174
- // Test 1: Private Key Generation
175
- logSubHeader('Test 1: Private Key Generation');
176
- const privateKey = new bsv.PrivateKey();
177
- const address = privateKey.toAddress();
178
- log(`Generated address: ${address.toString()}`, 'success');
179
-
180
- // Test 2: Transaction Creation
181
- logSubHeader('Test 2: Transaction Creation');
182
- const tx = new bsv.Transaction();
183
- log(`Created transaction: ${tx.id || 'empty transaction'}`, 'success');
184
-
185
- // Test 3: Script Building
186
- logSubHeader('Test 3: Script Building');
187
- const script = bsv.Script.buildPublicKeyHashOut(address);
188
- log(`Built P2PKH script: ${script.toString().substring(0, 50)}...`, 'success');
189
-
190
- // Test 4: Mock UTXO
191
- logSubHeader('Test 4: Mock UTXO Creation');
192
- const utxo = {
193
- txId: 'mock_' + Date.now(),
194
- outputIndex: 0,
195
- address: address.toString(),
196
- script: script.toString(),
197
- satoshis: 100000
198
- };
199
- log(`Created mock UTXO: ${utxo.satoshis} satoshis`, 'success');
200
-
201
- log('All basic tests passed! Smart contract functionality ready.', 'success');
202
-
203
- } catch (error) {
204
- log(`Test failed: ${error.message}`, 'error');
205
- }
206
- }
207
-
208
- /**
209
- * Feature 2: Covenant Builder
210
- */
211
- function generateCovenant(type = 'simple', amount = 100000, address = null) {
212
- logHeader('Generating Covenant');
213
-
214
- try {
215
- // Generate keys for covenant
216
- const covenantKey = new bsv.PrivateKey();
217
- const covenantAddress = covenantKey.toAddress();
218
-
219
- log(`Covenant Type: ${type}`, 'info');
220
- log(`Amount: ${amount} satoshis`, 'info');
221
- log(`Covenant Address: ${covenantAddress.toString()}`, 'info');
222
-
223
- // Build covenant script based on type
224
- let script;
225
- switch (type) {
226
- case 'simple':
227
- script = buildSimpleCovenant(amount, address);
228
- break;
229
- case 'timelock':
230
- script = buildTimelockCovenant(amount, address, 144); // 144 blocks ā‰ˆ 24 hours
231
- break;
232
- case 'multisig':
233
- script = buildMultisigCovenant(amount, address, 2, 3); // 2-of-3 multisig
234
- break;
235
- case 'conditional':
236
- script = buildConditionalCovenant(amount, address);
237
- break;
238
- default:
239
- throw new Error('Unknown covenant type');
240
- }
241
-
242
- currentCovenant = {
243
- type: type,
244
- amount: amount,
245
- address: address,
246
- script: script,
247
- covenantKey: covenantKey,
248
- covenantAddress: covenantAddress
249
- };
250
-
251
- log('Covenant generated successfully!', 'success');
252
- log(`Script length: ${script.toBuffer().length} bytes`, 'info');
253
-
254
- return currentCovenant;
255
-
256
- } catch (error) {
257
- log(`Covenant generation failed: ${error.message}`, 'error');
258
- return null;
259
- }
260
- }
261
-
262
- function buildSimpleCovenant(amount, recipientAddress) {
263
- // Simple covenant: can only be spent to specific address with exact amount
264
- const script = new bsv.Script();
265
-
266
- // Add covenant logic (simplified for demo)
267
- script.add(bsv.Opcode.OP_DUP)
268
- .add(bsv.Opcode.OP_HASH160)
269
- .add(bsv.Address.fromString(recipientAddress || '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa').hashBuffer)
270
- .add(bsv.Opcode.OP_EQUALVERIFY)
271
- .add(bsv.Opcode.OP_CHECKSIG);
272
-
273
- return script;
274
- }
275
-
276
- function buildTimelockCovenant(amount, recipientAddress, blocks) {
277
- // SmartLedger-BSV timelock using preimage validation
278
- const script = new bsv.Script();
279
-
280
- // Preimage-based timelock logic (SmartLedger-BSV method)
281
- script.add(bsv.Opcode.OP_DUP)
282
- .add(36) // Start position for nLockTime
283
- .add(4) // Length of nLockTime field
284
- .add(bsv.Opcode.OP_SUBSTR)
285
- .add(bsv.Opcode.OP_BIN2NUM)
286
- .add(blocks) // Required block height
287
- .add(bsv.Opcode.OP_GREATERTHANOREQUAL)
288
- .add(bsv.Opcode.OP_VERIFY)
289
- .add(bsv.Opcode.OP_HASH256)
290
- .add('placeholder_preimage_hash')
291
- .add(bsv.Opcode.OP_EQUALVERIFY)
292
- .add(bsv.Opcode.OP_DROP)
293
- .add(bsv.Address.fromString(recipientAddress || '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa').hashBuffer)
294
- .add(bsv.Opcode.OP_CHECKSIG);
295
-
296
- return script;
297
- }
298
-
299
- function buildMultisigCovenant(amount, recipientAddress, m, n) {
300
- // Multisig covenant: requires m-of-n signatures
301
- const script = new bsv.Script();
302
-
303
- // Generate dummy public keys for demo
304
- const pubkeys = [];
305
- for (let i = 0; i < n; i++) {
306
- pubkeys.push(new bsv.PrivateKey().publicKey);
307
- }
308
-
309
- script.add(bsv.Opcode.OP_0); // Bug in CHECKMULTISIG requires extra value
310
- for (let i = 0; i < m; i++) {
311
- script.add(bsv.Opcode.OP_0); // Placeholder for signatures
312
- }
313
- script.add(m);
314
- pubkeys.forEach(pubkey => script.add(pubkey.toBuffer()));
315
- script.add(n);
316
- script.add(bsv.Opcode.OP_CHECKMULTISIG);
317
-
318
- return script;
319
- }
320
-
321
- function buildConditionalCovenant(amount, recipientAddress) {
322
- // SmartLedger-BSV conditional covenant using preimage validation
323
- const script = new bsv.Script();
324
-
325
- script.add(bsv.Opcode.OP_IF)
326
- .add(bsv.Opcode.OP_DUP)
327
- .add(bsv.Opcode.OP_HASH256)
328
- .add('placeholder_preimage_hash_1')
329
- .add(bsv.Opcode.OP_EQUALVERIFY)
330
- .add(bsv.Opcode.OP_DROP)
331
- .add(bsv.Address.fromString(recipientAddress || '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa').hashBuffer)
332
- .add(bsv.Opcode.OP_CHECKSIG)
333
- .add(bsv.Opcode.OP_ELSE)
334
- .add(bsv.Opcode.OP_DUP)
335
- .add(bsv.Opcode.OP_HASH256)
336
- .add('placeholder_preimage_hash_2')
337
- .add(bsv.Opcode.OP_EQUALVERIFY)
338
- .add(bsv.Opcode.OP_DROP)
339
- .add(bsv.Address.fromString(recipientAddress || '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa').hashBuffer)
340
- .add(bsv.Opcode.OP_CHECKSIG)
341
- .add(bsv.Opcode.OP_ENDIF);
342
-
343
- return script;
344
- }
345
-
346
- function testCovenant() {
347
- if (!currentCovenant) {
348
- log('No covenant generated. Please generate a covenant first.', 'error');
349
- return;
350
- }
351
-
352
- logHeader('Testing Covenant');
353
-
354
- try {
355
- // Create a test transaction
356
- const tx = new bsv.Transaction();
357
-
358
- // Add input (mock UTXO)
359
- tx.from({
360
- txId: 'mock_covenant_input_' + Date.now(),
361
- outputIndex: 0,
362
- script: currentCovenant.script.toString(),
363
- satoshis: currentCovenant.amount
364
- });
365
-
366
- // Add output
367
- tx.to(currentCovenant.address || currentCovenant.covenantAddress.toString(), currentCovenant.amount - 1000);
368
-
369
- log('Test transaction created successfully!', 'success');
370
- log(`Transaction ID: ${tx.id}`, 'info');
371
- log(`Input amount: ${currentCovenant.amount} satoshis`, 'info');
372
- log(`Output amount: ${currentCovenant.amount - 1000} satoshis`, 'info');
373
- log('Fee: 1000 satoshis', 'info');
374
-
375
- } catch (error) {
376
- log(`Covenant test failed: ${error.message}`, 'error');
377
- }
378
- }
379
-
380
- function showCovenantScript() {
381
- if (!currentCovenant) {
382
- log('No covenant generated. Please generate a covenant first.', 'error');
383
- return;
384
- }
385
-
386
- logHeader('Covenant Script ASM');
387
-
388
- console.log(chalk.green('\nScript ASM:'));
389
- console.log(chalk.white(currentCovenant.script.toString()));
390
-
391
- log(`Script size: ${currentCovenant.script.toBuffer().length} bytes`, 'info');
392
- log(`Script hex: ${currentCovenant.script.toBuffer().toString('hex')}`, 'info');
393
- }
394
-
395
- /**
396
- * Feature 3: Preimage Parser
397
- */
398
- function generateSampleTx() {
399
- logHeader('Generating Sample Transaction');
400
-
401
- try {
402
- const privateKey = new bsv.PrivateKey();
403
- const address = privateKey.toAddress();
404
-
405
- const tx = new bsv.Transaction()
406
- .from({
407
- txId: 'sample_' + Date.now(),
408
- outputIndex: 0,
409
- script: bsv.Script.buildPublicKeyHashOut(address).toString(),
410
- satoshis: 100000
411
- })
412
- .to('1BitcoinEaterAddressDontSendf59kuE', 50000)
413
- .change(address)
414
- .sign(privateKey);
415
-
416
- log('Sample transaction generated!', 'success');
417
- log(`Transaction ID: ${tx.id}`, 'info');
418
- log(`Transaction size: ${tx.toString().length / 2} bytes`, 'info');
419
-
420
- console.log(chalk.green('\nTransaction Hex:'));
421
- console.log(chalk.white(tx.toString()));
422
-
423
- return tx.toString();
424
-
425
- } catch (error) {
426
- log(`Failed to generate sample: ${error.message}`, 'error');
427
- return null;
428
- }
429
- }
430
-
431
- function parsePreimage(txHex) {
432
- if (!txHex) {
433
- log('Please provide transaction hex or generate a sample first.', 'error');
434
- return;
435
- }
436
-
437
- logHeader('Parsing Preimage');
438
-
439
- try {
440
- const tx = new bsv.Transaction(txHex);
441
-
442
- // Extract preimage components (BIP-143)
443
- logSubHeader('BIP-143 Preimage Components');
444
- log(`Version: ${tx.version}`, 'success');
445
- log(`Input Count: ${tx.inputs.length}`, 'success');
446
- log(`Output Count: ${tx.outputs.length}`, 'success');
447
- log(`Lock Time: ${tx.nLockTime}`, 'success');
448
-
449
- // Show input details
450
- logSubHeader('Input Details');
451
- tx.inputs.forEach((input, index) => {
452
- log(`Input ${index}: ${input.prevTxId}:${input.outputIndex}`, 'info');
453
- });
454
-
455
- // Show output details
456
- logSubHeader('Output Details');
457
- tx.outputs.forEach((output, index) => {
458
- log(`Output ${index}: ${output.satoshis} sats to ${output.script.toString().substring(0, 50)}...`, 'info');
459
- });
460
-
461
- } catch (error) {
462
- log(`Preimage parsing failed: ${error.message}`, 'error');
463
- }
464
- }
465
-
466
- function extractSighash() {
467
- logHeader('SIGHASH Information');
468
-
469
- // SIGHASH flags
470
- const sighashTypes = {
471
- 0x01: 'SIGHASH_ALL',
472
- 0x02: 'SIGHASH_NONE',
473
- 0x03: 'SIGHASH_SINGLE',
474
- 0x81: 'SIGHASH_ALL | ANYONECANPAY',
475
- 0x82: 'SIGHASH_NONE | ANYONECANPAY',
476
- 0x83: 'SIGHASH_SINGLE | ANYONECANPAY'
477
- };
478
-
479
- logSubHeader('Available SIGHASH Types');
480
-
481
- Object.entries(sighashTypes).forEach(([flag, name]) => {
482
- log(`${flag}: ${name}`, 'info');
483
- });
484
-
485
- log('Most common: SIGHASH_ALL (0x01) - signs all inputs and outputs', 'success');
486
- }
487
-
488
- /**
489
- * Feature 4: UTXO Generator
490
- */
491
- function generateUTXO(wif = null, amount = 100000, network = 'livenet') {
492
- logHeader('Generating Mock UTXO');
493
-
494
- try {
495
- // Generate or use provided private key
496
- let privateKey;
497
- if (wif) {
498
- privateKey = bsv.PrivateKey.fromWIF(wif);
499
- log('Using provided private key', 'info');
500
- } else {
501
- privateKey = new bsv.PrivateKey(undefined, network);
502
- log('Generated new random private key', 'info');
503
- }
504
-
505
- const address = privateKey.toAddress(network);
506
- const script = bsv.Script.buildPublicKeyHashOut(address);
507
-
508
- // Create mock UTXO
509
- currentUTXO = {
510
- txId: 'mock_utxo_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9),
511
- outputIndex: 0,
512
- address: address.toString(),
513
- script: script.toString(),
514
- satoshis: amount,
515
- privateKey: privateKey,
516
- network: network
517
- };
518
-
519
- log('Mock UTXO generated successfully!', 'success');
520
- log(`UTXO ID: ${currentUTXO.txId}:${currentUTXO.outputIndex}`, 'info');
521
- log(`Address: ${currentUTXO.address}`, 'info');
522
- log(`Value: ${currentUTXO.satoshis} satoshis`, 'info');
523
- log(`Network: ${currentUTXO.network}`, 'info');
524
- log(`Private Key (WIF): ${currentUTXO.privateKey.toWIF()}`, 'info');
525
-
526
- return currentUTXO;
527
-
528
- } catch (error) {
529
- log(`UTXO generation failed: ${error.message}`, 'error');
530
- return null;
531
- }
532
- }
533
-
534
- function createSpendingTx() {
535
- if (!currentUTXO) {
536
- log('No UTXO available. Please generate a UTXO first.', 'error');
537
- return;
538
- }
539
-
540
- logHeader('Creating Spending Transaction');
541
-
542
- try {
543
- const recipientAddress = '1BitcoinEaterAddressDontSendf59kuE'; // Burn address for demo
544
- const fee = 1000;
545
- const outputAmount = currentUTXO.satoshis - fee;
546
-
547
- if (outputAmount <= 0) {
548
- throw new Error('Insufficient funds for transaction fee');
549
- }
550
-
551
- const tx = new bsv.Transaction()
552
- .from(currentUTXO)
553
- .to(recipientAddress, outputAmount)
554
- .sign(currentUTXO.privateKey);
555
-
556
- log('Spending transaction created!', 'success');
557
- log(`Transaction ID: ${tx.id}`, 'info');
558
- log(`Input: ${currentUTXO.satoshis} satoshis`, 'info');
559
- log(`Output: ${outputAmount} satoshis`, 'info');
560
- log(`Fee: ${fee} satoshis`, 'info');
561
- log(`Transaction size: ${tx.toString().length / 2} bytes`, 'info');
562
-
563
- console.log(chalk.green('\nRaw Transaction:'));
564
- console.log(chalk.white(tx.toString().substring(0, 100) + '...'));
565
-
566
- return tx;
567
-
568
- } catch (error) {
569
- log(`Spending transaction failed: ${error.message}`, 'error');
570
- return null;
571
- }
572
- }
573
-
574
- function showUTXODetails() {
575
- if (!currentUTXO) {
576
- log('No UTXO available. Please generate a UTXO first.', 'error');
577
- return;
578
- }
579
-
580
- logHeader('Detailed UTXO Information');
581
-
582
- console.log(chalk.green('\nUTXO Details:'));
583
- console.log(chalk.white(`Transaction ID: ${currentUTXO.txId}`));
584
- console.log(chalk.white(`Output Index: ${currentUTXO.outputIndex}`));
585
- console.log(chalk.white(`Address: ${currentUTXO.address}`));
586
- console.log(chalk.white(`Value: ${currentUTXO.satoshis} satoshis (${(currentUTXO.satoshis / 100000000).toFixed(8)} BSV)`));
587
- console.log(chalk.white(`Network: ${currentUTXO.network}`));
588
-
589
- console.log(chalk.green('\nScript Details:'));
590
- console.log(chalk.white(`Script ASM: ${currentUTXO.script}`));
591
- console.log(chalk.white(`Script Size: ${Buffer.from(currentUTXO.script, 'hex').length} bytes`));
592
-
593
- console.log(chalk.green('\nPrivate Key:'));
594
- console.log(chalk.white(`WIF: ${currentUTXO.privateKey.toWIF()}`));
595
- console.log(chalk.white(`Hex: ${currentUTXO.privateKey.toString()}`));
596
- console.log(chalk.white(`Compressed: ${currentUTXO.privateKey.compressed}`));
597
-
598
- console.log(chalk.green('\nAddress Details:'));
599
- console.log(chalk.white(`Hash160: ${bsv.Address.fromString(currentUTXO.address).hashBuffer.toString('hex')}`));
600
- console.log(chalk.white(`Version: ${bsv.Address.fromString(currentUTXO.address).network.pubkeyhash}`));
601
- }
602
-
603
- /**
604
- * Feature 5: Script Tools
605
- */
606
- function buildScript(asmCode, scriptType = 'custom') {
607
- logHeader('Building Script');
608
-
609
- try {
610
- if (!asmCode) {
611
- throw new Error('Please provide script ASM code');
612
- }
613
-
614
- const script = bsv.Script.fromASM(asmCode);
615
-
616
- log('Script built successfully!', 'success');
617
- log(`Script type: ${scriptType}`, 'info');
618
- log(`Script size: ${script.toBuffer().length} bytes`, 'info');
619
- log(`Script hex: ${script.toBuffer().toString('hex')}`, 'info');
620
-
621
- console.log(chalk.green('\nScript ASM:'));
622
- console.log(chalk.white(script.toString()));
623
-
624
- // Analyze script opcodes
625
- const opcodes = script.chunks.map(chunk => {
626
- if (chunk.opcodenum !== undefined) {
627
- return `OP_${bsv.Opcode.reverseMap[chunk.opcodenum] || chunk.opcodenum}`;
628
- } else if (chunk.buf) {
629
- return `DATA(${chunk.buf.length} bytes)`;
630
- }
631
- return 'UNKNOWN';
632
- });
633
-
634
- log(`Opcodes: ${opcodes.join(', ')}`, 'info');
635
-
636
- return script;
637
-
638
- } catch (error) {
639
- log(`Script building failed: ${error.message}`, 'error');
640
- return null;
641
- }
642
- }
643
-
644
- function analyzeScript(asmCode) {
645
- if (!asmCode) {
646
- log('Please provide script ASM code first.', 'error');
647
- return;
648
- }
649
-
650
- logHeader('Analyzing Script');
651
-
652
- try {
653
- const script = bsv.Script.fromASM(asmCode);
654
-
655
- // Script analysis
656
- const analysis = {
657
- size: script.toBuffer().length,
658
- chunks: script.chunks.length,
659
- isPushOnly: script.isPushOnly(),
660
- isStandard: true, // Simplified check
661
- hasTimelock: asmCode.includes('CHECKLOCKTIMEVERIFY') || asmCode.includes('CHECKSEQUENCEVERIFY'),
662
- hasMultisig: asmCode.includes('CHECKMULTISIG'),
663
- hasHash: asmCode.includes('HASH160') || asmCode.includes('HASH256'),
664
- complexity: 'Medium' // Simplified assessment
665
- };
666
-
667
- logSubHeader('Script Analysis Results');
668
- log(`Size: ${analysis.size} bytes`, 'info');
669
- log(`Chunks: ${analysis.chunks}`, 'info');
670
- log(`Push-only: ${analysis.isPushOnly ? 'Yes' : 'No'}`, 'info');
671
- log(`Standard: ${analysis.isStandard ? 'Yes' : 'No'}`, 'info');
672
- log(`Has timelock: ${analysis.hasTimelock ? 'Yes' : 'No'}`, 'info');
673
- log(`Has multisig: ${analysis.hasMultisig ? 'Yes' : 'No'}`, 'info');
674
- log(`Has hash ops: ${analysis.hasHash ? 'Yes' : 'No'}`, 'info');
675
- log(`Complexity: ${analysis.complexity}`, 'info');
676
-
677
- // Fee estimation
678
- const feePerByte = 1; // satoshis per byte
679
- const estimatedFee = analysis.size * feePerByte;
680
- log(`Estimated fee: ${estimatedFee} satoshis (at ${feePerByte} sat/byte)`, 'info');
681
-
682
- return analysis;
683
-
684
- } catch (error) {
685
- log(`Script analysis failed: ${error.message}`, 'error');
686
- return null;
687
- }
688
- }
689
-
690
- /**
691
- * Interactive CLI Functions
692
- */
693
- function showMainMenu() {
694
- console.log(chalk.cyan('\nšŸ“‹ Available Commands:'));
695
- console.log(chalk.white(' basics - Load library and run basic tests'));
696
- console.log(chalk.white(' covenant - Covenant builder demo'));
697
- console.log(chalk.white(' preimage - Preimage parser demo'));
698
- console.log(chalk.white(' utxo - UTXO generator demo'));
699
- console.log(chalk.white(' scripts - Script tools demo'));
700
- console.log(chalk.white(' examples - Show real-world use cases'));
701
- console.log(chalk.white(' help - Show this help menu'));
702
- console.log(chalk.white(' exit - Exit the demo'));
703
- console.log(chalk.cyan('─'.repeat(60)));
704
- }
705
-
706
- function showExamples() {
707
- logHeader('Real-World Use Cases');
708
-
709
- console.log(chalk.green('\nšŸ¦ Escrow Contracts'));
710
- console.log(chalk.white('Multi-party escrow with timeout conditions'));
711
- console.log(chalk.gray('- Buyer and seller can complete transaction normally'));
712
- console.log(chalk.gray('- If dispute, buyer+arbiter or seller+arbiter can resolve'));
713
- console.log(chalk.gray('- Includes timeout clause for refund after 30 days'));
714
-
715
- console.log(chalk.green('\nā° Time-locked Payments'));
716
- console.log(chalk.white('Payments that unlock after specific time'));
717
- console.log(chalk.gray('- Uses preimage validation instead of OP_CHECKLOCKTIMEVERIFY'));
718
- console.log(chalk.gray('- Validates nLockTime field from BIP-143 preimage'));
719
- console.log(chalk.gray('- SmartLedger-BSV OP_PUSH_TX methods'));
720
-
721
- console.log(chalk.green('\nšŸ”„ Recurring Payments'));
722
- console.log(chalk.white('Automated recurring payment covenants'));
723
- console.log(chalk.gray('- Self-perpetuating contract'));
724
- console.log(chalk.gray('- Fixed payment amounts and intervals'));
725
- console.log(chalk.gray('- Automatic recipient payment'));
726
-
727
- console.log(chalk.green('\nšŸŽ² Gaming Contracts'));
728
- console.log(chalk.white('Provably fair gaming and betting'));
729
- console.log(chalk.gray('- Commit-reveal schemes for fairness'));
730
- console.log(chalk.gray('- Automatic payout based on results'));
731
- console.log(chalk.gray('- Time limits for player actions'));
732
- }
733
-
734
- function processCommand(command) {
735
- const cmd = command.trim().toLowerCase();
736
- const args = cmd.split(' ');
737
-
738
- switch (args[0]) {
739
- case 'basics':
740
- loadLibrary();
741
- showFeatures();
742
- runBasicTests();
743
- break;
744
-
745
- case 'covenant':
746
- if (args[1] === 'generate') {
747
- const type = args[2] || 'simple';
748
- const amount = parseInt(args[3]) || 100000;
749
- generateCovenant(type, amount);
750
- } else if (args[1] === 'test') {
751
- testCovenant();
752
- } else if (args[1] === 'show') {
753
- showCovenantScript();
754
- } else {
755
- console.log(chalk.cyan('\nCovenant Commands:'));
756
- console.log(chalk.white(' covenant generate [type] [amount] - Generate covenant (simple/timelock/multisig/conditional)'));
757
- console.log(chalk.white(' covenant test - Test current covenant'));
758
- console.log(chalk.white(' covenant show - Show covenant script'));
759
- }
760
- break;
761
-
762
- case 'preimage':
763
- if (args[1] === 'sample') {
764
- generateSampleTx();
765
- } else if (args[1] === 'parse') {
766
- // Would need tx hex input in real scenario
767
- log('Use: preimage sample first to generate a transaction', 'info');
768
- } else if (args[1] === 'sighash') {
769
- extractSighash();
770
- } else {
771
- console.log(chalk.cyan('\nPreimage Commands:'));
772
- console.log(chalk.white(' preimage sample - Generate sample transaction'));
773
- console.log(chalk.white(' preimage sighash - Show SIGHASH information'));
774
- }
775
- break;
776
-
777
- case 'utxo':
778
- if (args[1] === 'generate') {
779
- const amount = parseInt(args[2]) || 100000;
780
- generateUTXO(null, amount);
781
- } else if (args[1] === 'spend') {
782
- createSpendingTx();
783
- } else if (args[1] === 'show') {
784
- showUTXODetails();
785
- } else {
786
- console.log(chalk.cyan('\nUTXO Commands:'));
787
- console.log(chalk.white(' utxo generate [amount] - Generate mock UTXO'));
788
- console.log(chalk.white(' utxo spend - Create spending transaction'));
789
- console.log(chalk.white(' utxo show - Show UTXO details'));
790
- }
791
- break;
792
-
793
- case 'scripts':
794
- if (args[1] === 'build') {
795
- const defaultASM = 'OP_DUP OP_HASH160 OP_PUSHDATA1 0x14 0x1234567890123456789012345678901234567890 OP_EQUALVERIFY OP_CHECKSIG';
796
- buildScript(defaultASM);
797
- } else if (args[1] === 'analyze') {
798
- const defaultASM = 'OP_DUP OP_HASH160 OP_PUSHDATA1 0x14 0x1234567890123456789012345678901234567890 OP_EQUALVERIFY OP_CHECKSIG';
799
- analyzeScript(defaultASM);
800
- } else {
801
- console.log(chalk.cyan('\nScript Commands:'));
802
- console.log(chalk.white(' scripts build - Build sample P2PKH script'));
803
- console.log(chalk.white(' scripts analyze - Analyze sample P2PKH script'));
804
- }
805
- break;
806
-
807
- case 'examples':
808
- showExamples();
809
- break;
810
-
811
- case 'help':
812
- showMainMenu();
813
- break;
814
-
815
- case 'exit':
816
- case 'quit':
817
- console.log(chalk.green('\nšŸ‘‹ Thanks for using SmartLedger-BSV! Happy coding!'));
818
- process.exit(0);
819
- break;
820
-
821
- case '':
822
- // Empty command, do nothing
823
- break;
824
-
825
- default:
826
- log(`Unknown command: ${args[0]}. Type 'help' for available commands.`, 'warning');
827
- break;
828
- }
829
- }
830
-
831
- /**
832
- * Main Function
833
- */
834
- function main() {
835
- // Check for command line arguments
836
- const args = process.argv.slice(2);
837
-
838
- if (args.includes('--help') || args.includes('-h')) {
839
- console.log(chalk.cyan('\nSmartLedger-BSV Smart Contract Demo (Node.js)\n'));
840
- console.log(chalk.white('Usage:'));
841
- console.log(chalk.white(' node smart_contract_demo.js - Interactive mode'));
842
- console.log(chalk.white(' node smart_contract_demo.js --feature basics - Run basics demo'));
843
- console.log(chalk.white(' node smart_contract_demo.js --feature covenant - Run covenant demo'));
844
- console.log(chalk.white(' node smart_contract_demo.js --feature preimage - Run preimage demo'));
845
- console.log(chalk.white(' node smart_contract_demo.js --feature utxo - Run UTXO demo'));
846
- console.log(chalk.white(' node smart_contract_demo.js --feature scripts - Run scripts demo'));
847
- console.log(chalk.white(' node smart_contract_demo.js --help - Show this help'));
848
- process.exit(0);
849
- }
850
-
851
- // Check for specific feature demo
852
- const featureIndex = args.indexOf('--feature');
853
- if (featureIndex !== -1 && args[featureIndex + 1]) {
854
- const feature = args[featureIndex + 1];
855
- console.log(HEADER);
856
- processCommand(feature);
857
- process.exit(0);
858
- }
859
-
860
- // Interactive mode
861
- console.log(HEADER);
862
- log('Welcome to SmartLedger-BSV Smart Contract Demo!', 'success');
863
- log('Type "help" to see available commands or "basics" to start.', 'info');
864
-
865
- showMainMenu();
866
-
867
- rl.prompt();
868
-
869
- rl.on('line', (input) => {
870
- processCommand(input);
871
- rl.prompt();
872
- }).on('close', () => {
873
- console.log(chalk.green('\nšŸ‘‹ Thanks for using SmartLedger-BSV! Happy coding!'));
874
- process.exit(0);
875
- });
876
- }
877
-
878
- // Handle errors gracefully
879
- process.on('uncaughtException', (error) => {
880
- log(`Uncaught exception: ${error.message}`, 'error');
881
- process.exit(1);
882
- });
883
-
884
- process.on('unhandledRejection', (reason, promise) => {
885
- log(`Unhandled rejection at ${promise}: ${reason}`, 'error');
886
- process.exit(1);
887
- });
888
-
889
- // Run the demo
890
- if (require.main === module) {
891
- main();
892
- }
893
-
894
- module.exports = {
895
- loadLibrary,
896
- showFeatures,
897
- runBasicTests,
898
- generateCovenant,
899
- testCovenant,
900
- showCovenantScript,
901
- generateSampleTx,
902
- parsePreimage,
903
- extractSighash,
904
- generateUTXO,
905
- createSpendingTx,
906
- showUTXODetails,
907
- buildScript,
908
- analyzeScript,
909
- showExamples
910
- };