hd-wallet-ui 1.1.1 → 1.1.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.
- package/package.json +2 -2
- package/src/app.js +20 -16
- package/src/template.js +71 -49
- package/styles/main.css +30 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hd-wallet-ui",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "HD Wallet modal UI — login, keys, identity, trust map, and security bond. Attach to any button in your app.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/app.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"bip39": "^3.1.0",
|
|
35
35
|
"buffer": "^6.0.3",
|
|
36
36
|
"flatbuffers": "^25.9.23",
|
|
37
|
-
"hd-wallet-wasm": "^1.1.
|
|
37
|
+
"hd-wallet-wasm": "^1.1.2",
|
|
38
38
|
"qrcode": "^1.5.3",
|
|
39
39
|
"vcard-cryptoperson": "^1.1.10"
|
|
40
40
|
},
|
package/src/app.js
CHANGED
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
coinTypeToConfig,
|
|
39
39
|
buildSigningPath,
|
|
40
40
|
buildEncryptionPath,
|
|
41
|
+
PKI_STORAGE_KEY,
|
|
41
42
|
} from './constants.js';
|
|
42
43
|
|
|
43
44
|
import {
|
|
@@ -1630,7 +1631,7 @@ async function updateAdversarialSecurity() {
|
|
|
1630
1631
|
// Update account header total value
|
|
1631
1632
|
const accountTotalEl = $('account-total-value');
|
|
1632
1633
|
if (accountTotalEl) {
|
|
1633
|
-
accountTotalEl.textContent = '
|
|
1634
|
+
accountTotalEl.textContent = 'Bond: ' + formatCurrencyValue(totalConverted, currency);
|
|
1634
1635
|
}
|
|
1635
1636
|
|
|
1636
1637
|
// Update account address dropdown values
|
|
@@ -3161,7 +3162,7 @@ function setupTrustHandlers() {
|
|
|
3161
3162
|
}
|
|
3162
3163
|
|
|
3163
3164
|
// Update encryption tab when it becomes active or HD controls change
|
|
3164
|
-
$qa('.modal-tab[data-modal-tab="
|
|
3165
|
+
$qa('.modal-tab[data-modal-tab="encrypt-tab-content"]').forEach(tab => {
|
|
3165
3166
|
tab.addEventListener('click', () => {
|
|
3166
3167
|
if (state.hdRoot) updateEncryptionTab();
|
|
3167
3168
|
});
|
|
@@ -3274,8 +3275,6 @@ function setupTrustHandlers() {
|
|
|
3274
3275
|
$('encrypt-out-iv').textContent = toHexCompact(iv);
|
|
3275
3276
|
$('encrypt-out-salt').textContent = toHexCompact(salt);
|
|
3276
3277
|
$('encrypt-out-sender-pub').textContent = toHexCompact(senderPub);
|
|
3277
|
-
$('encrypt-output-section').style.display = 'block';
|
|
3278
|
-
|
|
3279
3278
|
// Build EME (Encrypted Message Envelope) standard object
|
|
3280
3279
|
currentEME = new EMET(
|
|
3281
3280
|
Array.from(ciphertext), // ENCRYPTED_BLOB
|
|
@@ -3293,8 +3292,9 @@ function setupTrustHandlers() {
|
|
|
3293
3292
|
|
|
3294
3293
|
updateBundleDisplay();
|
|
3295
3294
|
|
|
3296
|
-
//
|
|
3297
|
-
$('
|
|
3295
|
+
// Switch to result step
|
|
3296
|
+
$('encrypt-step-compose').style.display = 'none';
|
|
3297
|
+
$('encrypt-step-result').style.display = 'block';
|
|
3298
3298
|
} catch (err) {
|
|
3299
3299
|
console.error('Encryption failed:', err);
|
|
3300
3300
|
alert('Encryption failed: ' + err.message);
|
|
@@ -3391,7 +3391,10 @@ function setupTrustHandlers() {
|
|
|
3391
3391
|
const decStr = new TextDecoder().decode(decrypted);
|
|
3392
3392
|
|
|
3393
3393
|
$('decrypt-result-value').textContent = decStr;
|
|
3394
|
-
|
|
3394
|
+
|
|
3395
|
+
// Switch to result step
|
|
3396
|
+
$('decrypt-step-input').style.display = 'none';
|
|
3397
|
+
$('decrypt-step-result').style.display = 'block';
|
|
3395
3398
|
} catch (err) {
|
|
3396
3399
|
console.error('Decryption failed:', err);
|
|
3397
3400
|
alert('Decryption failed: ' + err.message);
|
|
@@ -3404,15 +3407,16 @@ function setupTrustHandlers() {
|
|
|
3404
3407
|
if (btn) btn.disabled = !$('decrypt-payload')?.value?.trim();
|
|
3405
3408
|
});
|
|
3406
3409
|
|
|
3407
|
-
//
|
|
3408
|
-
$('encrypt-
|
|
3409
|
-
$('encrypt-
|
|
3410
|
-
$('encrypt-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
$('decrypt-
|
|
3410
|
+
// Back button: encrypt result -> compose
|
|
3411
|
+
$('encrypt-back-btn')?.addEventListener('click', () => {
|
|
3412
|
+
$('encrypt-step-result').style.display = 'none';
|
|
3413
|
+
$('encrypt-step-compose').style.display = 'block';
|
|
3414
|
+
});
|
|
3415
|
+
|
|
3416
|
+
// Back button: decrypt result -> input
|
|
3417
|
+
$('decrypt-back-btn')?.addEventListener('click', () => {
|
|
3418
|
+
$('decrypt-step-result').style.display = 'none';
|
|
3419
|
+
$('decrypt-step-input').style.display = 'block';
|
|
3416
3420
|
});
|
|
3417
3421
|
}
|
|
3418
3422
|
|
package/src/template.js
CHANGED
|
@@ -8,8 +8,9 @@ export function getModalHTML() {
|
|
|
8
8
|
<button class="modal-tab active" data-modal-tab="vcard-tab-content">Identity</button>
|
|
9
9
|
<button class="modal-tab" data-modal-tab="keys-tab-content">Keys</button>
|
|
10
10
|
<button class="modal-tab" data-modal-tab="trust-tab-content">Trust Map</button>
|
|
11
|
-
<button class="modal-tab" data-modal-tab="bond-tab-content">
|
|
12
|
-
<button class="modal-tab" data-modal-tab="
|
|
11
|
+
<button class="modal-tab" data-modal-tab="bond-tab-content">Bond</button>
|
|
12
|
+
<button class="modal-tab" data-modal-tab="encrypt-tab-content">Encrypt</button>
|
|
13
|
+
<button class="modal-tab" data-modal-tab="decrypt-tab-content">Decrypt</button>
|
|
13
14
|
</div>
|
|
14
15
|
<div class="modal-body">
|
|
15
16
|
<div id="keys-tab-content" class="modal-tab-content">
|
|
@@ -272,57 +273,62 @@ export function getModalHTML() {
|
|
|
272
273
|
</div>
|
|
273
274
|
</div>
|
|
274
275
|
|
|
275
|
-
<!--
|
|
276
|
-
<div id="
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
<
|
|
280
|
-
|
|
276
|
+
<!-- Encrypt Tab -->
|
|
277
|
+
<div id="encrypt-tab-content" class="modal-tab-content">
|
|
278
|
+
<!-- Step 1: Compose -->
|
|
279
|
+
<div id="encrypt-step-compose" class="encrypt-step">
|
|
280
|
+
<div class="encrypt-tab-intro">
|
|
281
|
+
<h4 class="section-label">Encrypt a Message</h4>
|
|
282
|
+
<p>ECDH key agreement + HKDF + AES-256-GCM (ECIES)</p>
|
|
283
|
+
</div>
|
|
281
284
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
</div>
|
|
297
|
-
<div class="encrypt-key-card glass-card">
|
|
298
|
-
<div class="encrypt-key-header">
|
|
299
|
-
<span class="encrypt-role-badge recipient">Recipient</span>
|
|
285
|
+
<div class="encrypt-keys-section">
|
|
286
|
+
<div class="encrypt-key-row">
|
|
287
|
+
<div class="encrypt-key-card glass-card">
|
|
288
|
+
<div class="encrypt-key-header">
|
|
289
|
+
<span class="encrypt-role-badge sender">Sender (You)</span>
|
|
290
|
+
</div>
|
|
291
|
+
<div class="encrypt-key-detail">
|
|
292
|
+
<label>Encryption Public Key</label>
|
|
293
|
+
<code id="encrypt-sender-pubkey" class="truncate">--</code>
|
|
294
|
+
</div>
|
|
295
|
+
<div class="encrypt-key-detail">
|
|
296
|
+
<label>Derivation Path</label>
|
|
297
|
+
<code id="encrypt-sender-path">--</code>
|
|
298
|
+
</div>
|
|
300
299
|
</div>
|
|
301
|
-
<div class="encrypt-key-
|
|
302
|
-
<
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
300
|
+
<div class="encrypt-key-card glass-card">
|
|
301
|
+
<div class="encrypt-key-header">
|
|
302
|
+
<span class="encrypt-role-badge recipient">Recipient</span>
|
|
303
|
+
</div>
|
|
304
|
+
<div class="encrypt-key-detail">
|
|
305
|
+
<label>Recipient Public Key (hex)</label>
|
|
306
|
+
<div class="encrypt-recipient-input-row">
|
|
307
|
+
<input type="text" id="encrypt-recipient-pubkey" class="glass-input compact" placeholder="Paste recipient's secp256k1 public key (hex)">
|
|
308
|
+
<button id="encrypt-use-self" class="glass-btn small" title="Use your own key (for testing)">Self</button>
|
|
309
|
+
</div>
|
|
306
310
|
</div>
|
|
307
311
|
</div>
|
|
308
312
|
</div>
|
|
309
313
|
</div>
|
|
310
|
-
</div>
|
|
311
314
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
<button id="encrypt-clear-btn" class="glass-btn small">Clear</button>
|
|
315
|
+
<div class="encrypt-message-section">
|
|
316
|
+
<div class="encrypt-input-group">
|
|
317
|
+
<label class="section-label">Message</label>
|
|
318
|
+
<textarea id="encrypt-plaintext" class="glass-input glass-textarea" rows="3" placeholder="Enter a message to encrypt..."></textarea>
|
|
319
|
+
</div>
|
|
320
|
+
<div class="encrypt-actions">
|
|
321
|
+
<button id="encrypt-btn" class="glass-btn primary" disabled>Encrypt</button>
|
|
322
|
+
</div>
|
|
321
323
|
</div>
|
|
322
324
|
</div>
|
|
323
325
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
+
<!-- Step 2: Result (replaces compose) -->
|
|
327
|
+
<div id="encrypt-step-result" class="encrypt-step" style="display:none;">
|
|
328
|
+
<div class="encrypt-step-header">
|
|
329
|
+
<button id="encrypt-back-btn" class="glass-btn small encrypt-back-btn"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 12H5M12 19l-7-7 7-7"/></svg> Back</button>
|
|
330
|
+
<h4 class="section-label">Encrypted Payload</h4>
|
|
331
|
+
</div>
|
|
326
332
|
<div class="encrypt-output-fields">
|
|
327
333
|
<div class="encrypt-field"><label>Ciphertext</label><code id="encrypt-out-ciphertext" class="encrypt-out-value truncate"></code><button class="copy-btn" data-copy="encrypt-out-ciphertext" title="Copy"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg></button></div>
|
|
328
334
|
<div class="encrypt-field"><label>Auth Tag</label><code id="encrypt-out-tag" class="encrypt-out-value truncate"></code></div>
|
|
@@ -348,13 +354,29 @@ export function getModalHTML() {
|
|
|
348
354
|
</div>
|
|
349
355
|
</div>
|
|
350
356
|
</div>
|
|
357
|
+
</div>
|
|
351
358
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
<div
|
|
357
|
-
<label>
|
|
359
|
+
<!-- Decrypt Tab -->
|
|
360
|
+
<div id="decrypt-tab-content" class="modal-tab-content">
|
|
361
|
+
<!-- Step 1: Input -->
|
|
362
|
+
<div id="decrypt-step-input" class="encrypt-step">
|
|
363
|
+
<div class="encrypt-tab-intro">
|
|
364
|
+
<h4 class="section-label">Decrypt a Message</h4>
|
|
365
|
+
<p>Paste an EME payload (JSON or base64 FlatBuffer) to decrypt with your key.</p>
|
|
366
|
+
</div>
|
|
367
|
+
<textarea id="decrypt-payload" class="glass-input glass-textarea" rows="6" placeholder='Paste EME JSON or base64 FlatBuffer here...'></textarea>
|
|
368
|
+
<div class="encrypt-actions">
|
|
369
|
+
<button id="decrypt-btn" class="glass-btn primary" disabled>Decrypt</button>
|
|
370
|
+
</div>
|
|
371
|
+
</div>
|
|
372
|
+
|
|
373
|
+
<!-- Step 2: Result (replaces input) -->
|
|
374
|
+
<div id="decrypt-step-result" class="encrypt-step" style="display:none;">
|
|
375
|
+
<div class="encrypt-step-header">
|
|
376
|
+
<button id="decrypt-back-btn" class="glass-btn small encrypt-back-btn"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 12H5M12 19l-7-7 7-7"/></svg> Back</button>
|
|
377
|
+
<h4 class="section-label">Decrypted Message</h4>
|
|
378
|
+
</div>
|
|
379
|
+
<div class="decrypt-result">
|
|
358
380
|
<div class="decrypt-result-value" id="decrypt-result-value"></div>
|
|
359
381
|
</div>
|
|
360
382
|
</div>
|
package/styles/main.css
CHANGED
|
@@ -4628,6 +4628,24 @@ a.chain-card:hover {
|
|
|
4628
4628
|
margin-top: 10px;
|
|
4629
4629
|
}
|
|
4630
4630
|
|
|
4631
|
+
.encrypt-step-header {
|
|
4632
|
+
display: flex;
|
|
4633
|
+
align-items: center;
|
|
4634
|
+
gap: 12px;
|
|
4635
|
+
margin-bottom: 16px;
|
|
4636
|
+
}
|
|
4637
|
+
|
|
4638
|
+
.encrypt-step-header .section-label {
|
|
4639
|
+
margin: 0;
|
|
4640
|
+
}
|
|
4641
|
+
|
|
4642
|
+
.encrypt-back-btn {
|
|
4643
|
+
display: inline-flex;
|
|
4644
|
+
align-items: center;
|
|
4645
|
+
gap: 4px;
|
|
4646
|
+
flex-shrink: 0;
|
|
4647
|
+
}
|
|
4648
|
+
|
|
4631
4649
|
.encrypt-output-section {
|
|
4632
4650
|
margin-bottom: 24px;
|
|
4633
4651
|
padding: 16px;
|
|
@@ -4663,6 +4681,18 @@ a.chain-card:hover {
|
|
|
4663
4681
|
flex: 1;
|
|
4664
4682
|
min-width: 0;
|
|
4665
4683
|
}
|
|
4684
|
+
.encrypt-field .copy-btn {
|
|
4685
|
+
background: none;
|
|
4686
|
+
border: none;
|
|
4687
|
+
padding: 4px;
|
|
4688
|
+
cursor: pointer;
|
|
4689
|
+
color: var(--white-30);
|
|
4690
|
+
flex-shrink: 0;
|
|
4691
|
+
transition: color 0.2s;
|
|
4692
|
+
}
|
|
4693
|
+
.encrypt-field .copy-btn:hover {
|
|
4694
|
+
color: var(--white);
|
|
4695
|
+
}
|
|
4666
4696
|
.encrypt-bundle-group {
|
|
4667
4697
|
margin-top: 12px;
|
|
4668
4698
|
}
|