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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hd-wallet-ui",
3
- "version": "1.4.3",
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.3",
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 derivePeerInfo(acct) {
501
- if (!state.hdRoot || !state.hdWalletModule) return null;
510
+ function deriveAccountPeerId() {
511
+ if (!state.hdRoot) return null;
502
512
  try {
503
- const path = acct.path || buildSigningPath(acct.coinType, acct.account, acct.index);
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 peer info:', e);
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
- if (initialHash) {
5843
- const tabEl = $(`${initialHash}-tab`);
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 === initialHash) {
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">&times;</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">&times;</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">