@neuraiproject/neurai-key 2.8.3 → 2.8.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.
@@ -0,0 +1,532 @@
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>Neurai-Key Verifier</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
16
+ background: #f5f5f5;
17
+ min-height: 100vh;
18
+ padding: 20px;
19
+ }
20
+
21
+ .container {
22
+ max-width: 900px;
23
+ margin: 0 auto;
24
+ background: white;
25
+ border-radius: 8px;
26
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
27
+ padding: 40px;
28
+ }
29
+
30
+ h1 {
31
+ color: #2c3e50;
32
+ text-align: center;
33
+ margin-bottom: 8px;
34
+ font-size: 2em;
35
+ font-weight: 600;
36
+ }
37
+
38
+ .subtitle {
39
+ text-align: center;
40
+ color: #7f8c8d;
41
+ margin-bottom: 30px;
42
+ font-size: 0.95em;
43
+ }
44
+
45
+ .input-section {
46
+ background: #fafafa;
47
+ padding: 20px;
48
+ border-radius: 6px;
49
+ margin-bottom: 25px;
50
+ border: 1px solid #e0e0e0;
51
+ }
52
+
53
+ label {
54
+ display: block;
55
+ color: #2c3e50;
56
+ font-weight: 500;
57
+ margin-bottom: 8px;
58
+ font-size: 0.95em;
59
+ }
60
+
61
+ textarea {
62
+ width: 100%;
63
+ padding: 12px;
64
+ border: 1px solid #d0d0d0;
65
+ border-radius: 4px;
66
+ font-size: 14px;
67
+ font-family: 'Courier New', monospace;
68
+ resize: vertical;
69
+ min-height: 100px;
70
+ transition: border-color 0.2s;
71
+ }
72
+
73
+ textarea:focus {
74
+ outline: none;
75
+ border-color: #3498db;
76
+ }
77
+
78
+ .network-selector {
79
+ margin: 15px 0;
80
+ }
81
+
82
+ select {
83
+ width: 100%;
84
+ padding: 10px 12px;
85
+ border: 1px solid #d0d0d0;
86
+ border-radius: 4px;
87
+ font-size: 14px;
88
+ background: white;
89
+ cursor: pointer;
90
+ transition: border-color 0.2s;
91
+ }
92
+
93
+ select:focus {
94
+ outline: none;
95
+ border-color: #3498db;
96
+ }
97
+
98
+ .button-group {
99
+ display: flex;
100
+ gap: 10px;
101
+ margin-top: 20px;
102
+ }
103
+
104
+ button {
105
+ flex: 1;
106
+ padding: 12px 24px;
107
+ font-size: 14px;
108
+ font-weight: 500;
109
+ border: none;
110
+ border-radius: 4px;
111
+ cursor: pointer;
112
+ transition: all 0.2s;
113
+ }
114
+
115
+ .btn-primary {
116
+ background: #3498db;
117
+ color: white;
118
+ }
119
+
120
+ .btn-primary:hover {
121
+ background: #2980b9;
122
+ }
123
+
124
+ .btn-secondary {
125
+ background: #95a5a6;
126
+ color: white;
127
+ }
128
+
129
+ .btn-secondary:hover {
130
+ background: #7f8c8d;
131
+ }
132
+
133
+ .btn-generate {
134
+ background: #27ae60;
135
+ color: white;
136
+ }
137
+
138
+ .btn-generate:hover {
139
+ background: #229954;
140
+ }
141
+
142
+ .results {
143
+ margin-top: 30px;
144
+ }
145
+
146
+ .address-card {
147
+ background: #fafafa;
148
+ padding: 15px;
149
+ border-radius: 4px;
150
+ margin-bottom: 15px;
151
+ border-left: 3px solid #3498db;
152
+ border: 1px solid #e0e0e0;
153
+ border-left: 3px solid #3498db;
154
+ }
155
+
156
+ .address-card:hover {
157
+ background: #f5f5f5;
158
+ }
159
+
160
+ .address-header {
161
+ font-size: 1em;
162
+ font-weight: 600;
163
+ color: #2c3e50;
164
+ margin-bottom: 12px;
165
+ display: flex;
166
+ justify-content: space-between;
167
+ align-items: center;
168
+ }
169
+
170
+ .address-type {
171
+ font-size: 0.75em;
172
+ background: #3498db;
173
+ color: white;
174
+ padding: 4px 8px;
175
+ border-radius: 3px;
176
+ font-weight: 500;
177
+ }
178
+
179
+ .address-info {
180
+ margin: 10px 0;
181
+ display: flex;
182
+ align-items: center;
183
+ gap: 10px;
184
+ }
185
+
186
+ .info-label {
187
+ font-weight: 600;
188
+ color: #555;
189
+ display: inline-block;
190
+ width: 120px;
191
+ font-size: 0.9em;
192
+ flex-shrink: 0;
193
+ }
194
+
195
+ .info-value {
196
+ font-family: 'Courier New', monospace;
197
+ color: #2c3e50;
198
+ word-break: break-all;
199
+ background: white;
200
+ padding: 8px 10px;
201
+ border-radius: 3px;
202
+ font-size: 0.85em;
203
+ border: 1px solid #e0e0e0;
204
+ flex: 1 1 auto;
205
+ min-width: 0;
206
+ overflow: hidden;
207
+ }
208
+
209
+ .error {
210
+ background: #fee;
211
+ color: #c53030;
212
+ padding: 12px;
213
+ border-radius: 4px;
214
+ margin: 15px 0;
215
+ border-left: 3px solid #fc8181;
216
+ font-size: 0.9em;
217
+ }
218
+
219
+ .success {
220
+ background: #f0fff4;
221
+ color: #22543d;
222
+ padding: 12px;
223
+ border-radius: 4px;
224
+ margin: 15px 0;
225
+ border-left: 3px solid #68d391;
226
+ font-size: 0.9em;
227
+ }
228
+
229
+ .info {
230
+ background: #e6f7ff;
231
+ color: #003a70;
232
+ padding: 12px;
233
+ border-radius: 4px;
234
+ margin: 15px 0;
235
+ border-left: 3px solid #69c0ff;
236
+ font-size: 0.9em;
237
+ }
238
+
239
+ .loading {
240
+ text-align: center;
241
+ padding: 30px;
242
+ color: #7f8c8d;
243
+ font-size: 1em;
244
+ }
245
+
246
+ .hidden {
247
+ display: none;
248
+ }
249
+
250
+ .copy-btn {
251
+ background: transparent;
252
+ color: #555;
253
+ border: none;
254
+ padding: 6px 8px;
255
+ border-radius: 3px;
256
+ cursor: pointer;
257
+ font-size: 1.2em;
258
+ transition: all 0.2s;
259
+ flex: 0 0 auto;
260
+ width: auto;
261
+ line-height: 1;
262
+ display: inline-flex;
263
+ align-items: center;
264
+ justify-content: center;
265
+ }
266
+
267
+ .copy-btn:hover {
268
+ color: #27ae60;
269
+ transform: scale(1.1);
270
+ }
271
+
272
+ @media (max-width: 768px) {
273
+ .container {
274
+ padding: 20px;
275
+ }
276
+
277
+ h1 {
278
+ font-size: 1.8em;
279
+ }
280
+
281
+ .button-group {
282
+ flex-direction: column;
283
+ }
284
+
285
+ .info-label {
286
+ display: block;
287
+ margin-bottom: 5px;
288
+ }
289
+
290
+ .info-value {
291
+ display: block;
292
+ max-width: 100%;
293
+ }
294
+ }
295
+ </style>
296
+ </head>
297
+ <body>
298
+ <div class="container">
299
+ <h1>Neurai Key Verifier</h1>
300
+ <p class="subtitle">Generate and verify addresses from your mnemonic (12 or 24 words)</p>
301
+
302
+ <div class="input-section">
303
+ <label for="mnemonic">Mnemonic Phrase (12 or 24 words):</label>
304
+ <textarea
305
+ id="mnemonic"
306
+ placeholder="Enter your mnemonic phrase here, separated by spaces. Example: word1 word2 word3..."
307
+ ></textarea>
308
+
309
+ <div class="network-selector">
310
+ <label for="network">Network:</label>
311
+ <select id="network">
312
+ <option value="xna">Neurai Mainnet (XNA)</option>
313
+ <option value="xna-test">Neurai Testnet (XNA-TEST)</option>
314
+ </select>
315
+ </div>
316
+
317
+ <div class="network-selector">
318
+ <label for="passphrase">Passphrase (Optional - BIP39 25th word):</label>
319
+ <input
320
+ type="text"
321
+ id="passphrase"
322
+ placeholder="Enter optional passphrase for extra security"
323
+ style="width: 100%; padding: 12px; border: 1px solid #d0d0d0; border-radius: 4px; font-size: 14px;"
324
+ />
325
+ <small style="color: #7f8c8d; font-size: 0.85em; display: block; margin-top: 5px;">
326
+ ⚠️ Warning: Different passphrases create different wallets. If you use a passphrase, you'll need both the mnemonic AND passphrase to recover your wallet.
327
+ </small>
328
+ </div>
329
+
330
+ <div class="button-group">
331
+ <button class="btn-primary" onclick="verificarYGenerar()">
332
+ Verify and Generate Addresses
333
+ </button>
334
+ <button class="btn-generate" onclick="generarNuevoMnemonic()">
335
+ Generate New Mnemonic
336
+ </button>
337
+ <button class="btn-secondary" onclick="limpiar()">
338
+ Clear
339
+ </button>
340
+ </div>
341
+ </div>
342
+
343
+ <div id="message"></div>
344
+ <div id="results" class="results"></div>
345
+ </div>
346
+
347
+ <script src="./NeuraiKey.js"></script>
348
+ <script>
349
+ function mostrarMensaje(mensaje, tipo) {
350
+ const messageDiv = document.getElementById('message');
351
+ messageDiv.className = tipo;
352
+ messageDiv.innerHTML = mensaje;
353
+ messageDiv.classList.remove('hidden');
354
+ }
355
+
356
+ function ocultarMensaje() {
357
+ const messageDiv = document.getElementById('message');
358
+ messageDiv.classList.add('hidden');
359
+ }
360
+
361
+ function limpiar() {
362
+ document.getElementById('mnemonic').value = '';
363
+ document.getElementById('passphrase').value = '';
364
+ document.getElementById('results').innerHTML = '';
365
+ ocultarMensaje();
366
+ }
367
+
368
+ function generarNuevoMnemonic() {
369
+ try {
370
+ const mnemonic = NeuraiKey.generateMnemonic();
371
+ document.getElementById('mnemonic').value = mnemonic;
372
+ mostrarMensaje('New mnemonic generated. Save it in a safe place!', 'success');
373
+ document.getElementById('results').innerHTML = '';
374
+ } catch (error) {
375
+ mostrarMensaje(`Error generating mnemonic: ${error.message}`, 'error');
376
+ }
377
+ }
378
+
379
+ function copiarTexto(texto, boton) {
380
+ navigator.clipboard.writeText(texto).then(() => {
381
+ const textoOriginal = boton.textContent;
382
+ boton.textContent = '✓';
383
+ setTimeout(() => {
384
+ boton.textContent = textoOriginal;
385
+ }, 2000);
386
+ }).catch(err => {
387
+ alert('Error copying: ' + err);
388
+ });
389
+ }
390
+
391
+ function verificarYGenerar() {
392
+ ocultarMensaje();
393
+ const resultsDiv = document.getElementById('results');
394
+ resultsDiv.innerHTML = '<div class="loading">Generating addresses...</div>';
395
+
396
+ setTimeout(() => {
397
+ try {
398
+ const mnemonic = document.getElementById('mnemonic').value.trim();
399
+ const network = document.getElementById('network').value;
400
+ const passphrase = document.getElementById('passphrase').value; // Obtener passphrase
401
+
402
+ if (!mnemonic) {
403
+ mostrarMensaje('Please enter a mnemonic phrase', 'error');
404
+ resultsDiv.innerHTML = '';
405
+ return;
406
+ }
407
+
408
+ // Validar que sea un mnemonic válido
409
+ const palabras = mnemonic.split(/\s+/).filter(p => p.length > 0);
410
+ if (palabras.length !== 12 && palabras.length !== 24) {
411
+ mostrarMensaje('Mnemonic must have exactly 12 or 24 words. Words found: ' + palabras.length, 'error');
412
+ resultsDiv.innerHTML = '';
413
+ return;
414
+ }
415
+
416
+ // Validar el mnemonic con bip39
417
+ if (!NeuraiKey.validateMnemonic || typeof NeuraiKey.validateMnemonic !== 'function') {
418
+ // Si no existe validateMnemonic, intentar generar una dirección para validar
419
+ try {
420
+ NeuraiKey.getAddressPair(network, mnemonic, 0, 0, passphrase);
421
+ } catch (e) {
422
+ mostrarMensaje('Invalid mnemonic: ' + e.message, 'error');
423
+ resultsDiv.innerHTML = '';
424
+ return;
425
+ }
426
+ }
427
+
428
+ const passphraseMsg = passphrase ? ' with passphrase' : '';
429
+ mostrarMensaje(`Valid mnemonic (${palabras.length} words). Generating addresses on ${network}${passphraseMsg}...`, 'success');
430
+
431
+ let html = '';
432
+
433
+ // Generar las primeras 5 direcciones
434
+ for (let i = 0; i < 5; i++) {
435
+ const addressPair = NeuraiKey.getAddressPair(network, mnemonic, 0, i, passphrase); // Usar passphrase
436
+
437
+ // Dirección Externa (para recibir)
438
+ html += `
439
+ <div class="address-card">
440
+ <div class="address-header">
441
+ <span>Address #${i + 1} - External (Receive)</span>
442
+ <span class="address-type">EXTERNAL</span>
443
+ </div>
444
+ <div class="address-info">
445
+ <span class="info-label">Address:</span>
446
+ <span class="info-value">${addressPair.external.address}</span>
447
+ <button class="copy-btn" onclick="copiarTexto('${addressPair.external.address}', this)">📋</button>
448
+ </div>
449
+ <div class="address-info">
450
+ <span class="info-label">Path:</span>
451
+ <span class="info-value">${addressPair.external.path}</span>
452
+ </div>
453
+ <div class="address-info">
454
+ <span class="info-label">Private Key:</span>
455
+ <span class="info-value">${addressPair.external.privateKey}</span>
456
+ <button class="copy-btn" onclick="copiarTexto('${addressPair.external.privateKey}', this)">📋</button>
457
+ </div>
458
+ <div class="address-info">
459
+ <span class="info-label">WIF:</span>
460
+ <span class="info-value">${addressPair.external.WIF}</span>
461
+ <button class="copy-btn" onclick="copiarTexto('${addressPair.external.WIF}', this)">📋</button>
462
+ </div>
463
+ </div>
464
+
465
+ <div class="address-card">
466
+ <div class="address-header">
467
+ <span>Address #${i + 1} - Internal (Change)</span>
468
+ <span class="address-type" style="background: #f5576c;">INTERNAL</span>
469
+ </div>
470
+ <div class="address-info">
471
+ <span class="info-label">Address:</span>
472
+ <span class="info-value">${addressPair.internal.address}</span>
473
+ <button class="copy-btn" onclick="copiarTexto('${addressPair.internal.address}', this)">📋</button>
474
+ </div>
475
+ <div class="address-info">
476
+ <span class="info-label">Path:</span>
477
+ <span class="info-value">${addressPair.internal.path}</span>
478
+ </div>
479
+ <div class="address-info">
480
+ <span class="info-label">Private Key:</span>
481
+ <span class="info-value">${addressPair.internal.privateKey}</span>
482
+ <button class="copy-btn" onclick="copiarTexto('${addressPair.internal.privateKey}', this)">📋</button>
483
+ </div>
484
+ <div class="address-info">
485
+ <span class="info-label">WIF:</span>
486
+ <span class="info-value">${addressPair.internal.WIF}</span>
487
+ <button class="copy-btn" onclick="copiarTexto('${addressPair.internal.WIF}', this)">📋</button>
488
+ </div>
489
+ </div>
490
+ `;
491
+ }
492
+
493
+ resultsDiv.innerHTML = html;
494
+
495
+ // Agregar mensaje informativo
496
+ const infoDiv = document.createElement('div');
497
+ infoDiv.className = 'info';
498
+ const passphraseInfo = passphrase ? '<br>- 🔐 <strong>Passphrase used:</strong> Remember you need BOTH mnemonic and passphrase to recover these addresses!' : '';
499
+ infoDiv.innerHTML = `
500
+ <strong>Information:</strong><br>
501
+ - The first 5 addresses (external and internal) have been generated<br>
502
+ - <strong>External</strong> addresses are used to receive payments<br>
503
+ - <strong>Internal</strong> addresses are used as change addresses<br>
504
+ - Each pair follows the BIP44 standard with path m/44'/175'/0'/change/index${passphraseInfo}
505
+ `;
506
+ resultsDiv.appendChild(infoDiv);
507
+
508
+ } catch (error) {
509
+ mostrarMensaje(`Error: ${error.message}`, 'error');
510
+ resultsDiv.innerHTML = '';
511
+ }
512
+ }, 100);
513
+ }
514
+
515
+ // Permitir verificar con Enter
516
+ document.getElementById('mnemonic').addEventListener('keypress', function(e) {
517
+ if (e.key === 'Enter' && !e.shiftKey) {
518
+ e.preventDefault();
519
+ verificarYGenerar();
520
+ }
521
+ });
522
+
523
+ // También permitir verificar con Enter en el campo de passphrase
524
+ document.getElementById('passphrase').addEventListener('keypress', function(e) {
525
+ if (e.key === 'Enter') {
526
+ e.preventDefault();
527
+ verificarYGenerar();
528
+ }
529
+ });
530
+ </script>
531
+ </body>
532
+ </html>
package/test.js CHANGED
@@ -7,49 +7,76 @@ test("Random mnemonic should contain 12 words", () => {
7
7
 
8
8
  test("Validate address on main-net", () => {
9
9
  const network = "xna";
10
- const mnemonic =
11
- "orphan resemble brain dwarf bus fancy horn among cricket logic duty crater";
10
+ const mnemonic = "result pact model attract result puzzle final boss private educate luggage era";
12
11
  const address = NeuraiKey.getAddressPair(network, mnemonic, 0, 1);
13
- expect(address.external.address).toBe("RKbP9SMo2KTKWsiTrEDhTWPuaTwfuPiN8G");
12
+ expect(address.external.address).toBe("NLdcSXGQvCVf2RTKhx7GZom34f1JADhBTp");
14
13
  });
15
14
 
16
15
  test("Validate address on test-net", () => {
17
16
  const network = "xna-test";
18
- const mnemonic =
19
- "orphan resemble brain dwarf bus fancy horn among cricket logic duty crater";
17
+ const mnemonic = "result pact model attract result puzzle final boss private educate luggage era";
20
18
  const address = NeuraiKey.getAddressPair(network, mnemonic, 0, 1);
21
- expect(address.external.address).toBe("n1nUspcdAaDAMfx2ksZJ5cDa7UKVEGstrX");
19
+ expect(address.external.address).toBe("tPXGaMRNwZuV1UKSrD9gABPscrJWUmedQ9");
20
+ });
21
+
22
+ test("Validate address with passphrase on main-net", () => {
23
+ const network = "xna";
24
+ const mnemonic = "result pact model attract result puzzle final boss private educate luggage era";
25
+ const passphrase = "my secret passphrase";
26
+ const address = NeuraiKey.getAddressPair(network, mnemonic, 0, 1, passphrase);
27
+ // With passphrase, the address should be different from the one without passphrase
28
+ expect(address.external.address).not.toBe("NLdcSXGQvCVf2RTKhx7GZom34f1JADhBTp");
29
+ // Verify it generates consistently with the same passphrase
30
+ const address2 = NeuraiKey.getAddressPair(network, mnemonic, 0, 1, passphrase);
31
+ expect(address.external.address).toBe(address2.external.address);
32
+ });
33
+
34
+ test("Different passphrases generate different addresses", () => {
35
+ const network = "xna";
36
+ const mnemonic = "result pact model attract result puzzle final boss private educate luggage era";
37
+ const passphrase1 = "passphrase1";
38
+ const passphrase2 = "passphrase2";
39
+
40
+ const address1 = NeuraiKey.getAddressPair(network, mnemonic, 0, 0, passphrase1);
41
+ const address2 = NeuraiKey.getAddressPair(network, mnemonic, 0, 0, passphrase2);
42
+
43
+ expect(address1.external.address).not.toBe(address2.external.address);
44
+ });
45
+
46
+ test("Empty passphrase equals no passphrase", () => {
47
+ const network = "xna";
48
+ const mnemonic = "result pact model attract result puzzle final boss private educate luggage era";
49
+
50
+ const addressWithEmpty = NeuraiKey.getAddressPair(network, mnemonic, 0, 1, "");
51
+ const addressWithoutPassphrase = NeuraiKey.getAddressPair(network, mnemonic, 0, 1);
52
+
53
+ expect(addressWithEmpty.external.address).toBe(addressWithoutPassphrase.external.address);
54
+ expect(addressWithEmpty.external.address).toBe("NLdcSXGQvCVf2RTKhx7GZom34f1JADhBTp");
22
55
  });
23
56
 
24
57
  test("Validate Wallet Import Format (WIF) main-net ", () => {
25
58
  const network = "xna";
26
- const mnemonic =
27
- "orphan resemble brain dwarf bus fancy horn among cricket logic duty crater";
59
+ const mnemonic = "result pact model attract result puzzle final boss private educate luggage era";
28
60
  const address = NeuraiKey.getAddressPair(network, mnemonic, 0, 1);
29
61
 
30
- expect(address.internal.address).toBe("RLnvUoy29k3QiQgtR6PL416rSNfHTuwhyU");
31
- expect(address.external.WIF).toBe(
32
- "KyWuYcev1hJ7YJZTjWx8coXNRm4jRbMEhgVVVC8vDcTaKRCMASUE"
33
- );
62
+ expect(address.internal.address).toBe("NQM5zP6jkwDgCZ2UQiUicW4e3YcWc4NY4S");
63
+ expect(address.external.WIF).toBe("KwWavecys1Qskgzwsyv6CNeTospWkvMeLzx3dLqeV4xAJEMXF8Qq");
34
64
  });
35
65
 
36
66
  test("Validate Wallet Import Format (WIF) test-net ", () => {
37
67
  const network = "xna-test";
38
- const mnemonic =
39
- "orphan resemble brain dwarf bus fancy horn among cricket logic duty crater";
68
+ const mnemonic = "result pact model attract result puzzle final boss private educate luggage era";
40
69
  const address = NeuraiKey.getAddressPair(network, mnemonic, 0, 1);
41
70
 
42
- expect(address.external.WIF).toBe(
43
- "cPchRRmzZXtPeFLHfrh8qcwaRaziJCS4gcAMBVVQh1EiehNyBtKB"
44
- );
71
+ expect(address.external.WIF).toBe("cSfwLzc9DNj4PdzyGK1sAZzxNwih2HaezMrT8w4MXyhf8qhaHJiE");
45
72
  });
46
73
 
47
74
  test("Validate get public address from Wallet Import Format (WIF) main-net ", () => {
48
75
  const network = "xna";
49
- const WIF = "KyWuYcev1hJ7YJZTjWx8coXNRm4jRbMEhgVVVC8vDcTaKRCMASUE";
76
+ const WIF = "KwWavecys1Qskgzwsyv6CNeTospWkvMeLzx3dLqeV4xAJEMXF8Qq";
50
77
  const addressObject = NeuraiKey.getAddressByWIF(network, WIF);
51
78
 
52
- expect(addressObject.address).toBe("RKbP9SMo2KTKWsiTrEDhTWPuaTwfuPiN8G");
79
+ expect(addressObject.address).toBe("NLdcSXGQvCVf2RTKhx7GZom34f1JADhBTp");
53
80
  });
54
81
 
55
82
  test("Valid bytes to mnemonic", () => {
@@ -73,14 +100,14 @@ test("Non valid bytes to mnemonic should fail", () => {
73
100
  describe("Validate diff languages", () => {
74
101
  it("Should accept spanish mnemonic", () => {
75
102
  const m =
76
- "velero nuera pepino reír barro reforma negar rumbo atento separar pesa puma";
103
+ "velero nuera pepino reír barro reforma negar rumbo atento separar pesa puma";
77
104
  const valid = NeuraiKey.isMnemonicValid(m);
78
105
  expect(valid).toBe(true);
79
106
  });
80
107
 
81
108
  it("Should accept French mnemonic", () => {
82
109
  const m =
83
- "vaseux mixte ozone quiétude besogne punaise membre réussir avarice samedi pantalon poney";
110
+ "vaseux mixte ozone quiétude besogne punaise membre réussir avarice samedi pantalon poney";
84
111
  const valid = NeuraiKey.isMnemonicValid(m);
85
112
  expect(valid).toBe(true);
86
113
  });
@@ -123,4 +150,4 @@ describe("generateAddress", () => {
123
150
  });
124
151
 
125
152
  // Add more tests if needed to cover different scenarios
126
- });
153
+ });