minimal-xec-wallet 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +241 -0
- package/dist/minimal-xec-wallet.js +66268 -0
- package/dist/minimal-xec-wallet.min.js +55 -0
- package/examples/README.md +380 -0
- package/examples/advanced/browser-compatibility-test.js +263 -0
- package/examples/advanced/get-xec-price.js +149 -0
- package/examples/advanced/optimize-utxos.js +255 -0
- package/examples/advanced/send-op-return.js +216 -0
- package/examples/browser-test.html +350 -0
- package/examples/key-management/derive-addresses.js +191 -0
- package/examples/key-management/export-to-wif.js +114 -0
- package/examples/key-management/validate-address.js +214 -0
- package/examples/optimization/simple-consolidation-test.js +79 -0
- package/examples/optimization/test-utxo-consolidation.js +179 -0
- package/examples/test-examples.js +1204 -0
- package/examples/tokens/burn-tokens.js +293 -0
- package/examples/tokens/get-token-balance.js +169 -0
- package/examples/tokens/get-token-info.js +269 -0
- package/examples/tokens/list-all-tokens.js +162 -0
- package/examples/tokens/send-any-token.js +260 -0
- package/examples/tokens/test-main-wallet-integration.js +193 -0
- package/examples/transactions/send-all-xec.js +205 -0
- package/examples/transactions/send-to-multiple.js +217 -0
- package/examples/transactions/send-xec.js +191 -0
- package/examples/utils/show-qr.js +119 -0
- package/examples/utils/wallet-helper.js +176 -0
- package/examples/validation/comprehensive-infrastructure-test.js +210 -0
- package/examples/wallet-creation/create-new-wallet.js +67 -0
- package/examples/wallet-creation/import-from-wif.js +135 -0
- package/examples/wallet-creation/restore-from-mnemonic.js +100 -0
- package/examples/wallet-info/get-balance.js +99 -0
- package/examples/wallet-info/get-transactions.js +157 -0
- package/examples/wallet-info/get-utxos.js +145 -0
- package/examples/wallet.json +11 -0
- package/lib/adapters/robust-chronik-router.js +507 -0
- package/lib/adapters/router.js +651 -0
- package/lib/alp-token-handler.js +581 -0
- package/lib/browser-wasm-loader.js +271 -0
- package/lib/consolidate-utxos.js +338 -0
- package/lib/hybrid-token-manager.js +322 -0
- package/lib/key-derivation.js +466 -0
- package/lib/op-return.js +314 -0
- package/lib/security.js +270 -0
- package/lib/send-xec.js +396 -0
- package/lib/slp-token-handler.js +572 -0
- package/lib/token-protocol-detector.js +307 -0
- package/lib/utxos.js +303 -0
- package/package.json +125 -0
|
@@ -0,0 +1,350 @@
|
|
|
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>Minimal XEC Wallet - Browser Compatibility Test</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
font-family: Arial, sans-serif;
|
|
10
|
+
max-width: 800px;
|
|
11
|
+
margin: 0 auto;
|
|
12
|
+
padding: 20px;
|
|
13
|
+
background: #f5f5f5;
|
|
14
|
+
}
|
|
15
|
+
.container {
|
|
16
|
+
background: white;
|
|
17
|
+
padding: 20px;
|
|
18
|
+
border-radius: 8px;
|
|
19
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
20
|
+
}
|
|
21
|
+
.status {
|
|
22
|
+
padding: 10px;
|
|
23
|
+
margin: 10px 0;
|
|
24
|
+
border-radius: 4px;
|
|
25
|
+
font-weight: bold;
|
|
26
|
+
}
|
|
27
|
+
.success { background: #d4edda; color: #155724; }
|
|
28
|
+
.warning { background: #fff3cd; color: #856404; }
|
|
29
|
+
.error { background: #f8d7da; color: #721c24; }
|
|
30
|
+
.info { background: #d1ecf1; color: #0c5460; }
|
|
31
|
+
pre {
|
|
32
|
+
background: #f8f9fa;
|
|
33
|
+
padding: 15px;
|
|
34
|
+
border-radius: 4px;
|
|
35
|
+
overflow-x: auto;
|
|
36
|
+
font-size: 12px;
|
|
37
|
+
}
|
|
38
|
+
button {
|
|
39
|
+
background: #007bff;
|
|
40
|
+
color: white;
|
|
41
|
+
border: none;
|
|
42
|
+
padding: 10px 20px;
|
|
43
|
+
border-radius: 4px;
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
margin: 5px;
|
|
46
|
+
}
|
|
47
|
+
button:hover { background: #0056b3; }
|
|
48
|
+
button:disabled {
|
|
49
|
+
background: #6c757d;
|
|
50
|
+
cursor: not-allowed;
|
|
51
|
+
}
|
|
52
|
+
.test-section {
|
|
53
|
+
margin: 20px 0;
|
|
54
|
+
padding: 15px;
|
|
55
|
+
border: 1px solid #dee2e6;
|
|
56
|
+
border-radius: 4px;
|
|
57
|
+
}
|
|
58
|
+
</style>
|
|
59
|
+
</head>
|
|
60
|
+
<body>
|
|
61
|
+
<div class="container">
|
|
62
|
+
<h1>š¦ Minimal XEC Wallet - Browser Test</h1>
|
|
63
|
+
<p>This page tests WebAssembly compatibility and wallet functionality in your browser.</p>
|
|
64
|
+
|
|
65
|
+
<div class="test-section">
|
|
66
|
+
<h2>š Browser Capabilities</h2>
|
|
67
|
+
<div id="browser-info"></div>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div class="test-section">
|
|
71
|
+
<h2>āļø WebAssembly Loading Test</h2>
|
|
72
|
+
<button onclick="testWASMLoading()">Test WebAssembly Loading</button>
|
|
73
|
+
<div id="wasm-status"></div>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div class="test-section">
|
|
77
|
+
<h2>š¦ Wallet Functionality Test</h2>
|
|
78
|
+
<button onclick="testWalletFunctionality()">Test Wallet Creation</button>
|
|
79
|
+
<div id="wallet-status"></div>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<div class="test-section">
|
|
83
|
+
<h2>š° Transaction Test</h2>
|
|
84
|
+
<button onclick="testTransactionBuilding()" id="tx-test-btn" disabled>Test Transaction Building</button>
|
|
85
|
+
<div id="transaction-status"></div>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<div class="test-section">
|
|
89
|
+
<h2>š Test Results</h2>
|
|
90
|
+
<div id="results-summary"></div>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<!-- Load the minimal-xec-wallet library -->
|
|
95
|
+
<script src="../dist/minimal-xec-wallet.min.js"></script>
|
|
96
|
+
|
|
97
|
+
<script>
|
|
98
|
+
let testResults = {
|
|
99
|
+
browserCapabilities: null,
|
|
100
|
+
wasmLoading: null,
|
|
101
|
+
walletCreation: null,
|
|
102
|
+
transactionBuilding: null
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
let wallet = null;
|
|
106
|
+
|
|
107
|
+
// Display browser capabilities on page load
|
|
108
|
+
window.onload = function() {
|
|
109
|
+
displayBrowserCapabilities();
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
function displayBrowserCapabilities() {
|
|
113
|
+
const capabilities = {
|
|
114
|
+
webAssembly: typeof WebAssembly !== 'undefined',
|
|
115
|
+
webAssemblyCompile: typeof WebAssembly !== 'undefined' && typeof WebAssembly.compile === 'function',
|
|
116
|
+
webAssemblyInstantiate: typeof WebAssembly !== 'undefined' && typeof WebAssembly.instantiate === 'function',
|
|
117
|
+
webWorkers: typeof Worker !== 'undefined',
|
|
118
|
+
cryptoSubtle: typeof crypto !== 'undefined' && crypto.subtle,
|
|
119
|
+
userAgent: navigator.userAgent
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
testResults.browserCapabilities = capabilities;
|
|
123
|
+
|
|
124
|
+
const html = `
|
|
125
|
+
<div class="status info">
|
|
126
|
+
<strong>Browser Information:</strong><br>
|
|
127
|
+
WebAssembly Support: ${capabilities.webAssembly ? 'ā
' : 'ā'}<br>
|
|
128
|
+
WebAssembly.compile: ${capabilities.webAssemblyCompile ? 'ā
' : 'ā'}<br>
|
|
129
|
+
WebAssembly.instantiate: ${capabilities.webAssemblyInstantiate ? 'ā
' : 'ā'}<br>
|
|
130
|
+
Web Workers: ${capabilities.webWorkers ? 'ā
' : 'ā'}<br>
|
|
131
|
+
Crypto.subtle: ${capabilities.cryptoSubtle ? 'ā
' : 'ā'}<br>
|
|
132
|
+
</div>
|
|
133
|
+
<pre>${capabilities.userAgent}</pre>
|
|
134
|
+
`;
|
|
135
|
+
|
|
136
|
+
document.getElementById('browser-info').innerHTML = html;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function testWASMLoading() {
|
|
140
|
+
const statusDiv = document.getElementById('wasm-status');
|
|
141
|
+
statusDiv.innerHTML = '<div class="status info">Testing WebAssembly loading...</div>';
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
const startTime = Date.now();
|
|
145
|
+
|
|
146
|
+
// Test if MinimalXecWallet is available
|
|
147
|
+
if (typeof MinimalXecWallet === 'undefined') {
|
|
148
|
+
throw new Error('MinimalXecWallet library not loaded');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Create a test wallet to trigger WASM initialization
|
|
152
|
+
const testWallet = new MinimalXecWallet();
|
|
153
|
+
|
|
154
|
+
// Wait for WASM initialization
|
|
155
|
+
await testWallet.wasmInitPromise;
|
|
156
|
+
|
|
157
|
+
const endTime = Date.now();
|
|
158
|
+
const loadTime = endTime - startTime;
|
|
159
|
+
|
|
160
|
+
testResults.wasmLoading = {
|
|
161
|
+
success: true,
|
|
162
|
+
loadTime
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
statusDiv.innerHTML = `
|
|
166
|
+
<div class="status success">
|
|
167
|
+
ā
WebAssembly loading successful!<br>
|
|
168
|
+
Load time: ${loadTime}ms
|
|
169
|
+
</div>
|
|
170
|
+
`;
|
|
171
|
+
|
|
172
|
+
} catch (err) {
|
|
173
|
+
testResults.wasmLoading = {
|
|
174
|
+
success: false,
|
|
175
|
+
error: err.message
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
statusDiv.innerHTML = `
|
|
179
|
+
<div class="status warning">
|
|
180
|
+
ā ļø WebAssembly loading failed, using fallbacks:<br>
|
|
181
|
+
${err.message}
|
|
182
|
+
</div>
|
|
183
|
+
`;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async function testWalletFunctionality() {
|
|
188
|
+
const statusDiv = document.getElementById('wallet-status');
|
|
189
|
+
statusDiv.innerHTML = '<div class="status info">Testing wallet creation...</div>';
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
const startTime = Date.now();
|
|
193
|
+
|
|
194
|
+
// Create wallet
|
|
195
|
+
wallet = new MinimalXecWallet();
|
|
196
|
+
|
|
197
|
+
// Wait for wallet info creation
|
|
198
|
+
await wallet.walletInfoPromise;
|
|
199
|
+
|
|
200
|
+
// Initialize wallet
|
|
201
|
+
await wallet.initialize();
|
|
202
|
+
|
|
203
|
+
const endTime = Date.now();
|
|
204
|
+
const initTime = endTime - startTime;
|
|
205
|
+
|
|
206
|
+
testResults.walletCreation = {
|
|
207
|
+
success: true,
|
|
208
|
+
initTime,
|
|
209
|
+
address: wallet.walletInfo.xecAddress
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
statusDiv.innerHTML = `
|
|
213
|
+
<div class="status success">
|
|
214
|
+
ā
Wallet created successfully!<br>
|
|
215
|
+
Initialization time: ${initTime}ms<br>
|
|
216
|
+
Address: ${wallet.walletInfo.xecAddress}
|
|
217
|
+
</div>
|
|
218
|
+
`;
|
|
219
|
+
|
|
220
|
+
// Enable transaction test button
|
|
221
|
+
document.getElementById('tx-test-btn').disabled = false;
|
|
222
|
+
|
|
223
|
+
} catch (err) {
|
|
224
|
+
testResults.walletCreation = {
|
|
225
|
+
success: false,
|
|
226
|
+
error: err.message
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
statusDiv.innerHTML = `
|
|
230
|
+
<div class="status error">
|
|
231
|
+
ā Wallet creation failed:<br>
|
|
232
|
+
${err.message}
|
|
233
|
+
</div>
|
|
234
|
+
`;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async function testTransactionBuilding() {
|
|
239
|
+
const statusDiv = document.getElementById('transaction-status');
|
|
240
|
+
statusDiv.innerHTML = '<div class="status info">Testing transaction building...</div>';
|
|
241
|
+
|
|
242
|
+
if (!wallet) {
|
|
243
|
+
statusDiv.innerHTML = '<div class="status error">ā Wallet not created yet</div>';
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
try {
|
|
248
|
+
// Test basic operations that don't require funding
|
|
249
|
+
|
|
250
|
+
// Test address validation
|
|
251
|
+
const isValidAddress = wallet._validateAddress(wallet.walletInfo.xecAddress);
|
|
252
|
+
|
|
253
|
+
// Test key pair generation
|
|
254
|
+
const keyPair = await wallet.getKeyPair(0);
|
|
255
|
+
|
|
256
|
+
// Test WIF export/validation
|
|
257
|
+
const wif = wallet.exportPrivateKeyAsWIF();
|
|
258
|
+
const isValidWIF = wallet.validateWIF(wif);
|
|
259
|
+
|
|
260
|
+
// Test balance query (will show error but shouldn't crash)
|
|
261
|
+
let balanceTest = 'Skipped';
|
|
262
|
+
try {
|
|
263
|
+
await wallet.getXecBalance();
|
|
264
|
+
balanceTest = 'Success';
|
|
265
|
+
} catch (err) {
|
|
266
|
+
balanceTest = `Error (expected): ${err.message.substring(0, 50)}...`;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
testResults.transactionBuilding = {
|
|
270
|
+
success: true,
|
|
271
|
+
addressValidation: isValidAddress,
|
|
272
|
+
keyPairGeneration: !!keyPair.xecAddress,
|
|
273
|
+
wifOperations: isValidWIF,
|
|
274
|
+
balanceQuery: balanceTest
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
statusDiv.innerHTML = `
|
|
278
|
+
<div class="status success">
|
|
279
|
+
ā
Transaction building test completed!<br>
|
|
280
|
+
Address validation: ${isValidAddress ? 'ā
' : 'ā'}<br>
|
|
281
|
+
Key pair generation: ${keyPair.xecAddress ? 'ā
' : 'ā'}<br>
|
|
282
|
+
WIF operations: ${isValidWIF ? 'ā
' : 'ā'}<br>
|
|
283
|
+
Balance query: ${balanceTest}
|
|
284
|
+
</div>
|
|
285
|
+
`;
|
|
286
|
+
|
|
287
|
+
updateResultsSummary();
|
|
288
|
+
|
|
289
|
+
} catch (err) {
|
|
290
|
+
testResults.transactionBuilding = {
|
|
291
|
+
success: false,
|
|
292
|
+
error: err.message
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
statusDiv.innerHTML = `
|
|
296
|
+
<div class="status error">
|
|
297
|
+
ā Transaction building failed:<br>
|
|
298
|
+
${err.message}
|
|
299
|
+
</div>
|
|
300
|
+
`;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function updateResultsSummary() {
|
|
305
|
+
const summaryDiv = document.getElementById('results-summary');
|
|
306
|
+
|
|
307
|
+
let allTestsPassed = true;
|
|
308
|
+
let summary = '<h3>Overall Test Results:</h3>';
|
|
309
|
+
|
|
310
|
+
if (testResults.browserCapabilities) {
|
|
311
|
+
const browserSupport = testResults.browserCapabilities.webAssembly ? 'Modern Browser' : 'Legacy Browser';
|
|
312
|
+
summary += `<strong>Browser Type:</strong> ${browserSupport}<br>`;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (testResults.wasmLoading) {
|
|
316
|
+
const wasmStatus = testResults.wasmLoading.success ? 'ā
Success' : 'ā ļø Fallback';
|
|
317
|
+
summary += `<strong>WebAssembly Loading:</strong> ${wasmStatus}<br>`;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (testResults.walletCreation) {
|
|
321
|
+
const walletStatus = testResults.walletCreation.success ? 'ā
Success' : 'ā Failed';
|
|
322
|
+
summary += `<strong>Wallet Creation:</strong> ${walletStatus}<br>`;
|
|
323
|
+
if (!testResults.walletCreation.success) allTestsPassed = false;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (testResults.transactionBuilding) {
|
|
327
|
+
const txStatus = testResults.transactionBuilding.success ? 'ā
Success' : 'ā Failed';
|
|
328
|
+
summary += `<strong>Transaction Building:</strong> ${txStatus}<br>`;
|
|
329
|
+
if (!testResults.transactionBuilding.success) allTestsPassed = false;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const overallStatus = allTestsPassed ? 'success' : 'warning';
|
|
333
|
+
const overallMessage = allTestsPassed
|
|
334
|
+
? 'š All tests passed! Your browser is fully compatible with minimal-xec-wallet.'
|
|
335
|
+
: 'ā ļø Some tests failed. The wallet may work with reduced functionality.';
|
|
336
|
+
|
|
337
|
+
summaryDiv.innerHTML = `
|
|
338
|
+
<div class="status ${overallStatus}">
|
|
339
|
+
${summary}<br>
|
|
340
|
+
<strong>${overallMessage}</strong>
|
|
341
|
+
</div>
|
|
342
|
+
`;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Test console logging
|
|
346
|
+
console.log('š Minimal XEC Wallet Browser Test Page Loaded');
|
|
347
|
+
console.log('Click the test buttons to validate browser compatibility');
|
|
348
|
+
</script>
|
|
349
|
+
</body>
|
|
350
|
+
</html>
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Derive multiple addresses from wallet mnemonic.
|
|
3
|
+
This example shows how to generate addresses at different HD paths.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const MinimalXECWallet = require('../../index')
|
|
7
|
+
const WalletHelper = require('../utils/wallet-helper')
|
|
8
|
+
|
|
9
|
+
// Get command line arguments
|
|
10
|
+
const args = process.argv.slice(2)
|
|
11
|
+
const count = parseInt(args[0]) || 10
|
|
12
|
+
|
|
13
|
+
function showUsage () {
|
|
14
|
+
console.log('Usage: node derive-addresses.js [count]')
|
|
15
|
+
console.log('')
|
|
16
|
+
console.log('Examples:')
|
|
17
|
+
console.log(' node derive-addresses.js # Derive 10 addresses')
|
|
18
|
+
console.log(' node derive-addresses.js 5 # Derive 5 addresses')
|
|
19
|
+
console.log(' node derive-addresses.js 20 # Derive 20 addresses')
|
|
20
|
+
console.log('')
|
|
21
|
+
console.log('Parameters:')
|
|
22
|
+
console.log(' count: Number of addresses to derive (default: 10, max: 100)')
|
|
23
|
+
console.log('')
|
|
24
|
+
console.log('Note: This only works with wallets created from mnemonic phrases')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function deriveAddresses () {
|
|
28
|
+
try {
|
|
29
|
+
console.log('š Deriving multiple addresses from wallet...\n')
|
|
30
|
+
|
|
31
|
+
// Validate count
|
|
32
|
+
if (isNaN(count) || count < 1 || count > 100) {
|
|
33
|
+
console.log('ā Invalid count. Must be between 1 and 100')
|
|
34
|
+
showUsage()
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Load wallet from file
|
|
39
|
+
const walletData = WalletHelper.loadWallet()
|
|
40
|
+
if (!walletData) {
|
|
41
|
+
console.log(' Run: node examples/wallet-creation/create-new-wallet.js')
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Check if wallet has mnemonic
|
|
46
|
+
if (!walletData.mnemonic) {
|
|
47
|
+
console.log('ā This wallet was not created from a mnemonic!')
|
|
48
|
+
console.log(' Address derivation requires a mnemonic phrase.')
|
|
49
|
+
console.log(' Only wallets created with:')
|
|
50
|
+
console.log(' ⢠create-new-wallet.js')
|
|
51
|
+
console.log(' ⢠restore-from-mnemonic.js')
|
|
52
|
+
console.log(' support multiple address derivation.')
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Create wallet instance from saved data
|
|
57
|
+
const wallet = new MinimalXECWallet(walletData.mnemonic)
|
|
58
|
+
await wallet.walletInfoPromise
|
|
59
|
+
|
|
60
|
+
console.log('š Wallet Information:')
|
|
61
|
+
console.log('ā'.repeat(60))
|
|
62
|
+
console.log(`Mnemonic: ${walletData.mnemonic.split(' ').length} words`)
|
|
63
|
+
console.log(`Base Address: ${walletData.xecAddress}`)
|
|
64
|
+
console.log(`Base HD Path: ${walletData.hdPath}`)
|
|
65
|
+
console.log(`Addresses to derive: ${count}`)
|
|
66
|
+
console.log('ā'.repeat(60))
|
|
67
|
+
|
|
68
|
+
console.log('\nš Deriving addresses...')
|
|
69
|
+
|
|
70
|
+
// Derive addresses at different indices
|
|
71
|
+
const addresses = []
|
|
72
|
+
|
|
73
|
+
for (let i = 0; i < count; i++) {
|
|
74
|
+
try {
|
|
75
|
+
const keyPair = await wallet.getKeyPair(i)
|
|
76
|
+
addresses.push({
|
|
77
|
+
index: i,
|
|
78
|
+
address: keyPair.xecAddress,
|
|
79
|
+
privateKey: keyPair.wif,
|
|
80
|
+
publicKey: keyPair.publicKey,
|
|
81
|
+
hdIndex: keyPair.hdIndex
|
|
82
|
+
})
|
|
83
|
+
} catch (err) {
|
|
84
|
+
console.log(` Warning: Failed to derive address at index ${i}:`, err.message)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.log('\nš Derived Addresses:')
|
|
89
|
+
console.log('ā'.repeat(80))
|
|
90
|
+
console.log('Index Address HD Path')
|
|
91
|
+
console.log('ā'.repeat(80))
|
|
92
|
+
|
|
93
|
+
addresses.forEach(addr => {
|
|
94
|
+
const hdPath = `m/44'/899'/0'/0/${addr.index}`
|
|
95
|
+
const addressShort = `${addr.address.substring(0, 25)}...${addr.address.substring(addr.address.length - 8)}`
|
|
96
|
+
console.log(`${addr.index.toString().padStart(3)} ${addressShort} ${hdPath}`)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
console.log('ā'.repeat(80))
|
|
100
|
+
console.log(`Total addresses derived: ${addresses.length}`)
|
|
101
|
+
|
|
102
|
+
// Show detailed information for first few addresses
|
|
103
|
+
if (addresses.length > 0) {
|
|
104
|
+
console.log('\nš Detailed Information (first 3 addresses):')
|
|
105
|
+
|
|
106
|
+
addresses.slice(0, 3).forEach((addr, i) => {
|
|
107
|
+
console.log(`\n${i + 1}. Address ${addr.index}:`)
|
|
108
|
+
console.log(' ā'.repeat(50))
|
|
109
|
+
console.log(` Address: ${addr.address}`)
|
|
110
|
+
console.log(` HD Path: m/44'/899'/0'/0/${addr.index}`)
|
|
111
|
+
|
|
112
|
+
// Show private key format (truncated for security)
|
|
113
|
+
const pkShort = `${addr.privateKey.substring(0, 8)}...${addr.privateKey.substring(addr.privateKey.length - 8)}`
|
|
114
|
+
console.log(` Private Key: ${pkShort}`)
|
|
115
|
+
|
|
116
|
+
const pubShort = `${addr.publicKey.substring(0, 16)}...${addr.publicKey.substring(addr.publicKey.length - 8)}`
|
|
117
|
+
console.log(` Public Key: ${pubShort}`)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
if (addresses.length > 3) {
|
|
121
|
+
console.log(`\n ... and ${addresses.length - 3} more addresses`)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Address usage guidance
|
|
126
|
+
console.log('\nš” Address Usage Guidance:')
|
|
127
|
+
console.log('ā'.repeat(60))
|
|
128
|
+
console.log('⢠Address 0: Primary wallet address (current active)')
|
|
129
|
+
console.log('⢠Address 1+: Additional addresses for privacy/organization')
|
|
130
|
+
console.log('⢠Each address has its own private key')
|
|
131
|
+
console.log('⢠All addresses share the same recovery mnemonic')
|
|
132
|
+
console.log('⢠Use different addresses for different purposes')
|
|
133
|
+
|
|
134
|
+
console.log('\nš Security Notes:')
|
|
135
|
+
console.log('ā'.repeat(60))
|
|
136
|
+
console.log('⢠All these addresses are derived from your mnemonic')
|
|
137
|
+
console.log('⢠Anyone with your mnemonic can access ALL addresses')
|
|
138
|
+
console.log('⢠Keep your mnemonic phrase secure and private')
|
|
139
|
+
console.log('⢠Consider using different addresses for enhanced privacy')
|
|
140
|
+
|
|
141
|
+
console.log('\nš± How to Use Multiple Addresses:')
|
|
142
|
+
console.log('ā'.repeat(60))
|
|
143
|
+
console.log('⢠Give different addresses to different people/services')
|
|
144
|
+
console.log('⢠Use separate addresses for savings vs spending')
|
|
145
|
+
console.log('⢠Organize funds by purpose (trading, storage, etc.)')
|
|
146
|
+
console.log('⢠Enhanced privacy by not linking all transactions')
|
|
147
|
+
|
|
148
|
+
// Balance checking suggestion
|
|
149
|
+
console.log('\nš Check Balances:')
|
|
150
|
+
console.log('ā'.repeat(60))
|
|
151
|
+
console.log('To check individual address balances:')
|
|
152
|
+
addresses.slice(0, 3).forEach(addr => {
|
|
153
|
+
console.log(`⢠Address ${addr.index}: node examples/wallet-info/get-balance.js`)
|
|
154
|
+
console.log(` (Then manually check ${addr.address})`)
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
console.log('\nā ļø Important Considerations:')
|
|
158
|
+
console.log('ā'.repeat(60))
|
|
159
|
+
console.log('⢠This wallet library tracks only the primary address (index 0)')
|
|
160
|
+
console.log('⢠To use other addresses, you would need to:')
|
|
161
|
+
console.log(' - Import their private keys separately, or')
|
|
162
|
+
console.log(' - Modify the wallet to track multiple addresses')
|
|
163
|
+
console.log('⢠Most wallet software supports multiple address management')
|
|
164
|
+
} catch (err) {
|
|
165
|
+
console.error('ā Failed to derive addresses:', err.message)
|
|
166
|
+
|
|
167
|
+
// Provide helpful error context
|
|
168
|
+
if (err.message.includes('mnemonic')) {
|
|
169
|
+
console.log('\nš Mnemonic Error:')
|
|
170
|
+
console.log(' ⢠Your wallet.json might not contain a valid mnemonic')
|
|
171
|
+
console.log(' ⢠Try restoring from your original mnemonic phrase')
|
|
172
|
+
console.log(' ⢠Only HD wallets support address derivation')
|
|
173
|
+
} else if (err.message.includes('path') || err.message.includes('derivation')) {
|
|
174
|
+
console.log('\nš¤ļø Derivation Error:')
|
|
175
|
+
console.log(' ⢠HD path derivation failed')
|
|
176
|
+
console.log(' ⢠Your mnemonic might be invalid')
|
|
177
|
+
console.log(' ⢠Try with a smaller number of addresses')
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
process.exit(1)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Show usage if requested
|
|
185
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
186
|
+
showUsage()
|
|
187
|
+
process.exit(0)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Run the example
|
|
191
|
+
deriveAddresses()
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Export an XEC wallet's private key to WIF (Wallet Import Format).
|
|
3
|
+
This example shows how to export private keys in different formats.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const MinimalXECWallet = require('../../index')
|
|
7
|
+
const WalletHelper = require('../utils/wallet-helper')
|
|
8
|
+
|
|
9
|
+
async function exportToWif () {
|
|
10
|
+
try {
|
|
11
|
+
console.log('š Exporting XEC wallet private key to WIF format...\n')
|
|
12
|
+
|
|
13
|
+
// Check if wallet exists
|
|
14
|
+
if (!WalletHelper.walletExists()) {
|
|
15
|
+
console.error('ā No wallet found!')
|
|
16
|
+
console.log(' Create a wallet first using one of these commands:')
|
|
17
|
+
console.log(' ⢠node examples/wallet-creation/create-new-wallet.js')
|
|
18
|
+
console.log(' ⢠node examples/wallet-creation/restore-from-mnemonic.js')
|
|
19
|
+
console.log(' ⢠node examples/wallet-creation/import-from-wif.js')
|
|
20
|
+
process.exit(1)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Load wallet from wallet.json
|
|
24
|
+
const walletInfo = WalletHelper.loadWallet()
|
|
25
|
+
const wallet = new MinimalXECWallet(walletInfo.mnemonic || walletInfo.privateKey)
|
|
26
|
+
await wallet.walletInfoPromise
|
|
27
|
+
|
|
28
|
+
console.log('š Current Wallet Information:')
|
|
29
|
+
console.log('ā'.repeat(50))
|
|
30
|
+
console.log(`XEC Address: ${wallet.walletInfo.xecAddress}`)
|
|
31
|
+
console.log(`Wallet Type: ${wallet.walletInfo.mnemonic ? 'HD Wallet' : 'Single Key'}`)
|
|
32
|
+
console.log('ā'.repeat(50))
|
|
33
|
+
|
|
34
|
+
console.log('\nš Exporting Private Key in WIF Formats:')
|
|
35
|
+
console.log('ā'.repeat(50))
|
|
36
|
+
|
|
37
|
+
// Export mainnet compressed WIF
|
|
38
|
+
const mainnetCompressed = wallet.exportPrivateKeyAsWIF(true, false)
|
|
39
|
+
console.log(`Mainnet Compressed: ${mainnetCompressed}`)
|
|
40
|
+
console.log(`āā Validation: ${wallet.validateWIF(mainnetCompressed) ? 'ā
Valid' : 'ā Invalid'}`)
|
|
41
|
+
console.log(`āā Length: ${mainnetCompressed.length} characters`)
|
|
42
|
+
console.log('āā Usage: Most common format for importing')
|
|
43
|
+
|
|
44
|
+
// Export mainnet uncompressed WIF
|
|
45
|
+
const mainnetUncompressed = wallet.exportPrivateKeyAsWIF(false, false)
|
|
46
|
+
console.log(`\nMainnet Uncompressed: ${mainnetUncompressed}`)
|
|
47
|
+
console.log(`āā Validation: ${wallet.validateWIF(mainnetUncompressed) ? 'ā
Valid' : 'ā Invalid'}`)
|
|
48
|
+
console.log(`āā Length: ${mainnetUncompressed.length} characters`)
|
|
49
|
+
console.log('āā Usage: Legacy format, less common')
|
|
50
|
+
|
|
51
|
+
// Export testnet compressed WIF
|
|
52
|
+
const testnetCompressed = wallet.exportPrivateKeyAsWIF(true, true)
|
|
53
|
+
console.log(`\nTestnet Compressed: ${testnetCompressed}`)
|
|
54
|
+
console.log(`āā Validation: ${wallet.validateWIF(testnetCompressed) ? 'ā
Valid' : 'ā Invalid'}`)
|
|
55
|
+
console.log(`āā Length: ${testnetCompressed.length} characters`)
|
|
56
|
+
console.log('āā Usage: For testnet applications')
|
|
57
|
+
|
|
58
|
+
// Export testnet uncompressed WIF
|
|
59
|
+
const testnetUncompressed = wallet.exportPrivateKeyAsWIF(false, true)
|
|
60
|
+
console.log(`\nTestnet Uncompressed: ${testnetUncompressed}`)
|
|
61
|
+
console.log(`āā Validation: ${wallet.validateWIF(testnetUncompressed) ? 'ā
Valid' : 'ā Invalid'}`)
|
|
62
|
+
console.log(`āā Length: ${testnetUncompressed.length} characters`)
|
|
63
|
+
console.log('āā Usage: For testnet, legacy format')
|
|
64
|
+
|
|
65
|
+
console.log('\nš WIF Format Reference:')
|
|
66
|
+
console.log('ā'.repeat(50))
|
|
67
|
+
console.log('Format | Prefix | Network | Compression')
|
|
68
|
+
console.log('ā'.repeat(50))
|
|
69
|
+
console.log('Mainnet Compressed | K, L | Mainnet | Yes')
|
|
70
|
+
console.log('Mainnet Uncompressed | 5 | Mainnet | No')
|
|
71
|
+
console.log('Testnet Compressed | c | Testnet | Yes')
|
|
72
|
+
console.log('Testnet Uncompressed | 9 | Testnet | No')
|
|
73
|
+
|
|
74
|
+
console.log('\nš Round-trip Validation Test:')
|
|
75
|
+
console.log('ā'.repeat(30))
|
|
76
|
+
|
|
77
|
+
// Test round-trip conversion
|
|
78
|
+
const testWIF = mainnetCompressed
|
|
79
|
+
const importedWallet = new MinimalXECWallet(testWIF)
|
|
80
|
+
await importedWallet.walletInfoPromise
|
|
81
|
+
|
|
82
|
+
const addressMatch = importedWallet.walletInfo.xecAddress === wallet.walletInfo.xecAddress
|
|
83
|
+
console.log(`Original Address: ${wallet.walletInfo.xecAddress}`)
|
|
84
|
+
console.log(`Imported Address: ${importedWallet.walletInfo.xecAddress}`)
|
|
85
|
+
console.log(`Addresses Match: ${addressMatch ? 'ā
Yes' : 'ā No'}`)
|
|
86
|
+
|
|
87
|
+
if (addressMatch) {
|
|
88
|
+
console.log('\nš Success! WIF export and import working correctly.')
|
|
89
|
+
} else {
|
|
90
|
+
console.log('\nā Warning! Address mismatch detected.')
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
console.log('\nš SECURITY WARNINGS:')
|
|
94
|
+
console.log('ā'.repeat(50))
|
|
95
|
+
console.log('⢠WIF private keys provide FULL access to your funds')
|
|
96
|
+
console.log('⢠Never share WIF keys with anyone')
|
|
97
|
+
console.log('⢠Store WIF keys securely and offline')
|
|
98
|
+
console.log('⢠Anyone with your WIF can steal your XEC')
|
|
99
|
+
console.log('⢠Use WIF export only when necessary (wallet recovery, etc.)')
|
|
100
|
+
|
|
101
|
+
console.log('\nš” Usage Examples:')
|
|
102
|
+
console.log('ā'.repeat(50))
|
|
103
|
+
console.log('⢠Import into other wallets or applications')
|
|
104
|
+
console.log('⢠Paper wallet creation for cold storage')
|
|
105
|
+
console.log('⢠Wallet backup and recovery')
|
|
106
|
+
console.log('⢠Cross-platform wallet migration')
|
|
107
|
+
} catch (err) {
|
|
108
|
+
console.error('ā Failed to export WIF:', err.message)
|
|
109
|
+
process.exit(1)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Run the example
|
|
114
|
+
exportToWif()
|