hd-wallet-ui 1.1.1 → 1.1.3
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 +21 -16
- package/src/template.js +71 -49
- package/styles/main.css +34 -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.3",
|
|
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.3",
|
|
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
|
|
@@ -2585,6 +2586,7 @@ function setupMainAppHandlers() {
|
|
|
2585
2586
|
if (video) {
|
|
2586
2587
|
video.srcObject = cameraStream;
|
|
2587
2588
|
video.style.display = '';
|
|
2589
|
+
await video.play();
|
|
2588
2590
|
}
|
|
2589
2591
|
const preview = $('vcard-photo-preview');
|
|
2590
2592
|
if (preview) {
|
|
@@ -3161,7 +3163,7 @@ function setupTrustHandlers() {
|
|
|
3161
3163
|
}
|
|
3162
3164
|
|
|
3163
3165
|
// Update encryption tab when it becomes active or HD controls change
|
|
3164
|
-
$qa('.modal-tab[data-modal-tab="
|
|
3166
|
+
$qa('.modal-tab[data-modal-tab="encrypt-tab-content"]').forEach(tab => {
|
|
3165
3167
|
tab.addEventListener('click', () => {
|
|
3166
3168
|
if (state.hdRoot) updateEncryptionTab();
|
|
3167
3169
|
});
|
|
@@ -3274,8 +3276,6 @@ function setupTrustHandlers() {
|
|
|
3274
3276
|
$('encrypt-out-iv').textContent = toHexCompact(iv);
|
|
3275
3277
|
$('encrypt-out-salt').textContent = toHexCompact(salt);
|
|
3276
3278
|
$('encrypt-out-sender-pub').textContent = toHexCompact(senderPub);
|
|
3277
|
-
$('encrypt-output-section').style.display = 'block';
|
|
3278
|
-
|
|
3279
3279
|
// Build EME (Encrypted Message Envelope) standard object
|
|
3280
3280
|
currentEME = new EMET(
|
|
3281
3281
|
Array.from(ciphertext), // ENCRYPTED_BLOB
|
|
@@ -3293,8 +3293,9 @@ function setupTrustHandlers() {
|
|
|
3293
3293
|
|
|
3294
3294
|
updateBundleDisplay();
|
|
3295
3295
|
|
|
3296
|
-
//
|
|
3297
|
-
$('
|
|
3296
|
+
// Switch to result step
|
|
3297
|
+
$('encrypt-step-compose').style.display = 'none';
|
|
3298
|
+
$('encrypt-step-result').style.display = 'block';
|
|
3298
3299
|
} catch (err) {
|
|
3299
3300
|
console.error('Encryption failed:', err);
|
|
3300
3301
|
alert('Encryption failed: ' + err.message);
|
|
@@ -3391,7 +3392,10 @@ function setupTrustHandlers() {
|
|
|
3391
3392
|
const decStr = new TextDecoder().decode(decrypted);
|
|
3392
3393
|
|
|
3393
3394
|
$('decrypt-result-value').textContent = decStr;
|
|
3394
|
-
|
|
3395
|
+
|
|
3396
|
+
// Switch to result step
|
|
3397
|
+
$('decrypt-step-input').style.display = 'none';
|
|
3398
|
+
$('decrypt-step-result').style.display = 'block';
|
|
3395
3399
|
} catch (err) {
|
|
3396
3400
|
console.error('Decryption failed:', err);
|
|
3397
3401
|
alert('Decryption failed: ' + err.message);
|
|
@@ -3404,15 +3408,16 @@ function setupTrustHandlers() {
|
|
|
3404
3408
|
if (btn) btn.disabled = !$('decrypt-payload')?.value?.trim();
|
|
3405
3409
|
});
|
|
3406
3410
|
|
|
3407
|
-
//
|
|
3408
|
-
$('encrypt-
|
|
3409
|
-
$('encrypt-
|
|
3410
|
-
$('encrypt-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
$('decrypt-
|
|
3411
|
+
// Back button: encrypt result -> compose
|
|
3412
|
+
$('encrypt-back-btn')?.addEventListener('click', () => {
|
|
3413
|
+
$('encrypt-step-result').style.display = 'none';
|
|
3414
|
+
$('encrypt-step-compose').style.display = 'block';
|
|
3415
|
+
});
|
|
3416
|
+
|
|
3417
|
+
// Back button: decrypt result -> input
|
|
3418
|
+
$('decrypt-back-btn')?.addEventListener('click', () => {
|
|
3419
|
+
$('decrypt-step-result').style.display = 'none';
|
|
3420
|
+
$('decrypt-step-input').style.display = 'block';
|
|
3416
3421
|
});
|
|
3417
3422
|
}
|
|
3418
3423
|
|
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
|
@@ -142,6 +142,10 @@ body {
|
|
|
142
142
|
border-bottom: 1px solid var(--glass-border);
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
body:has(.modal.active) {
|
|
146
|
+
overflow: hidden;
|
|
147
|
+
}
|
|
148
|
+
|
|
145
149
|
body:has(.modal.active) .nav-bar {
|
|
146
150
|
z-index: 1;
|
|
147
151
|
}
|
|
@@ -4628,6 +4632,24 @@ a.chain-card:hover {
|
|
|
4628
4632
|
margin-top: 10px;
|
|
4629
4633
|
}
|
|
4630
4634
|
|
|
4635
|
+
.encrypt-step-header {
|
|
4636
|
+
display: flex;
|
|
4637
|
+
align-items: center;
|
|
4638
|
+
gap: 12px;
|
|
4639
|
+
margin-bottom: 16px;
|
|
4640
|
+
}
|
|
4641
|
+
|
|
4642
|
+
.encrypt-step-header .section-label {
|
|
4643
|
+
margin: 0;
|
|
4644
|
+
}
|
|
4645
|
+
|
|
4646
|
+
.encrypt-back-btn {
|
|
4647
|
+
display: inline-flex;
|
|
4648
|
+
align-items: center;
|
|
4649
|
+
gap: 4px;
|
|
4650
|
+
flex-shrink: 0;
|
|
4651
|
+
}
|
|
4652
|
+
|
|
4631
4653
|
.encrypt-output-section {
|
|
4632
4654
|
margin-bottom: 24px;
|
|
4633
4655
|
padding: 16px;
|
|
@@ -4663,6 +4685,18 @@ a.chain-card:hover {
|
|
|
4663
4685
|
flex: 1;
|
|
4664
4686
|
min-width: 0;
|
|
4665
4687
|
}
|
|
4688
|
+
.encrypt-field .copy-btn {
|
|
4689
|
+
background: none;
|
|
4690
|
+
border: none;
|
|
4691
|
+
padding: 4px;
|
|
4692
|
+
cursor: pointer;
|
|
4693
|
+
color: var(--white-30);
|
|
4694
|
+
flex-shrink: 0;
|
|
4695
|
+
transition: color 0.2s;
|
|
4696
|
+
}
|
|
4697
|
+
.encrypt-field .copy-btn:hover {
|
|
4698
|
+
color: var(--white);
|
|
4699
|
+
}
|
|
4666
4700
|
.encrypt-bundle-group {
|
|
4667
4701
|
margin-top: 12px;
|
|
4668
4702
|
}
|