smartledger-bsv 3.3.5 → 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 (126) hide show
  1. package/CHANGELOG.md +400 -0
  2. package/README.md +235 -80
  3. package/SECURITY.md +88 -0
  4. package/anchor-entry.js +1 -0
  5. package/bin/cli.js +354 -0
  6. package/bsv-anchor.min.js +12 -0
  7. package/bsv-covenant.min.js +8 -8
  8. package/bsv-didweb.min.js +12 -0
  9. package/bsv-gdaf.min.js +9 -9
  10. package/bsv-ltp.min.js +9 -9
  11. package/bsv-mnemonic.min.js +2 -2
  12. package/bsv-shamir.min.js +3 -3
  13. package/bsv-smartcontract.min.js +9 -9
  14. package/bsv-statuslist.min.js +18 -0
  15. package/bsv-vcjwt.min.js +12 -0
  16. package/bsv.bundle.js +9 -9
  17. package/bsv.d.ts +486 -9
  18. package/bsv.min.js +8 -8
  19. package/build/webpack.anchor.config.js +17 -0
  20. package/build/webpack.didweb.config.js +17 -0
  21. package/build/webpack.statuslist.config.js +17 -0
  22. package/build/webpack.vcjwt.config.js +17 -0
  23. package/didweb-entry.js +1 -0
  24. package/docs/COVENANT_DEVELOPMENT_RESOLVED.md +2 -2
  25. package/docs/MODULE_REFERENCE_COMPLETE.md +61 -58
  26. package/docs/advanced/LEGAL_TOKEN_PROTOCOL.md +3 -3
  27. package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
  28. package/docs/getting-started/INSTALLATION.md +30 -30
  29. package/docs/getting-started/QUICK_START.md +18 -18
  30. package/docs/migration/FROM_BSV_1_5_6.md +16 -10
  31. package/docs/technical/roadmap.md +3 -3
  32. package/gdaf-entry.js +1 -2
  33. package/index.js +68 -9
  34. package/lib/anchor/index.js +102 -0
  35. package/lib/browser-utxo-manager-es5.js +11 -4
  36. package/lib/browser-utxo-manager.js +15 -8
  37. package/lib/didweb/index.js +177 -0
  38. package/lib/ltp/claim.js +1 -0
  39. package/lib/ltp/obligation.js +1 -0
  40. package/lib/ltp/registry.js +2 -0
  41. package/lib/ltp/right.js +1 -0
  42. package/lib/smart_contract/covenant.js +10 -1
  43. package/lib/smartutxo.js +20 -12
  44. package/lib/statuslist/index.js +164 -0
  45. package/lib/transaction/transaction.js +8 -1
  46. package/lib/util/_.js +7 -1
  47. package/lib/vcjwt/index.js +189 -0
  48. package/ltp-entry.js +1 -2
  49. package/package.json +21 -15
  50. package/statuslist-entry.js +1 -0
  51. package/utilities/blockchain-state.js +32 -23
  52. package/vcjwt-entry.js +1 -0
  53. package/demos/README.md +0 -188
  54. package/demos/architecture_demo.js +0 -247
  55. package/demos/browser-test.html +0 -1208
  56. package/demos/bsv_wallet_demo.js +0 -242
  57. package/demos/complete_ltp_demo.js +0 -511
  58. package/demos/debug_tools_demo.js +0 -87
  59. package/demos/demo_features.js +0 -123
  60. package/demos/easy_interface_demo.js +0 -109
  61. package/demos/ecies_demo.js +0 -182
  62. package/demos/gdaf_core_test.js +0 -131
  63. package/demos/gdaf_demo.js +0 -237
  64. package/demos/ltp_demo.js +0 -361
  65. package/demos/ltp_primitives_demo.js +0 -403
  66. package/demos/message_demo.js +0 -209
  67. package/demos/preimage_separation_demo.js +0 -383
  68. package/demos/script_helper_demo.js +0 -289
  69. package/demos/security_demo.js +0 -287
  70. package/demos/shamir_demo.js +0 -121
  71. package/demos/simple_demo.js +0 -204
  72. package/demos/simple_p2pkh_demo.js +0 -169
  73. package/demos/simple_utxo_preimage_demo.js +0 -196
  74. package/demos/smart_contract_demo.html +0 -1347
  75. package/demos/smart_contract_demo.js +0 -910
  76. package/demos/utxo_generator_demo.js +0 -244
  77. package/demos/validation_pipeline_demo.js +0 -155
  78. package/demos/web3keys.html +0 -740
  79. package/examples/README.md +0 -200
  80. package/examples/basic/transaction-creation.js +0 -534
  81. package/examples/basic/transaction_signature_api_gap.js +0 -178
  82. package/examples/complete_workflow_demo.js +0 -783
  83. package/examples/covenants/advanced_covenant_demo.js +0 -219
  84. package/examples/covenants/covenant_interface_demo.js +0 -270
  85. package/examples/covenants/covenant_manual_signature_resolved.js +0 -212
  86. package/examples/covenants/covenant_signature_template.js +0 -117
  87. package/examples/covenants2/covenant_bidirectional_example.js +0 -262
  88. package/examples/covenants2/covenant_utils_demo.js +0 -120
  89. package/examples/covenants2/preimage_covenant_utils.js +0 -287
  90. package/examples/covenants2/production_integration.js +0 -256
  91. package/examples/data/covenant_utxos.json +0 -28
  92. package/examples/data/utxos.json +0 -26
  93. package/examples/definitive_working_demo.js +0 -261
  94. package/examples/final_working_contracts.js +0 -338
  95. package/examples/preimage/README.md +0 -178
  96. package/examples/preimage/extract_preimage_bidirectional.js +0 -421
  97. package/examples/preimage/generate_sample_preimage.js +0 -208
  98. package/examples/preimage/generate_sighash_examples.js +0 -152
  99. package/examples/preimage/parse_preimage.js +0 -117
  100. package/examples/preimage/test_preimage_extractor.js +0 -53
  101. package/examples/preimage/test_varint_extraction.js +0 -95
  102. package/examples/scripts/custom_script_helper_example.js +0 -273
  103. package/examples/scripts/custom_script_signature_test.js +0 -344
  104. package/examples/scripts/script_interpreter.js +0 -193
  105. package/examples/smart_contract/complete_workflow_demo.js +0 -343
  106. package/examples/smart_contract/covenant_builder_demo.js +0 -176
  107. package/examples/smart_contract/script_testing_integration.js +0 -198
  108. package/examples/smart_contract_templates.js +0 -718
  109. package/examples/working_smart_contracts.js +0 -348
  110. package/lib/smart_contract/test_integration.js +0 -269
  111. package/tests/browser-compatibility/README.md +0 -35
  112. package/tests/browser-compatibility/test-cdn-vs-local.html +0 -186
  113. package/tests/browser-compatibility/test-pbkdf2.html +0 -51
  114. package/tests/bundle-completeness-test.html +0 -131
  115. package/tests/bundle-demo.html +0 -476
  116. package/tests/smartcontract-test.html +0 -239
  117. package/tests/standalone-modules-test.html +0 -260
  118. package/tests/test.html +0 -612
  119. package/tests/test_builtin_verify.js +0 -117
  120. package/tests/test_debug_integration.js +0 -71
  121. package/tests/test_ecdsa_little.js +0 -70
  122. package/tests/test_shamir.js +0 -221
  123. package/tests/test_smartverify_der.js +0 -110
  124. package/tests/test_standalone_shamir.html +0 -83
  125. package/tests/unpkg-demo.html +0 -194
  126. package/utilities/blockchain-state.json +0 -118565
@@ -1,169 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Simple P2PKH Self-Send Demo
5
- *
6
- * Creates a simple transaction sending 100 satoshis to ourselves
7
- * and returning the change to ourselves - the most basic BSV transaction.
8
- */
9
-
10
- // Configuration
11
- const config = {
12
- feePerKb: 10 // 10 satoshis per kilobyte
13
- };
14
-
15
- const bsv = require('../index.js');
16
-
17
- console.log('💳 Simple P2PKH Self-Send Demo');
18
- console.log('===============================\n');
19
-
20
- console.log('This demo shows the simplest possible BSV transaction:');
21
- console.log('• Send 100 satoshis to ourselves');
22
- console.log('• Return change to ourselves');
23
- console.log('• Uses standard P2PKH (Pay-to-Public-Key-Hash)');
24
- console.log('• Minimal transaction overhead\n');
25
-
26
- const privateKey = new bsv.PrivateKey('L1aW4aubDFB7yfras2S1mN3bqg9nwySY8nkoLmJebSLD5BWv3ENZ');
27
- const address = privateKey.toAddress().toString();
28
-
29
- console.log('📝 Transaction Details:');
30
- console.log('======================');
31
- console.log(`Private Key: ${privateKey.toString()}`);
32
- console.log(`Address: ${address}`);
33
- console.log(`Self-send Amount: 100 satoshis`);
34
- console.log(`Fee Rate: ${config.feePerKb} sats/KB`);
35
- console.log(`Transaction Type: P2PKH → P2PKH\n`);
36
-
37
- // Create a realistic mock UTXO (what we might have from previous transactions)
38
- const mockUTXO = {
39
- txid: '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
40
- vout: 0,
41
- address: address,
42
- satoshis: 50000, // 0.0005 BSV
43
- script: bsv.Script.buildPublicKeyHashOut(address).toHex()
44
- };
45
-
46
- console.log('💰 Available UTXO:');
47
- console.log(` TXID: ${mockUTXO.txid}`);
48
- console.log(` Output: ${mockUTXO.vout}`);
49
- console.log(` Amount: ${mockUTXO.satoshis} satoshis (${mockUTXO.satoshis / 100000000} BSV)`);
50
- console.log(` Script: P2PKH to ${address}\n`);
51
-
52
- try {
53
- console.log('🔨 Building Transaction:');
54
- console.log('========================');
55
-
56
- // Create the transaction - send 100 sats to ourselves
57
- const transaction = new bsv.Transaction()
58
- .from(mockUTXO) // Input: our UTXO
59
- .to(address, 100) // Output 1: 100 sats to ourselves
60
- .change(address) // Output 2: change back to ourselves
61
- .feePerKb(config.feePerKb || 10) // Set fee rate: 10 sats per KB
62
- .sign(privateKey); // Sign with our private key
63
-
64
- console.log('✅ Transaction built successfully!');
65
- console.log(`Transaction ID: ${transaction.id}`);
66
- console.log(`Size: ${transaction.toBuffer().length} bytes`);
67
- console.log(`Fee: ${transaction.getFee()} satoshis\n`);
68
-
69
- // Show transaction structure
70
- console.log('🔍 Transaction Structure:');
71
- console.log('=========================');
72
- console.log(`Inputs (${transaction.inputs.length}):`);
73
- transaction.inputs.forEach((input, i) => {
74
- console.log(` Input ${i}: ${input.prevTxId}:${input.outputIndex} (${mockUTXO.satoshis} sats)`);
75
- });
76
-
77
- console.log(`Outputs (${transaction.outputs.length}):`);
78
- transaction.outputs.forEach((output, i) => {
79
- const addr = output.script.toAddress().toString();
80
- console.log(` Output ${i}: ${addr} (${output.satoshis} sats)`);
81
- });
82
-
83
- const totalOutput = transaction.outputs.reduce((sum, output) => sum + output.satoshis, 0);
84
- console.log(`Total Output: ${totalOutput} sats`);
85
- console.log(`Fee Paid: ${mockUTXO.satoshis - totalOutput} sats\n`);
86
-
87
- // Validation
88
- console.log('🔐 Validation Results:');
89
- console.log('======================');
90
-
91
- const isValid = transaction.verify();
92
- console.log(`Basic BSV Validation: ${isValid ? '✅ VALID' : '❌ INVALID'}`);
93
-
94
- // Test signature verification if available
95
- if (bsv.SmartVerify) {
96
- let smartVerifyPassed = true;
97
-
98
- for (let i = 0; i < transaction.inputs.length; i++) {
99
- try {
100
- const input = transaction.inputs[i];
101
- const signature = input.script.chunks[0]?.buf;
102
- const publicKey = input.script.chunks[1]?.buf;
103
-
104
- if (signature && publicKey && input.output) {
105
- // Get the previous output script (subscript for sighash)
106
- const subscript = input.output.script;
107
- const satoshisBN = new bsv.crypto.BN(input.output.satoshis);
108
-
109
- // Calculate the signature hash with proper parameters
110
- const sighash = transaction.sighash(i, undefined, subscript, satoshisBN);
111
-
112
- const sigBuffer = signature.slice(0, -1); // Remove sighash flag
113
- const pubkeyObj = new bsv.PublicKey(publicKey);
114
-
115
- // Parse signature with hashtype for proper verification
116
- const parsedSig = bsv.crypto.Signature.fromDER(sigBuffer);
117
- parsedSig.nhashtype = signature[signature.length - 1]; // Set the hashtype
118
-
119
- // Use transaction's built-in verification (which handles endianness correctly)
120
- const txVerifyValid = transaction.verifySignature(parsedSig, pubkeyObj, i, subscript, satoshisBN);
121
- const isCanonical = bsv.SmartVerify.isCanonical(sigBuffer);
122
-
123
- console.log(`Input ${i} Transaction Verify: ${txVerifyValid ? '✅ VALID' : '❌ INVALID'}`);
124
- console.log(`Input ${i} Canonical: ${isCanonical ? '✅ YES' : '❌ NO'}`);
125
- console.log(`Input ${i} SigHash: ${sighash.toString('hex').substring(0, 16)}...`);
126
- console.log(`Input ${i} Signature: ${parsedSig.r.toString('hex').substring(0, 16)}...`);
127
-
128
- if (!txVerifyValid || !isCanonical) {
129
- smartVerifyPassed = false;
130
- }
131
- } else {
132
- console.log(`Input ${i}: Missing signature, public key, or output information`);
133
- smartVerifyPassed = false;
134
- }
135
- } catch (error) {
136
- console.log(`Input ${i} Error: ${error.message}`);
137
- smartVerifyPassed = false;
138
- }
139
- }
140
-
141
- console.log(`Transaction Verify Overall: ${smartVerifyPassed ? '✅ PASSED' : '❌ FAILED'}`);
142
- }
143
-
144
- // Miner validation if available
145
- if (bsv.SmartMiner) {
146
- const miner = new bsv.SmartMiner(bsv, { validateScripts: true });
147
- const minerAccepted = miner.acceptTransaction(transaction);
148
- console.log(`Miner Simulation: ${minerAccepted ? '✅ ACCEPTED' : '❌ REJECTED'}`);
149
- }
150
-
151
- console.log('\n📋 Summary:');
152
- console.log('===========');
153
- console.log('Transaction Type: Simple P2PKH self-send');
154
- console.log('Input: 1 UTXO from our address');
155
- console.log('Output 1: 100 sats to our address');
156
- console.log('Output 2: Change back to our address');
157
- console.log('Security: All signatures verified and canonical');
158
- console.log('Status: Ready for broadcast to BSV network\n');
159
-
160
- console.log('💡 This is the most basic BSV transaction possible:');
161
- console.log(' • Standard P2PKH inputs and outputs');
162
- console.log(' • Self-contained (no external dependencies)');
163
- console.log(' • Minimal fees and overhead');
164
- console.log(' • Perfect for testing and development');
165
-
166
- } catch (error) {
167
- console.error('❌ Demo failed:', error.message);
168
- console.error('Stack:', error.stack);
169
- }
@@ -1,196 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Simple UTXO Generator + Preimage Field Separation Demo
5
- *
6
- * This focused example demonstrates:
7
- * 1. Generating real UTXOs with the UTXOGenerator
8
- * 2. Creating a transaction and extracting the BIP-143 preimage
9
- * 3. Separating the preimage into each individual field with clear visualization
10
- */
11
-
12
- // Workaround for Node.js environment with minified BSV
13
- global.window = global.window || {};
14
- global.window.crypto = global.window.crypto || require('crypto').webcrypto || require('crypto');
15
-
16
- const bsv = require('../bsv.min.js');
17
- const SmartContract = bsv.SmartContract;
18
-
19
- console.log('🔬 UTXO Generator + Preimage Field Separation');
20
- console.log('='.repeat(60));
21
-
22
- async function simpleDemo() {
23
- // 1. Generate mock UTXO for preimage demonstration
24
- console.log('\n📦 Creating Mock UTXO for Demo:');
25
- console.log('-'.repeat(45));
26
-
27
- const demoPrivateKey = new bsv.PrivateKey();
28
- const demoAddress = demoPrivateKey.toAddress();
29
-
30
- const utxo = {
31
- txid: 'fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210',
32
- vout: 0,
33
- satoshis: 100000,
34
- address: demoAddress.toString(),
35
- script: bsv.Script.buildPublicKeyHashOut(demoAddress).toHex(),
36
- scriptPubKey: bsv.Script.buildPublicKeyHashOut(demoAddress).toHex()
37
- };
38
-
39
- console.log(`✅ Created Mock UTXO:`);
40
- console.log(` TXID: ${utxo.txid}`);
41
- console.log(` VOUT: ${utxo.vout}`);
42
- console.log(` Amount: ${utxo.satoshis.toLocaleString()} satoshis`);
43
- console.log(` Address: ${utxo.address}`);
44
- console.log(` Script: ${utxo.script}`);
45
-
46
- // 2. Create transaction and generate preimage
47
- console.log('\n🔨 Creating Transaction & Generating Preimage:');
48
- console.log('-'.repeat(45));
49
-
50
- const privateKey = demoPrivateKey;
51
- const address = demoAddress;
52
-
53
- const tx = new bsv.Transaction()
54
- .from({
55
- txId: utxo.txid,
56
- outputIndex: utxo.vout,
57
- scriptPubKey: utxo.scriptPubKey,
58
- satoshis: utxo.satoshis
59
- })
60
- .to(address, 95000) // Leave some for fees
61
- .sign(privateKey);
62
-
63
- // Generate BIP-143 preimage
64
- const sighashType = bsv.crypto.Signature.SIGHASH_ALL | bsv.crypto.Signature.SIGHASH_FORKID;
65
- const subscript = bsv.Script.buildPublicKeyHashOut(address);
66
- const preimageBuffer = bsv.Transaction.sighash.sighashPreimage(
67
- tx, sighashType, 0, subscript, new bsv.crypto.BN(utxo.satoshis)
68
- );
69
-
70
- console.log(`✅ Transaction: ${tx.id}`);
71
- console.log(`✅ Preimage: ${preimageBuffer.length} bytes`);
72
- console.log(` Full hex: ${preimageBuffer.toString('hex')}`);
73
-
74
- // 3. Use SmartContract Preimage class to separate fields
75
- console.log('\n🔍 Separating Preimage Fields:');
76
- console.log('='.repeat(60));
77
-
78
- const preimage = new SmartContract.Preimage(preimageBuffer.toString('hex'));
79
-
80
- // BIP-143 defines these 10 fields in order
81
- const fieldNames = [
82
- 'version', // 4 bytes - nVersion
83
- 'hashPrevouts', // 32 bytes - hashPrevouts
84
- 'hashSequence', // 32 bytes - hashSequence
85
- 'outpoint', // 36 bytes - outpoint (32 byte hash + 4 byte index)
86
- 'scriptCode', // Variable - scriptCode with length prefix
87
- 'amount', // 8 bytes - value in satoshis
88
- 'sequence', // 4 bytes - nSequence
89
- 'hashOutputs', // 32 bytes - hashOutputs
90
- 'locktime', // 4 bytes - nLockTime
91
- 'sighash' // 4 bytes - sighash flags
92
- ];
93
-
94
- let runningOffset = 0;
95
-
96
- fieldNames.forEach((fieldName, index) => {
97
- const fieldBuffer = preimage.getField(fieldName);
98
- const fieldHex = fieldBuffer.toString('hex');
99
-
100
- console.log(`\n${(index + 1).toString().padStart(2)}. ${fieldName.toUpperCase()}:`);
101
- console.log(` Bytes: ${runningOffset} - ${runningOffset + fieldBuffer.length - 1} (${fieldBuffer.length} bytes)`);
102
- console.log(` Hex: ${fieldHex}`);
103
-
104
- // Interpret the field value for better understanding
105
- switch (fieldName) {
106
- case 'version':
107
- console.log(` Value: Version ${fieldBuffer.readUInt32LE(0)}`);
108
- break;
109
- case 'amount':
110
- // Read 64-bit little-endian integer (compatible with older Node.js)
111
- const low = fieldBuffer.readUInt32LE(0);
112
- const high = fieldBuffer.readUInt32LE(4);
113
- const sats = low + (high * 0x100000000);
114
- console.log(` Value: ${sats} satoshis (${(sats / 100000000).toFixed(8)} BSV)`);
115
- break;
116
- case 'outpoint':
117
- const txid = fieldBuffer.slice(0, 32).reverse().toString('hex');
118
- const vout = fieldBuffer.slice(32).readUInt32LE(0);
119
- console.log(` Value: ${txid}:${vout}`);
120
- break;
121
- case 'sequence':
122
- const seq = fieldBuffer.readUInt32LE(0);
123
- console.log(` Value: ${seq} (0x${seq.toString(16)})`);
124
- break;
125
- case 'locktime':
126
- const locktime = fieldBuffer.readUInt32LE(0);
127
- console.log(` Value: ${locktime} ${locktime < 500000000 ? '(block height)' : '(timestamp)'}`);
128
- break;
129
- case 'sighash':
130
- const sighash = fieldBuffer.readUInt32LE(0);
131
- const flags = [];
132
- if (sighash & 0x01) flags.push('SIGHASH_ALL');
133
- if (sighash & 0x02) flags.push('SIGHASH_NONE');
134
- if (sighash & 0x03) flags.push('SIGHASH_SINGLE');
135
- if (sighash & 0x40) flags.push('SIGHASH_FORKID');
136
- if (sighash & 0x80) flags.push('SIGHASH_ANYONECANPAY');
137
- console.log(` Value: 0x${sighash.toString(16)} (${flags.join(' | ')})`);
138
- break;
139
- case 'scriptCode':
140
- console.log(` Value: P2PKH script (${fieldBuffer.length} bytes)`);
141
- break;
142
- default:
143
- console.log(` Value: 32-byte hash`);
144
- }
145
-
146
- runningOffset += fieldBuffer.length;
147
- });
148
-
149
- // 4. Show extraction strategies
150
- console.log('\n🧪 Testing Different Extraction Strategies:');
151
- console.log('-'.repeat(50));
152
-
153
- const strategies = ['LEFT', 'RIGHT', 'DYNAMIC'];
154
- strategies.forEach(strategy => {
155
- try {
156
- const extracted = preimage.extract(strategy);
157
- console.log(`✅ ${strategy.padEnd(7)}: ${Object.keys(extracted).length} fields extracted`);
158
- } catch (error) {
159
- console.log(`❌ ${strategy.padEnd(7)}: ${error.message}`);
160
- }
161
- });
162
-
163
- // 5. Summary
164
- console.log('\n📊 Summary:');
165
- console.log('-'.repeat(30));
166
- console.log(`✅ UTXOs created: 1`);
167
- console.log(`✅ Transaction built: ${tx.inputs.length} input → ${tx.outputs.length} output`);
168
- console.log(`✅ Preimage generated: ${preimageBuffer.length} bytes`);
169
- console.log(`✅ Fields extracted: ${fieldNames.length} (all BIP-143 fields)`);
170
- console.log(`✅ Total field data: ${runningOffset} bytes`);
171
-
172
- const sighashInfo = preimage.getSighashInfo();
173
- console.log(`✅ SIGHASH analysis: ${sighashInfo.hasZeroHashes ? 'Has zero hashes ⚠️' : 'Clean ✅'}`);
174
-
175
- console.log('\n🎯 Key Takeaways:');
176
- console.log(' • UTXOGenerator creates real, usable UTXOs for testing');
177
- console.log(' • Preimage class extracts all 10 BIP-143 fields perfectly');
178
- console.log(' • Each field has specific meaning and can be interpreted');
179
- console.log(' • Multiple extraction strategies ensure robust parsing');
180
-
181
- return { utxo, transaction: tx, preimage: preimageBuffer, fieldCount: fieldNames.length };
182
- }
183
-
184
- // Run the demo
185
- if (require.main === module) {
186
- simpleDemo()
187
- .then(result => {
188
- console.log('\n🎉 Demo completed successfully!');
189
- })
190
- .catch(error => {
191
- console.error('\n❌ Demo failed:', error.message);
192
- process.exit(1);
193
- });
194
- }
195
-
196
- module.exports = { simpleDemo };