hd-wallet-ui 2.0.10 → 2.0.12

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": "2.0.10",
3
+ "version": "2.0.12",
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.32",
43
- "hd-wallet-wasm": "^2.0.10",
43
+ "hd-wallet-wasm": "^2.0.12",
44
44
  "qrcode": "^1.5.3",
45
45
  "spacedatastandards.org": "^1.93.3",
46
46
  "vcard-cryptoperson": "^1.1.11"
package/src/app.js CHANGED
@@ -841,7 +841,9 @@ function renderWalletSelector() {
841
841
  const option = document.createElement('option');
842
842
  option.value = String(wallet.id);
843
843
  const walletValue = state.walletFiatTotals[wallet.id] ?? 0;
844
- option.textContent = `${wallet.name} (${formatCurrencyValue(walletValue, displayCurrency)})`;
844
+ option.textContent = wallet.id === state.activeWalletId
845
+ ? wallet.name
846
+ : `${wallet.name} (${formatCurrencyValue(walletValue, displayCurrency)})`;
845
847
  select.appendChild(option);
846
848
  });
847
849
  select.value = String(state.activeWalletId);
@@ -850,6 +852,13 @@ function renderWalletSelector() {
850
852
  updateIdentityWalletKeys();
851
853
  }
852
854
 
855
+ function updateWalletBondDisplay(currency = state.walletFiatCurrency || getSelectedCurrency()) {
856
+ const valueEl = $('wallet-bond-value');
857
+ const wallet = getCurrentWallet();
858
+ const walletValue = wallet ? state.walletFiatTotals?.[wallet.id] ?? 0 : 0;
859
+ if (valueEl) valueEl.textContent = formatCurrencyValue(walletValue, currency);
860
+ }
861
+
853
862
  function updateIdentityWalletKeys() {
854
863
  const identity = getCurrentWalletIdentity();
855
864
  const xpubEl = $('identity-wallet-xpub');
@@ -2128,7 +2137,6 @@ async function updateWalletBondTotal() {
2128
2137
  const currency = getSelectedCurrency();
2129
2138
  const prices = await fetchCryptoPrices(currency);
2130
2139
 
2131
- let total = 0;
2132
2140
  const walletTotals = {};
2133
2141
  let hasPositiveBalance = false;
2134
2142
  let missingPriceForFundedAccount = false;
@@ -2145,27 +2153,20 @@ async function updateWalletBondTotal() {
2145
2153
  }
2146
2154
 
2147
2155
  const fiatValue = bal * price;
2148
- total += fiatValue;
2149
2156
  const walletId = getAccountWalletId(acct);
2150
2157
  walletTotals[walletId] = (walletTotals[walletId] || 0) + fiatValue;
2151
2158
  }
2152
2159
 
2153
- if (hasPositiveBalance && total <= 0 && missingPriceForFundedAccount) {
2160
+ const pricedTotal = Object.values(walletTotals).reduce((sum, v) => sum + (Number.isFinite(v) ? v : 0), 0);
2161
+ if (hasPositiveBalance && pricedTotal <= 0 && missingPriceForFundedAccount) {
2154
2162
  throw new Error('Funded accounts found but fiat pricing is unavailable');
2155
2163
  }
2156
2164
 
2157
2165
  state.walletFiatTotals = walletTotals;
2158
2166
  state.walletFiatCurrency = currency;
2159
2167
 
2160
- const formatted = formatCurrencyValue(total, currency);
2161
- if (valueEl) valueEl.textContent = formatted;
2168
+ updateWalletBondDisplay(currency);
2162
2169
  renderWalletSelector();
2163
-
2164
- // Also update the header bond total
2165
- const accountTotalEl = $('account-total-value');
2166
- if (accountTotalEl) {
2167
- accountTotalEl.textContent = 'Bond: ' + formatted;
2168
- }
2169
2170
  } catch (e) {
2170
2171
  console.warn('Bond total calculation failed:', e);
2171
2172
  // Keep last known totals if pricing endpoint is temporarily unavailable.
@@ -2173,10 +2174,7 @@ async function updateWalletBondTotal() {
2173
2174
  const cachedTotal = Object.values(cachedTotals).reduce((sum, v) => sum + (Number.isFinite(v) ? v : 0), 0);
2174
2175
  if (cachedTotal > 0) {
2175
2176
  const displayCurrency = state.walletFiatCurrency || getSelectedCurrency();
2176
- const formatted = formatCurrencyValue(cachedTotal, displayCurrency);
2177
- if (valueEl) valueEl.textContent = formatted;
2178
- const accountTotalEl = $('account-total-value');
2179
- if (accountTotalEl) accountTotalEl.textContent = 'Bond: ' + formatted;
2177
+ updateWalletBondDisplay(displayCurrency);
2180
2178
  } else if (valueEl && !valueEl.textContent) {
2181
2179
  valueEl.textContent = '$0.00';
2182
2180
  }
@@ -4276,7 +4274,7 @@ function setupMainAppHandlers() {
4276
4274
  // Modal close handlers
4277
4275
  $qa('.modal').forEach(modal => {
4278
4276
  modal.addEventListener('click', (e) => {
4279
- if (e.target === modal || e.target.classList.contains('modal-close')) {
4277
+ if (e.target === modal || e.target.closest?.('.modal-close')) {
4280
4278
  modal.classList.remove('active');
4281
4279
  }
4282
4280
  });
@@ -4285,7 +4283,7 @@ function setupMainAppHandlers() {
4285
4283
  // Account modal tab switching
4286
4284
  $qa('.modal-tab[data-modal-tab]').forEach(tab => {
4287
4285
  tab.addEventListener('click', () => {
4288
- $qa('.modal-tab[data-modal-tab]').forEach(t => t.classList.remove('active'));
4286
+ $qa('.modal-tab').forEach(t => t.classList.remove('active'));
4289
4287
  $qa('.modal-tab-content').forEach(c => c.classList.remove('active'));
4290
4288
  tab.classList.add('active');
4291
4289
  const target = $(tab.dataset.modalTab);
@@ -4808,16 +4806,19 @@ function setupMainAppHandlers() {
4808
4806
  closeWalletActionMenus();
4809
4807
  closeAssetActionOverlay();
4810
4808
  renderWalletSelector();
4809
+ updateWalletBondDisplay();
4811
4810
  renderAccountsList();
4812
4811
  updateCustomPathDefault();
4813
4812
  };
4814
4813
  $('account-wallet-select')?.addEventListener('change', handleWalletSelectChange);
4815
4814
  $('wallet-active-select')?.addEventListener('change', handleWalletSelectChange);
4816
- $('account-wallet-manage-btn')?.addEventListener('click', () => {
4815
+ $('wallet-manage-tab')?.addEventListener('click', () => {
4817
4816
  closeWalletActionMenus();
4818
4817
  closeAssetActionOverlay();
4819
- const walletTab = _root.querySelector?.('.modal-tab[data-modal-tab="wallet-tab-content"]');
4820
- if (walletTab) walletTab.click();
4818
+ $qa('.modal-tab').forEach(t => t.classList.remove('active'));
4819
+ $qa('.modal-tab-content').forEach(c => c.classList.remove('active'));
4820
+ $('wallet-manage-tab')?.classList.add('active');
4821
+ $('wallet-tab-content')?.classList.add('active');
4821
4822
  showWalletsView();
4822
4823
  });
4823
4824
  $('wallet-manage-btn')?.addEventListener('click', () => {
package/src/template.js CHANGED
@@ -3,12 +3,13 @@ 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-wallet-row"><select id="account-wallet-select" class="glass-input compact account-wallet-select" aria-label="Select wallet"></select><button id="account-wallet-manage-btn" class="glass-btn small">Manage</button></div></div><button class="modal-close">&times;</button></div>
6
+ <div class="modal-header account-modal-header"><div class="account-header-info"><div class="account-wallet-row"><select id="account-wallet-select" class="glass-input compact account-wallet-select" aria-label="Select wallet"></select></div></div><button class="modal-close account-modal-close" type="button" aria-label="Close"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></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>
10
10
  <button class="modal-tab" data-modal-tab="messaging-tab-content">Messaging</button>
11
11
  <button class="modal-tab" data-modal-tab="wallet-tab-content">Wallet</button>
12
+ <button class="modal-tab" id="wallet-manage-tab" type="button">Manage</button>
12
13
  </div>
13
14
  <div class="modal-body">
14
15
  <!-- Wallet Tab -->
@@ -18,7 +19,7 @@ export function getModalHTML() {
18
19
  <!-- Portfolio Value (Phantom-style hero) -->
19
20
  <div class="ph-portfolio">
20
21
  <div class="ph-portfolio-value" id="wallet-bond-value">$0.00</div>
21
- <div class="ph-portfolio-label">Total Balance</div>
22
+ <div class="ph-portfolio-label">Bond</div>
22
23
  </div>
23
24
 
24
25
  <!-- Action Buttons Row -->
@@ -59,7 +60,7 @@ export function getModalHTML() {
59
60
  <h4 id="wallet-asset-action-title"></h4>
60
61
  <div id="wallet-asset-action-path" class="wallet-asset-action-path"></div>
61
62
  </div>
62
- <button id="wallet-asset-action-close" class="modal-close" type="button">&times;</button>
63
+ <button id="wallet-asset-action-close" class="modal-close" type="button" aria-label="Close"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
63
64
  </div>
64
65
  <code id="wallet-asset-action-address" class="wallet-asset-action-address"></code>
65
66
  <div class="wallet-asset-action-buttons">
@@ -548,9 +549,9 @@ export function getModalHTML() {
548
549
  <!-- Login Modal -->
549
550
  <div id="login-modal" class="modal">
550
551
  <div class="modal-glass login-modal-content">
551
- <div class="modal-header"><h3>Login</h3><button class="modal-close">&times;</button></div>
552
+ <div class="modal-header"><h3>Login</h3><button class="modal-close" type="button" aria-label="Close"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button></div>
552
553
  <div id="wallet-info-box" class="wallet-info-box">
553
- <div id="wallet-info-expanded" class="wallet-info-expanded"><div class="wallet-info-content"><strong>Decentralized Wallet</strong> — Your credentials never leave your browser.</div><button class="wallet-info-close" id="wallet-info-dismiss" title="Dismiss">&times;</button></div>
554
+ <div id="wallet-info-expanded" class="wallet-info-expanded"><div class="wallet-info-content"><strong>Decentralized Wallet</strong> — Your credentials never leave your browser.</div><button class="wallet-info-close" id="wallet-info-dismiss" title="Dismiss" aria-label="Dismiss"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button></div>
554
555
  <div id="wallet-info-collapsed" class="wallet-info-collapsed" style="display:none"><span>Decentralized Wallet</span><div class="wallet-info-icon-wrap"><svg viewBox="0 0 16 16"><circle cx="8" cy="8" r="7" fill="none" stroke="currentColor" stroke-width="0.75"/><text x="8" y="8" text-anchor="middle" dominant-baseline="central" font-size="11" fill="currentColor">i</text></svg></div></div>
555
556
  </div>
556
557
  <div class="modal-body">
package/src/trust-ui.js CHANGED
@@ -19,6 +19,8 @@ import {
19
19
  // Helpers
20
20
  // =============================================================================
21
21
 
22
+ const CLOSE_ICON = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>';
23
+
22
24
  export function truncatePubkey(pubkey, prefixLen = 12, suffixLen = 8) {
23
25
  if (!pubkey) return '';
24
26
  if (pubkey.length <= prefixLen + suffixLen + 3) return pubkey;
@@ -257,7 +259,7 @@ export function showEstablishTrustModal(onConfirm) {
257
259
  <div class="modal-glass">
258
260
  <div class="modal-header">
259
261
  <h3>Establish Trust</h3>
260
- <button class="modal-close">&times;</button>
262
+ <button class="modal-close" type="button" aria-label="Close">${CLOSE_ICON}</button>
261
263
  </div>
262
264
  <div class="modal-body">
263
265
 
@@ -474,7 +476,7 @@ export function showRevokeTrustModal(originalTxHash, onConfirm) {
474
476
  <div class="modal-glass">
475
477
  <div class="modal-header">
476
478
  <h3>Revoke Trust</h3>
477
- <button class="modal-close">&times;</button>
479
+ <button class="modal-close" type="button" aria-label="Close">${CLOSE_ICON}</button>
478
480
  </div>
479
481
  <div class="modal-body">
480
482
  <div class="trust-warning">
@@ -564,7 +566,7 @@ function buildRuleRow(rule, index) {
564
566
  <select class="glass-select rule-severity">${severityOptions}</select>
565
567
  </div>
566
568
  <div class="rule-field rule-field-actions">
567
- <button class="glass-btn glass-btn-sm rule-delete-btn" data-index="${index}" title="Delete rule">&times;</button>
569
+ <button class="glass-btn glass-btn-sm rule-delete-btn" data-index="${index}" title="Delete rule" aria-label="Delete rule"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
568
570
  </div>
569
571
  </div>
570
572
  </div>
@@ -590,7 +592,7 @@ export function showRulesModal(rules, onSave) {
590
592
  <div class="modal-glass">
591
593
  <div class="modal-header">
592
594
  <h3>Trust Rules</h3>
593
- <button class="modal-close">&times;</button>
595
+ <button class="modal-close" type="button" aria-label="Close">${CLOSE_ICON}</button>
594
596
  </div>
595
597
  <div class="modal-body">
596
598
  <div class="rules-list">
package/styles/main.css CHANGED
@@ -1185,11 +1185,6 @@ body:has(.modal.active) .nav-bar {
1185
1185
  user-drag: none;
1186
1186
  }
1187
1187
 
1188
- .modal-header h3 {
1189
- font-size: 18px;
1190
- font-weight: 600;
1191
- }
1192
-
1193
1188
  .account-header-info {
1194
1189
  display: flex;
1195
1190
  flex-direction: column;
@@ -1198,24 +1193,15 @@ body:has(.modal.active) .nav-bar {
1198
1193
  min-width: 0;
1199
1194
  }
1200
1195
 
1201
- .account-header-top {
1202
- display: flex;
1203
- align-items: baseline;
1204
- gap: 12px;
1205
- }
1206
-
1207
- .account-total-value {
1208
- font-weight: 500;
1209
- color: #4ade80;
1210
- letter-spacing: 0.02em;
1211
- opacity: 0.9;
1196
+ .account-modal-header {
1197
+ position: relative;
1198
+ padding-right: 56px;
1212
1199
  }
1213
1200
 
1214
1201
  .account-wallet-row {
1215
1202
  display: flex;
1216
1203
  align-items: center;
1217
1204
  gap: 10px;
1218
- margin-top: 4px;
1219
1205
  width: 100%;
1220
1206
  min-width: 0;
1221
1207
  }
@@ -1236,10 +1222,6 @@ body:has(.modal.active) .nav-bar {
1236
1222
  background-position: right 11px center;
1237
1223
  }
1238
1224
 
1239
- #account-wallet-manage-btn {
1240
- flex: 0 0 auto;
1241
- }
1242
-
1243
1225
  @media (max-width: 600px) {
1244
1226
  .account-wallet-row {
1245
1227
  gap: 8px;
@@ -1263,17 +1245,23 @@ body:has(.modal.active) .nav-bar {
1263
1245
  display: flex;
1264
1246
  align-items: center;
1265
1247
  justify-content: center;
1266
- background: var(--white-10);
1248
+ background: transparent;
1267
1249
  border: none;
1268
- border-radius: 50%;
1269
1250
  color: var(--white);
1270
- font-size: 20px;
1271
1251
  cursor: pointer;
1272
- transition: background 0.2s;
1252
+ padding: 0;
1253
+ transition: color 0.2s, opacity 0.2s;
1273
1254
  }
1274
1255
 
1275
1256
  .modal-close:hover {
1276
- background: var(--white-20);
1257
+ color: var(--white-80);
1258
+ opacity: 0.9;
1259
+ }
1260
+
1261
+ .account-modal-close {
1262
+ position: absolute;
1263
+ top: 12px;
1264
+ right: 14px;
1277
1265
  }
1278
1266
 
1279
1267
  .modal-body {
package/styles/widget.css CHANGED
@@ -1187,11 +1187,6 @@ body:has(#hd-wallet-ui-container .modal.active) #hd-wallet-ui-container .nav-bar
1187
1187
  user-drag: none;
1188
1188
  }
1189
1189
 
1190
- #hd-wallet-ui-container .modal-header h3 {
1191
- font-size: 18px;
1192
- font-weight: 600;
1193
- }
1194
-
1195
1190
  #hd-wallet-ui-container .account-header-info {
1196
1191
  display: flex;
1197
1192
  flex-direction: column;
@@ -1200,24 +1195,15 @@ body:has(#hd-wallet-ui-container .modal.active) #hd-wallet-ui-container .nav-bar
1200
1195
  min-width: 0;
1201
1196
  }
1202
1197
 
1203
- #hd-wallet-ui-container .account-header-top {
1204
- display: flex;
1205
- align-items: baseline;
1206
- gap: 12px;
1207
- }
1208
-
1209
- #hd-wallet-ui-container .account-total-value {
1210
- font-weight: 500;
1211
- color: #4ade80;
1212
- letter-spacing: 0.02em;
1213
- opacity: 0.9;
1198
+ #hd-wallet-ui-container .account-modal-header {
1199
+ position: relative;
1200
+ padding-right: 56px;
1214
1201
  }
1215
1202
 
1216
1203
  #hd-wallet-ui-container .account-wallet-row {
1217
1204
  display: flex;
1218
1205
  align-items: center;
1219
1206
  gap: 10px;
1220
- margin-top: 4px;
1221
1207
  width: 100%;
1222
1208
  min-width: 0;
1223
1209
  }
@@ -1238,10 +1224,6 @@ body:has(#hd-wallet-ui-container .modal.active) #hd-wallet-ui-container .nav-bar
1238
1224
  background-position: right 11px center;
1239
1225
  }
1240
1226
 
1241
- #hd-wallet-ui-container #account-wallet-manage-btn {
1242
- flex: 0 0 auto;
1243
- }
1244
-
1245
1227
  @media (max-width: 600px) {
1246
1228
  #hd-wallet-ui-container .account-wallet-row {
1247
1229
  gap: 8px;
@@ -1265,17 +1247,23 @@ body:has(#hd-wallet-ui-container .modal.active) #hd-wallet-ui-container .nav-bar
1265
1247
  display: flex;
1266
1248
  align-items: center;
1267
1249
  justify-content: center;
1268
- background: var(--white-10);
1250
+ background: transparent;
1269
1251
  border: none;
1270
- border-radius: 50%;
1271
1252
  color: var(--white);
1272
- font-size: 20px;
1273
1253
  cursor: pointer;
1274
- transition: background 0.2s;
1254
+ padding: 0;
1255
+ transition: color 0.2s, opacity 0.2s;
1275
1256
  }
1276
1257
 
1277
1258
  #hd-wallet-ui-container .modal-close:hover {
1278
- background: var(--white-20);
1259
+ color: var(--white-80);
1260
+ opacity: 0.9;
1261
+ }
1262
+
1263
+ #hd-wallet-ui-container .account-modal-close {
1264
+ position: absolute;
1265
+ top: 12px;
1266
+ right: 14px;
1279
1267
  }
1280
1268
 
1281
1269
  #hd-wallet-ui-container .modal-body {