smartledger-bsv 3.0.0 → 3.0.2

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.
@@ -0,0 +1,328 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * šŸ”„ BSV Transaction Examples
5
+ *
6
+ * Demonstrates the complete transaction flow:
7
+ * 1. Create transaction
8
+ * 2. Broadcast to miner
9
+ * 3. Miner validates and processes
10
+ * 4. UTXO set updates
11
+ */
12
+
13
+ const bsv = require('../index.js');
14
+ const fs = require('fs');
15
+ const path = require('path');
16
+
17
+ // Import our utilities
18
+ const {
19
+ loadBlockchainState,
20
+ importWalletFromFile,
21
+ getBlockchainStats
22
+ } = require('./blockchain-state');
23
+ const {
24
+ acceptTransaction,
25
+ getMempoolStatus
26
+ } = require('./miner-simulator');
27
+ const {
28
+ loadConfig,
29
+ updateUTXOFromTransaction
30
+ } = require('./utxo-manager');
31
+
32
+ /**
33
+ * Initialize the blockchain with our test wallet
34
+ */
35
+ async function initializeBlockchain() {
36
+ console.log('šŸš€ Initializing blockchain with test wallet...\n');
37
+
38
+ // Import wallet from wallet.json into blockchain state
39
+ const imported = importWalletFromFile();
40
+
41
+ if (!imported) {
42
+ console.log('āŒ Failed to import wallet. Run wallet-setup.js first!');
43
+ return false;
44
+ }
45
+
46
+ console.log('');
47
+ getBlockchainStats();
48
+ return true;
49
+ }
50
+
51
+ /**
52
+ * Create a simple P2PKH transaction
53
+ */
54
+ function createSimpleTransaction(fromAddress, toAddress, amount, privateKey, utxo) {
55
+ console.log(`\nšŸ’ø Creating P2PKH transaction:`);
56
+ console.log(`From: ${fromAddress}`);
57
+ console.log(`To: ${toAddress}`);
58
+ console.log(`Amount: ${amount} satoshis\n`);
59
+
60
+ try {
61
+ // Create transaction with proper SIGHASH_FORKID
62
+ const tx = new bsv.Transaction()
63
+ .from(utxo)
64
+ .to(toAddress, amount)
65
+ .change(fromAddress)
66
+ .fee(1000) // 1000 sat fee
67
+ .sign(privateKey, bsv.crypto.Signature.SIGHASH_ALL | bsv.crypto.Signature.SIGHASH_FORKID);
68
+
69
+ console.log(`āœ… Transaction created: ${tx.id}`);
70
+ console.log(`Inputs: ${tx.inputs.length}`);
71
+ console.log(`Outputs: ${tx.outputs.length}`);
72
+ console.log(`Fee: ${tx.getFee()} satoshis\n`);
73
+
74
+ return tx;
75
+ } catch (error) {
76
+ console.error('āŒ Error creating transaction:', error.message);
77
+ return null;
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Example 1: Simple P2PKH payment
83
+ */
84
+ async function exampleSimplePayment() {
85
+ console.log('\n' + '='.repeat(80));
86
+ console.log('šŸ“ EXAMPLE 1: Simple P2PKH Payment');
87
+ console.log('='.repeat(80));
88
+
89
+ // Load wallet config
90
+ const config = loadConfig();
91
+ const wallet = config.wallet;
92
+
93
+ // Create recipient address (just generate a new one for demo)
94
+ const recipientKey = new bsv.PrivateKey();
95
+ const recipientAddress = recipientKey.toAddress().toString();
96
+
97
+ console.log(`šŸ‘› Sender: ${wallet.address}`);
98
+ console.log(`šŸŽÆ Recipient: ${recipientAddress}`);
99
+
100
+ // Use the primary UTXO
101
+ const utxo = config.utxo;
102
+ console.log(`šŸ’° Using UTXO: ${utxo.txid}:${utxo.vout} (${utxo.satoshis} sats)`);
103
+
104
+ // Create transaction (send 15,000 sats)
105
+ const amount = 15000;
106
+ const tx = createSimpleTransaction(
107
+ wallet.address,
108
+ recipientAddress,
109
+ amount,
110
+ bsv.PrivateKey.fromWIF(wallet.privateKeyWIF),
111
+ utxo
112
+ );
113
+
114
+ if (!tx) {
115
+ console.log('āŒ Failed to create transaction');
116
+ return;
117
+ }
118
+
119
+ // Broadcast to miner
120
+ console.log('šŸ“” Broadcasting transaction to miner...');
121
+ const result = acceptTransaction(tx);
122
+
123
+ if (result.accepted) {
124
+ console.log('\nšŸŽ‰ Transaction accepted and processed!');
125
+
126
+ // Update local wallet
127
+ updateUTXOFromTransaction(tx, utxo);
128
+
129
+ console.log('\nšŸ“Š Updated blockchain state:');
130
+ getBlockchainStats();
131
+ } else {
132
+ console.log('\nāŒ Transaction rejected by miner');
133
+ console.log('Errors:', result.errors);
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Example 2: Chain multiple transactions
139
+ */
140
+ async function exampleTransactionChain() {
141
+ console.log('\n' + '='.repeat(80));
142
+ console.log('šŸ”— EXAMPLE 2: Transaction Chain');
143
+ console.log('='.repeat(80));
144
+
145
+ const config = loadConfig();
146
+ const wallet = config.wallet;
147
+
148
+ // Find an available UTXO for the second transaction
149
+ const availableUTXOs = config.availableUTXOs || [];
150
+
151
+ if (availableUTXOs.length === 0) {
152
+ console.log('āŒ No available UTXOs for chaining. Run example 1 first.');
153
+ return;
154
+ }
155
+
156
+ // Use the first available UTXO
157
+ const utxo = availableUTXOs[0];
158
+ console.log(`šŸ’° Using UTXO: ${utxo.txid}:${utxo.vout} (${utxo.satoshis} sats)`);
159
+
160
+ // Create another recipient
161
+ const recipientKey = new bsv.PrivateKey();
162
+ const recipientAddress = recipientKey.toAddress().toString();
163
+
164
+ console.log(`šŸ‘› Sender: ${wallet.address}`);
165
+ console.log(`šŸŽÆ Recipient: ${recipientAddress}`);
166
+
167
+ // Create second transaction
168
+ const amount = Math.min(5000, utxo.satoshis - 1000); // Leave room for fee
169
+ const tx = createSimpleTransaction(
170
+ wallet.address,
171
+ recipientAddress,
172
+ amount,
173
+ bsv.PrivateKey.fromWIF(wallet.privateKeyWIF),
174
+ utxo
175
+ );
176
+
177
+ if (!tx) {
178
+ console.log('āŒ Failed to create transaction');
179
+ return;
180
+ }
181
+
182
+ // Broadcast to miner
183
+ console.log('šŸ“” Broadcasting transaction to miner...');
184
+ const result = acceptTransaction(tx);
185
+
186
+ if (result.accepted) {
187
+ console.log('\nšŸŽ‰ Transaction accepted and processed!');
188
+
189
+ // Update local wallet
190
+ updateUTXOFromTransaction(tx, utxo);
191
+
192
+ console.log('\nšŸ“Š Updated blockchain state:');
193
+ getBlockchainStats();
194
+ } else {
195
+ console.log('\nāŒ Transaction rejected by miner');
196
+ console.log('Errors:', result.errors);
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Example 3: Multi-output transaction
202
+ */
203
+ async function exampleMultiOutput() {
204
+ console.log('\n' + '='.repeat(80));
205
+ console.log('šŸŽ­ EXAMPLE 3: Multi-Output Transaction');
206
+ console.log('='.repeat(80));
207
+
208
+ const config = loadConfig();
209
+ const wallet = config.wallet;
210
+
211
+ // Find an available UTXO
212
+ const availableUTXOs = config.availableUTXOs || [];
213
+
214
+ if (availableUTXOs.length === 0) {
215
+ console.log('āŒ No available UTXOs. Run example 1 first.');
216
+ return;
217
+ }
218
+
219
+ // Use the largest available UTXO
220
+ const utxo = availableUTXOs.reduce((max, current) =>
221
+ current.satoshis > max.satoshis ? current : max
222
+ );
223
+
224
+ console.log(`šŸ’° Using UTXO: ${utxo.txid}:${utxo.vout} (${utxo.satoshis} sats)`);
225
+
226
+ // Create multiple recipients
227
+ const recipient1 = new bsv.PrivateKey().toAddress().toString();
228
+ const recipient2 = new bsv.PrivateKey().toAddress().toString();
229
+ const recipient3 = new bsv.PrivateKey().toAddress().toString();
230
+
231
+ console.log(`šŸ‘› Sender: ${wallet.address}`);
232
+ console.log(`šŸŽÆ Recipients: ${recipient1.slice(0, 10)}... ${recipient2.slice(0, 10)}... ${recipient3.slice(0, 10)}...`);
233
+
234
+ try {
235
+ // Create multi-output transaction with proper SIGHASH_FORKID
236
+ const tx = new bsv.Transaction()
237
+ .from(utxo)
238
+ .to(recipient1, 3000)
239
+ .to(recipient2, 4000)
240
+ .to(recipient3, 5000)
241
+ .change(wallet.address)
242
+ .fee(1000)
243
+ .sign(bsv.PrivateKey.fromWIF(wallet.privateKeyWIF), bsv.crypto.Signature.SIGHASH_ALL | bsv.crypto.Signature.SIGHASH_FORKID);
244
+
245
+ console.log(`\nāœ… Multi-output transaction created: ${tx.id}`);
246
+ console.log(`Inputs: ${tx.inputs.length}`);
247
+ console.log(`Outputs: ${tx.outputs.length}`);
248
+ console.log(`Total sent: 12,000 satoshis to 3 recipients`);
249
+
250
+ // Broadcast to miner
251
+ console.log('\nšŸ“” Broadcasting transaction to miner...');
252
+ const result = acceptTransaction(tx);
253
+
254
+ if (result.accepted) {
255
+ console.log('\nšŸŽ‰ Transaction accepted and processed!');
256
+
257
+ // Update local wallet
258
+ updateUTXOFromTransaction(tx, utxo);
259
+
260
+ console.log('\nšŸ“Š Updated blockchain state:');
261
+ getBlockchainStats();
262
+ } else {
263
+ console.log('\nāŒ Transaction rejected by miner');
264
+ console.log('Errors:', result.errors);
265
+ }
266
+ } catch (error) {
267
+ console.error('āŒ Error creating multi-output transaction:', error.message);
268
+ }
269
+ }
270
+
271
+ /**
272
+ * Run all examples
273
+ */
274
+ async function runAllExamples() {
275
+ console.log('šŸš€ BSV Transaction Examples');
276
+ console.log('🌟 Demonstrating complete transaction flow with miner simulation\n');
277
+
278
+ // Initialize blockchain state
279
+ const initialized = await initializeBlockchain();
280
+ if (!initialized) {
281
+ return;
282
+ }
283
+
284
+ // Show initial miner status
285
+ console.log('\nšŸ“Š Initial miner status:');
286
+ getMempoolStatus();
287
+
288
+ // Run examples
289
+ await exampleSimplePayment();
290
+ await new Promise(resolve => setTimeout(resolve, 1000)); // Small delay
291
+
292
+ await exampleTransactionChain();
293
+ await new Promise(resolve => setTimeout(resolve, 1000)); // Small delay
294
+
295
+ await exampleMultiOutput();
296
+
297
+ // Final status
298
+ console.log('\nšŸ“Š Final miner status:');
299
+ getMempoolStatus();
300
+
301
+ console.log('\nšŸŽÆ Examples completed!');
302
+ console.log('Check blockchain-state.json to see the global UTXO set');
303
+ console.log('Check wallet.json to see your local wallet state');
304
+ }
305
+
306
+ // If called directly, run examples
307
+ if (require.main === module) {
308
+ const args = process.argv.slice(2);
309
+
310
+ if (args[0] === '1') {
311
+ initializeBlockchain().then(() => exampleSimplePayment());
312
+ } else if (args[0] === '2') {
313
+ exampleTransactionChain();
314
+ } else if (args[0] === '3') {
315
+ exampleMultiOutput();
316
+ } else {
317
+ runAllExamples();
318
+ }
319
+ }
320
+
321
+ module.exports = {
322
+ initializeBlockchain,
323
+ createSimpleTransaction,
324
+ exampleSimplePayment,
325
+ exampleTransactionChain,
326
+ exampleMultiOutput,
327
+ runAllExamples
328
+ };
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * šŸ”„ BSV UTXO Manager
5
+ *
6
+ * Updates the wallet.json file with new UTXOs after transactions.
7
+ * Tracks which UTXOs are spent and which are available for BSV development.
8
+ */
9
+
10
+ const bsv = require('../index.js');
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+
14
+ function loadConfig() {
15
+ const configPath = path.join(__dirname, 'wallet.json');
16
+ return JSON.parse(fs.readFileSync(configPath, 'utf8'));
17
+ }
18
+
19
+ function saveConfig(config) {
20
+ const configPath = path.join(__dirname, 'wallet.json');
21
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
22
+ console.log('šŸ’¾ Updated wallet.json');
23
+ }
24
+
25
+ function updateUTXOFromTransaction(tx, spentUTXO = null) {
26
+ console.log('šŸ”„ Updating UTXO set from transaction...\n');
27
+
28
+ const config = loadConfig();
29
+
30
+ console.log('šŸ“‹ Transaction Analysis:');
31
+ console.log(`Transaction ID: ${tx.id}`);
32
+ console.log(`Inputs: ${tx.inputs.length}`);
33
+ console.log(`Outputs: ${tx.outputs.length}\n`);
34
+
35
+ // Mark spent UTXO
36
+ if (spentUTXO) {
37
+ console.log('āŒ Spent UTXO:');
38
+ console.log(` TXID: ${spentUTXO.txid}`);
39
+ console.log(` Vout: ${spentUTXO.vout}`);
40
+ console.log(` Amount: ${spentUTXO.satoshis} satoshis\n`);
41
+
42
+ // Add to spent UTXOs list
43
+ if (!config.spentUTXOs) config.spentUTXOs = [];
44
+ config.spentUTXOs.push({
45
+ txid: spentUTXO.txid,
46
+ vout: spentUTXO.vout,
47
+ satoshis: spentUTXO.satoshis,
48
+ spentInTx: tx.id,
49
+ spentAt: new Date().toISOString()
50
+ });
51
+ }
52
+
53
+ // Add new UTXOs from outputs
54
+ const newUTXOs = [];
55
+
56
+ for (let i = 0; i < tx.outputs.length; i++) {
57
+ const output = tx.outputs[i];
58
+ const outputAddress = output.script.toAddress();
59
+
60
+ // Only track UTXOs that go to our wallet address
61
+ if (outputAddress.toString() === config.wallet.address) {
62
+ const newUTXO = {
63
+ txid: tx.id,
64
+ vout: i,
65
+ outputIndex: i,
66
+ script: output.script.toHex(),
67
+ scriptPubKey: output.script.toHex(),
68
+ satoshis: output.satoshis,
69
+ address: outputAddress.toString(),
70
+ createdAt: new Date().toISOString()
71
+ };
72
+
73
+ newUTXOs.push(newUTXO);
74
+
75
+ console.log(`āœ… New UTXO ${i}:`);
76
+ console.log(` TXID: ${newUTXO.txid}`);
77
+ console.log(` Vout: ${newUTXO.vout}`);
78
+ console.log(` Amount: ${newUTXO.satoshis} satoshis`);
79
+ console.log(` Address: ${newUTXO.address}`);
80
+ }
81
+ }
82
+
83
+ // Update config with new UTXOs
84
+ if (!config.availableUTXOs) config.availableUTXOs = [];
85
+ config.availableUTXOs = config.availableUTXOs.concat(newUTXOs);
86
+
87
+ // Update the main UTXO to the largest available UTXO
88
+ if (newUTXOs.length > 0) {
89
+ const largestUTXO = newUTXOs.reduce((max, utxo) =>
90
+ utxo.satoshis > max.satoshis ? utxo : max
91
+ );
92
+
93
+ config.utxo = largestUTXO;
94
+ console.log(`\nšŸŽÆ Primary UTXO updated to: ${largestUTXO.satoshis} satoshis`);
95
+ }
96
+
97
+ // Update metadata
98
+ config.metadata.lastUpdated = new Date().toISOString();
99
+ config.metadata.transactionCount = (config.metadata.transactionCount || 0) + 1;
100
+
101
+ saveConfig(config);
102
+
103
+ return {
104
+ newUTXOs,
105
+ totalValue: newUTXOs.reduce((sum, utxo) => sum + utxo.satoshis, 0),
106
+ config
107
+ };
108
+ }
109
+
110
+ function getAvailableBalance() {
111
+ const config = loadConfig();
112
+
113
+ const balance = config.availableUTXOs
114
+ ? config.availableUTXOs.reduce((sum, utxo) => sum + utxo.satoshis, 0)
115
+ : config.utxo.satoshis;
116
+
117
+ return balance;
118
+ }
119
+
120
+ function listUTXOs() {
121
+ const config = loadConfig();
122
+
123
+ console.log('šŸ’° Current UTXO Set:');
124
+ console.log('═══════════════════════════════════════════\n');
125
+
126
+ console.log('šŸŽÆ Primary UTXO:');
127
+ console.log(` TXID: ${config.utxo.txid}`);
128
+ console.log(` Vout: ${config.utxo.vout}`);
129
+ console.log(` Amount: ${config.utxo.satoshis} satoshis\n`);
130
+
131
+ if (config.availableUTXOs && config.availableUTXOs.length > 0) {
132
+ console.log('šŸ“ All Available UTXOs:');
133
+ config.availableUTXOs.forEach((utxo, index) => {
134
+ console.log(` ${index + 1}. ${utxo.txid}:${utxo.vout} - ${utxo.satoshis} sats`);
135
+ });
136
+ }
137
+
138
+ if (config.spentUTXOs && config.spentUTXOs.length > 0) {
139
+ console.log('\nāŒ Spent UTXOs:');
140
+ config.spentUTXOs.forEach((utxo, index) => {
141
+ console.log(` ${index + 1}. ${utxo.txid}:${utxo.vout} - ${utxo.satoshis} sats (spent in ${utxo.spentInTx})`);
142
+ });
143
+ }
144
+
145
+ const totalBalance = getAvailableBalance();
146
+ console.log(`\nšŸ’° Total Available Balance: ${totalBalance} satoshis`);
147
+
148
+ return config;
149
+ }
150
+
151
+ // If called directly, list current UTXOs
152
+ if (require.main === module) {
153
+ listUTXOs();
154
+ }
155
+
156
+ module.exports = {
157
+ updateUTXOFromTransaction,
158
+ getAvailableBalance,
159
+ listUTXOs,
160
+ loadConfig,
161
+ saveConfig
162
+ };
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * šŸŽÆ BSV Wallet Setup Utility
5
+ *
6
+ * Creates a test wallet with mock UTXO for BSV development and testing.
7
+ * Generates a consistent environment with private keys, addresses, and UTXOs.
8
+ */
9
+
10
+ const bsv = require('../index.js');
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+
14
+ // Import the mock UTXO functionality from mock-utxo-generator.js
15
+ function randomHex(len) {
16
+ const crypto = require('crypto');
17
+ return crypto.randomBytes(len).toString('hex');
18
+ }
19
+
20
+ function createMockTxId() {
21
+ return randomHex(32);
22
+ }
23
+
24
+ function buildP2pkhScriptHex(address) {
25
+ return bsv.Script.buildPublicKeyHashOut(address).toHex();
26
+ }
27
+
28
+ function mkUtxo(privateKey, sats = 100000) {
29
+ const address = privateKey.toAddress().toString();
30
+ const txid = createMockTxId();
31
+ const vout = 0;
32
+ const scriptHex = buildP2pkhScriptHex(address);
33
+
34
+ return {
35
+ txId: txid,
36
+ txid: txid,
37
+ vout: vout,
38
+ outputIndex: vout,
39
+ satoshis: sats,
40
+ value: sats,
41
+ script: scriptHex,
42
+ scriptPubKey: scriptHex,
43
+ address,
44
+ };
45
+ }
46
+
47
+ function createTestWallet() {
48
+ console.log('šŸ”§ Creating test wallet...\n');
49
+
50
+ // Generate a new private key for testing
51
+ const privateKey = new bsv.PrivateKey();
52
+ const publicKey = privateKey.toPublicKey();
53
+ const address = privateKey.toAddress();
54
+
55
+ console.log('šŸ“‹ Test Wallet Details:');
56
+ console.log(`Private Key (WIF): ${privateKey.toWIF()}`);
57
+ console.log(`Private Key (Hex): ${privateKey.toString('hex')}`);
58
+ console.log(`Public Key: ${publicKey.toString()}`);
59
+ console.log(`Address: ${address.toString()}`);
60
+ console.log(`Pubkey Hash160: ${bsv.crypto.Hash.sha256ripemd160(publicKey.toBuffer()).toString('hex')}\n`);
61
+
62
+ // Create a mock UTXO with sufficient funds for testing
63
+ const utxo = mkUtxo(privateKey, 50000); // 50,000 satoshis
64
+
65
+ console.log('šŸ’° Mock UTXO Created:');
66
+ console.log(`TXID: ${utxo.txid}`);
67
+ console.log(`Vout: ${utxo.vout}`);
68
+ console.log(`Satoshis: ${utxo.satoshis}`);
69
+ console.log(`Script: ${utxo.script}\n`);
70
+
71
+ // Create test environment config
72
+ const testConfig = {
73
+ wallet: {
74
+ privateKeyWIF: privateKey.toWIF(),
75
+ privateKeyHex: privateKey.toString('hex'),
76
+ publicKey: publicKey.toString(),
77
+ address: address.toString(),
78
+ pubkeyHash160: bsv.crypto.Hash.sha256ripemd160(publicKey.toBuffer()).toString('hex')
79
+ },
80
+ utxo: {
81
+ txid: utxo.txid,
82
+ vout: utxo.vout,
83
+ outputIndex: utxo.outputIndex,
84
+ script: utxo.script,
85
+ scriptPubKey: utxo.scriptPubKey,
86
+ satoshis: utxo.satoshis,
87
+ address: utxo.address
88
+ },
89
+ testParams: {
90
+ nLockTimeTarget: 1000,
91
+ sighashType: bsv.crypto.Signature.SIGHASH_ALL | bsv.crypto.Signature.SIGHASH_FORKID,
92
+ covenantAmount: 40000, // Amount for covenant output
93
+ fee: 1000, // Transaction fee
94
+ changeAmount: 9000 // Remaining change
95
+ },
96
+ metadata: {
97
+ created: new Date().toISOString(),
98
+ description: 'Test wallet and UTXO for BSV preimage covenant testing',
99
+ version: '1.0'
100
+ }
101
+ };
102
+
103
+ return testConfig;
104
+ }
105
+
106
+ function saveTestConfig(config) {
107
+ const configPath = path.join(__dirname, 'wallet.json');
108
+
109
+ console.log('šŸ’¾ Saving wallet configuration...');
110
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
111
+
112
+ console.log(`āœ… Wallet configuration saved to: ${configPath}\n`);
113
+
114
+ return configPath;
115
+ }
116
+
117
+ function displaySetupSummary(config) {
118
+ console.log('šŸ“Š Test Environment Summary:');
119
+ console.log('═══════════════════════════════════════════');
120
+ console.log(`Address: ${config.wallet.address}`);
121
+ console.log(`Balance: ${config.utxo.satoshis} satoshis`);
122
+ console.log(`Mock TXID: ${config.utxo.txid.substring(0, 16)}...`);
123
+ console.log(`nLockTime Target: ${config.testParams.nLockTimeTarget}`);
124
+ console.log(`Covenant Amount: ${config.testParams.covenantAmount} satoshis`);
125
+ console.log(`Fee: ${config.testParams.fee} satoshis`);
126
+ console.log('═══════════════════════════════════════════\n');
127
+
128
+ console.log('\nšŸŽÆ Next Steps:');
129
+ console.log('1. Use the wallet credentials in your tests');
130
+ console.log('2. Import wallet.json in your test files');
131
+ console.log('3. Call updateUTXOFromTransaction() after each transaction\n');
132
+ }
133
+
134
+ // Main execution
135
+ function main() {
136
+ console.log('šŸš€ BSV Preimage Covenant - Test Wallet Setup\n');
137
+
138
+ try {
139
+ // Create test wallet and configuration
140
+ const testConfig = createTestWallet();
141
+
142
+ // Save configuration to file
143
+ const configPath = saveTestConfig(testConfig);
144
+
145
+ // Display summary
146
+ displaySetupSummary(testConfig);
147
+
148
+ console.log('āœ… Test wallet setup complete!');
149
+ console.log(`šŸ“ Configuration file: ${path.basename(configPath)}`);
150
+
151
+ } catch (error) {
152
+ console.error('āŒ Error setting up test wallet:', error.message);
153
+ process.exit(1);
154
+ }
155
+ }
156
+
157
+ // Run if called directly
158
+ if (require.main === module) {
159
+ main();
160
+ }
161
+
162
+ // Export functions for use in other files
163
+ module.exports = {
164
+ createTestWallet,
165
+ mkUtxo,
166
+ saveTestConfig
167
+ };
@@ -0,0 +1,30 @@
1
+ {
2
+ "wallet": {
3
+ "privateKeyWIF": "KwbaQqFUpt9MYQRrkVWk7QC799nAfcqYRYKj4ZNeZBkut3YP45rJ",
4
+ "privateKeyHex": "KwbaQqFUpt9MYQRrkVWk7QC799nAfcqYRYKj4ZNeZBkut3YP45rJ",
5
+ "publicKey": "02330726b97010d7bb1f88b1213330e644916cedfd5fee9c57153592c6b5a44fe9",
6
+ "address": "15XJXD7CSMqHL2ivFCu8PZTACQQ8MPbWY9",
7
+ "pubkeyHash160": "319b9b8eef10d00cf84b5d4772dca69b5f5a7b5c"
8
+ },
9
+ "utxo": {
10
+ "txid": "d6625d13f3130360dea7ebe8ccf8ccdb5e40b3cd5ea51b2094983a3789354c3e",
11
+ "vout": 0,
12
+ "outputIndex": 0,
13
+ "script": "76a914319b9b8eef10d00cf84b5d4772dca69b5f5a7b5c88ac",
14
+ "scriptPubKey": "76a914319b9b8eef10d00cf84b5d4772dca69b5f5a7b5c88ac",
15
+ "satoshis": 50000,
16
+ "address": "15XJXD7CSMqHL2ivFCu8PZTACQQ8MPbWY9"
17
+ },
18
+ "testParams": {
19
+ "nLockTimeTarget": 1000,
20
+ "sighashType": 65,
21
+ "covenantAmount": 40000,
22
+ "fee": 1000,
23
+ "changeAmount": 9000
24
+ },
25
+ "metadata": {
26
+ "created": "2025-10-19T14:33:10.987Z",
27
+ "description": "Test wallet and UTXO for BSV preimage covenant testing",
28
+ "version": "1.0"
29
+ }
30
+ }