hd-wallet-ui 1.4.3 → 1.5.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.
- package/package.json +2 -2
- package/src/app.js +52 -55
- package/src/template.js +5 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hd-wallet-ui",
|
|
3
|
-
"version": "1.4
|
|
3
|
+
"version": "1.5.4",
|
|
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",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"buffer": "^6.0.3",
|
|
41
41
|
"flatbuffers": "^25.9.23",
|
|
42
42
|
"flatc-wasm": "^26.1.15",
|
|
43
|
-
"hd-wallet-wasm": "^1.4
|
|
43
|
+
"hd-wallet-wasm": "^1.5.4",
|
|
44
44
|
"qrcode": "^1.5.3",
|
|
45
45
|
"spacedatastandards.org": "^23.3.3-0.3.4",
|
|
46
46
|
"vcard-cryptoperson": "^1.1.11"
|
package/src/app.js
CHANGED
|
@@ -77,6 +77,16 @@ const $ = (id) => {
|
|
|
77
77
|
if (_root !== document) return document.getElementById(id);
|
|
78
78
|
return null;
|
|
79
79
|
};
|
|
80
|
+
|
|
81
|
+
export function normalizeTabHash(rawHash) {
|
|
82
|
+
return String(rawHash || '')
|
|
83
|
+
.replace(/^\/+/g, '')
|
|
84
|
+
.split(/[/?#]/)[0]
|
|
85
|
+
.replace(/[^a-z0-9_-]/gi, '')
|
|
86
|
+
.replace(/-tab$/i, '')
|
|
87
|
+
.toLowerCase();
|
|
88
|
+
}
|
|
89
|
+
|
|
80
90
|
const $q = (sel) => _root.querySelector(sel) || (_root !== document ? document.querySelector(sel) : null);
|
|
81
91
|
const $qa = (sel) => {
|
|
82
92
|
const list = _root.querySelectorAll(sel);
|
|
@@ -497,26 +507,12 @@ function deriveHDKey(path) {
|
|
|
497
507
|
}
|
|
498
508
|
}
|
|
499
509
|
|
|
500
|
-
function
|
|
501
|
-
if (!state.hdRoot
|
|
510
|
+
function deriveAccountPeerId() {
|
|
511
|
+
if (!state.hdRoot) return null;
|
|
502
512
|
try {
|
|
503
|
-
|
|
504
|
-
const derived = state.hdRoot.derivePath(path);
|
|
505
|
-
let pubKey, curve;
|
|
506
|
-
if (acct.coinType === 501) {
|
|
507
|
-
pubKey = ed25519.getPublicKey(derived.privateKey());
|
|
508
|
-
curve = Curve.ED25519;
|
|
509
|
-
} else {
|
|
510
|
-
pubKey = derived.publicKey();
|
|
511
|
-
curve = Curve.SECP256K1;
|
|
512
|
-
}
|
|
513
|
-
const peerIdBytes = state.hdWalletModule.libp2p.peerIdFromPublicKey(pubKey, curve);
|
|
514
|
-
return {
|
|
515
|
-
peerIdStr: state.hdWalletModule.libp2p.peerIdToString(peerIdBytes),
|
|
516
|
-
ipnsHash: state.hdWalletModule.libp2p.ipnsHash(peerIdBytes),
|
|
517
|
-
};
|
|
513
|
+
return state.hdRoot.peerIdString();
|
|
518
514
|
} catch (e) {
|
|
519
|
-
console.warn('Failed to derive
|
|
515
|
+
console.warn('Failed to derive account PeerID:', e);
|
|
520
516
|
return null;
|
|
521
517
|
}
|
|
522
518
|
}
|
|
@@ -1629,18 +1625,6 @@ async function showReceiveModal(acct) {
|
|
|
1629
1625
|
<h4 id="wallet-receive-title" class="section-label"></h4>
|
|
1630
1626
|
<canvas id="wallet-receive-qr"></canvas>
|
|
1631
1627
|
<code id="wallet-receive-address" class="wallet-receive-address"></code>
|
|
1632
|
-
<div id="wallet-receive-peer-section" class="wallet-receive-peer-section" style="display:none">
|
|
1633
|
-
<div class="wallet-receive-field">
|
|
1634
|
-
<span class="wallet-receive-field-label">PeerID</span>
|
|
1635
|
-
<code id="wallet-receive-peerid" class="wallet-receive-field-value"></code>
|
|
1636
|
-
<button id="wallet-receive-copy-peerid" class="glass-btn small">Copy</button>
|
|
1637
|
-
</div>
|
|
1638
|
-
<div class="wallet-receive-field">
|
|
1639
|
-
<span class="wallet-receive-field-label">IPNS</span>
|
|
1640
|
-
<code id="wallet-receive-ipns" class="wallet-receive-field-value"></code>
|
|
1641
|
-
<button id="wallet-receive-copy-ipns" class="glass-btn small">Copy</button>
|
|
1642
|
-
</div>
|
|
1643
|
-
</div>
|
|
1644
1628
|
<div class="wallet-receive-actions">
|
|
1645
1629
|
<button id="wallet-receive-copy" class="glass-btn small">Copy Address</button>
|
|
1646
1630
|
<button id="wallet-receive-close" class="glass-btn small">Close</button>
|
|
@@ -1655,18 +1639,6 @@ async function showReceiveModal(acct) {
|
|
|
1655
1639
|
if (titleEl) titleEl.textContent = `Receive ${acct.name}`;
|
|
1656
1640
|
if (addrEl) addrEl.textContent = acct.address;
|
|
1657
1641
|
|
|
1658
|
-
const peerSection = overlay.querySelector('#wallet-receive-peer-section');
|
|
1659
|
-
const peerIdEl = overlay.querySelector('#wallet-receive-peerid');
|
|
1660
|
-
const ipnsEl = overlay.querySelector('#wallet-receive-ipns');
|
|
1661
|
-
const peerInfo = derivePeerInfo(acct);
|
|
1662
|
-
if (peerInfo && peerSection) {
|
|
1663
|
-
peerSection.style.display = '';
|
|
1664
|
-
if (peerIdEl) peerIdEl.textContent = peerInfo.peerIdStr;
|
|
1665
|
-
if (ipnsEl) ipnsEl.textContent = peerInfo.ipnsHash;
|
|
1666
|
-
} else if (peerSection) {
|
|
1667
|
-
peerSection.style.display = 'none';
|
|
1668
|
-
}
|
|
1669
|
-
|
|
1670
1642
|
try {
|
|
1671
1643
|
const qrCanvas = overlay.querySelector('#wallet-receive-qr');
|
|
1672
1644
|
if (qrCanvas) {
|
|
@@ -1689,16 +1661,6 @@ async function showReceiveModal(acct) {
|
|
|
1689
1661
|
overlay.querySelector('#wallet-receive-close')?.addEventListener('click', () => {
|
|
1690
1662
|
overlay.style.display = 'none';
|
|
1691
1663
|
}, { once: true });
|
|
1692
|
-
|
|
1693
|
-
overlay.querySelector('#wallet-receive-copy-peerid')?.addEventListener('click', () => {
|
|
1694
|
-
const val = overlay.querySelector('#wallet-receive-peerid')?.textContent;
|
|
1695
|
-
if (val) navigator.clipboard.writeText(val).catch(() => {});
|
|
1696
|
-
}, { once: true });
|
|
1697
|
-
|
|
1698
|
-
overlay.querySelector('#wallet-receive-copy-ipns')?.addEventListener('click', () => {
|
|
1699
|
-
const val = overlay.querySelector('#wallet-receive-ipns')?.textContent;
|
|
1700
|
-
if (val) navigator.clipboard.writeText(val).catch(() => {});
|
|
1701
|
-
}, { once: true });
|
|
1702
1664
|
}
|
|
1703
1665
|
|
|
1704
1666
|
// =============================================================================
|
|
@@ -2537,6 +2499,7 @@ function login(keys) {
|
|
|
2537
2499
|
const xpub = state.hdRoot.toXpub();
|
|
2538
2500
|
_onLoginCallback({
|
|
2539
2501
|
xpub,
|
|
2502
|
+
peerId: deriveAccountPeerId(),
|
|
2540
2503
|
signingPublicKey: sdnPubKey,
|
|
2541
2504
|
async sign(message) {
|
|
2542
2505
|
const msgBytes = typeof message === 'string'
|
|
@@ -2594,6 +2557,16 @@ function login(keys) {
|
|
|
2594
2557
|
if (walletTabXpubEl) {
|
|
2595
2558
|
setTruncatedValue(walletTabXpubEl, state.hdRoot.toXpub() || 'N/A');
|
|
2596
2559
|
}
|
|
2560
|
+
// Populate wallet tab PeerID display
|
|
2561
|
+
const walletTabPeerIdEl = $('wallet-tab-peerid');
|
|
2562
|
+
const peerIdRow = $('ph-portfolio-peerid-row');
|
|
2563
|
+
if (walletTabPeerIdEl && peerIdRow) {
|
|
2564
|
+
const peerIdStr = deriveAccountPeerId();
|
|
2565
|
+
if (peerIdStr) {
|
|
2566
|
+
setTruncatedValue(walletTabPeerIdEl, peerIdStr);
|
|
2567
|
+
peerIdRow.style.display = '';
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2597
2570
|
populateAccountAddressDropdown();
|
|
2598
2571
|
if (xprvEl) {
|
|
2599
2572
|
xprvEl.textContent = 'Hidden (click reveal)';
|
|
@@ -2857,6 +2830,27 @@ function populateAccountAddressDropdown() {
|
|
|
2857
2830
|
}
|
|
2858
2831
|
};
|
|
2859
2832
|
}
|
|
2833
|
+
|
|
2834
|
+
// Populate PeerID row (derived from account-level secp256k1 key)
|
|
2835
|
+
const peerIdStr = deriveAccountPeerId();
|
|
2836
|
+
const peerIdRow = $('account-peerid-row');
|
|
2837
|
+
const peerIdEl = $('account-peerid-display');
|
|
2838
|
+
if (peerIdStr && peerIdRow && peerIdEl) {
|
|
2839
|
+
peerIdRow.style.display = '';
|
|
2840
|
+
peerIdEl.textContent = `${peerIdStr.slice(0,8)}...${peerIdStr.slice(-8)}`;
|
|
2841
|
+
peerIdEl.title = peerIdStr;
|
|
2842
|
+
}
|
|
2843
|
+
const peerCopyBtn = $('account-peerid-copy');
|
|
2844
|
+
if (peerCopyBtn) {
|
|
2845
|
+
peerCopyBtn.onclick = () => {
|
|
2846
|
+
if (peerIdStr) {
|
|
2847
|
+
navigator.clipboard.writeText(peerIdStr).then(() => {
|
|
2848
|
+
peerCopyBtn.title = 'Copied!';
|
|
2849
|
+
setTimeout(() => { peerCopyBtn.title = 'Copy PeerID'; }, 1500);
|
|
2850
|
+
});
|
|
2851
|
+
}
|
|
2852
|
+
};
|
|
2853
|
+
}
|
|
2860
2854
|
}
|
|
2861
2855
|
|
|
2862
2856
|
function populateWalletAddresses() {
|
|
@@ -4581,6 +4575,8 @@ function setupMainAppHandlers() {
|
|
|
4581
4575
|
let value = '';
|
|
4582
4576
|
if (targetId === 'wallet-xpub' || targetId === 'wallet-tab-xpub') {
|
|
4583
4577
|
value = state.hdRoot?.toXpub?.() || '';
|
|
4578
|
+
} else if (targetId === 'wallet-tab-peerid') {
|
|
4579
|
+
value = deriveAccountPeerId() || '';
|
|
4584
4580
|
} else if (targetId === 'wallet-xprv') {
|
|
4585
4581
|
if (targetEl.dataset.revealed !== 'true') {
|
|
4586
4582
|
alert('Reveal the xprv first to copy it.');
|
|
@@ -5839,14 +5835,15 @@ export async function init(rootElement, options = {}) {
|
|
|
5839
5835
|
|
|
5840
5836
|
// Handle initial hash navigation
|
|
5841
5837
|
const initialHash = window.location.hash.slice(1);
|
|
5842
|
-
|
|
5843
|
-
|
|
5838
|
+
const normalizedTab = normalizeTabHash(initialHash);
|
|
5839
|
+
if (normalizedTab) {
|
|
5840
|
+
const tabEl = $(`${normalizedTab}-tab`);
|
|
5844
5841
|
if (tabEl) {
|
|
5845
5842
|
setTimeout(() => {
|
|
5846
5843
|
tabEl.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
5847
5844
|
$qa('.nav-link[data-tab]').forEach(link => {
|
|
5848
5845
|
link.classList.remove('active');
|
|
5849
|
-
if (link.dataset.tab ===
|
|
5846
|
+
if (link.dataset.tab === normalizedTab) {
|
|
5850
5847
|
link.classList.add('active');
|
|
5851
5848
|
}
|
|
5852
5849
|
});
|
package/src/template.js
CHANGED
|
@@ -3,7 +3,7 @@ export function getModalHTML() {
|
|
|
3
3
|
<!-- Keys Modal -->
|
|
4
4
|
<div id="keys-modal" class="modal">
|
|
5
5
|
<div class="modal-glass modal-wide">
|
|
6
|
-
<div class="modal-header"><div class="account-header-info"><div class="account-header-top"><h3>Account</h3><h3 class="account-total-value" id="account-total-value"></h3></div><div class="account-address-row"><span class="account-address-label">xpub</span><code class="account-address-display" id="account-address-display"></code><button class="account-address-copy" id="account-address-copy" title="Copy xpub"><svg width="12" height="12" 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"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button></div></div><button class="modal-close">×</button></div>
|
|
6
|
+
<div class="modal-header"><div class="account-header-info"><div class="account-header-top"><h3>Account</h3><h3 class="account-total-value" id="account-total-value"></h3></div><div class="account-address-row"><span class="account-address-label">xpub</span><code class="account-address-display" id="account-address-display"></code><button class="account-address-copy" id="account-address-copy" title="Copy xpub"><svg width="12" height="12" 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"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button></div><div class="account-address-row" id="account-peerid-row" style="display:none"><span class="account-address-label">PeerID</span><code class="account-address-display" id="account-peerid-display"></code><button class="account-address-copy" id="account-peerid-copy" title="Copy PeerID"><svg width="12" height="12" 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"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button></div></div><button class="modal-close">×</button></div>
|
|
7
7
|
<div class="modal-tabs">
|
|
8
8
|
<button class="modal-tab active" data-modal-tab="vcard-tab-content">Identity</button>
|
|
9
9
|
<button class="modal-tab" data-modal-tab="trust-tab-content">Trust Map</button>
|
|
@@ -23,6 +23,10 @@ export function getModalHTML() {
|
|
|
23
23
|
<code id="wallet-tab-xpub" class="ph-xpub-text truncate"></code>
|
|
24
24
|
<button class="ph-xpub-copy copy-key-btn" data-copy="wallet-tab-xpub" title="Copy xPub"><svg width="12" height="12" 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"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button>
|
|
25
25
|
</div>
|
|
26
|
+
<div class="ph-portfolio-xpub" id="ph-portfolio-peerid-row" style="display:none">
|
|
27
|
+
<code id="wallet-tab-peerid" class="ph-xpub-text truncate"></code>
|
|
28
|
+
<button class="ph-xpub-copy copy-key-btn" data-copy="wallet-tab-peerid" title="Copy PeerID"><svg width="12" height="12" 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"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button>
|
|
29
|
+
</div>
|
|
26
30
|
</div>
|
|
27
31
|
|
|
28
32
|
<div class="wallet-selector-row">
|