hd-wallet-ui 2.0.18 → 2.0.20
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 +145 -191
- package/src/template.js +57 -44
- package/src/trust-ui.js +4 -6
- package/styles/main.css +83 -201
- package/styles/widget.css +83 -201
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hd-wallet-ui",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.20",
|
|
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.
|
|
43
|
+
"hd-wallet-wasm": "^2.0.20",
|
|
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
|
@@ -526,50 +526,6 @@ function deriveAccountPeerId() {
|
|
|
526
526
|
}
|
|
527
527
|
}
|
|
528
528
|
|
|
529
|
-
function getWalletIdentityPath(wallet = getCurrentWallet()) {
|
|
530
|
-
if (!wallet) return "m/44'/0'/0'";
|
|
531
|
-
return `m/44'/0'/${wallet.accountIndex}'`;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
function getCurrentWalletIdentity(wallet = getCurrentWallet()) {
|
|
535
|
-
if (!state.hdRoot || !wallet) return { xpub: '', peerId: '', path: getWalletIdentityPath(wallet) };
|
|
536
|
-
const path = getWalletIdentityPath(wallet);
|
|
537
|
-
try {
|
|
538
|
-
const accountKey = deriveHDKey(path);
|
|
539
|
-
return {
|
|
540
|
-
xpub: accountKey?.toXpub?.() || '',
|
|
541
|
-
peerId: accountKey?.peerIdString?.() || '',
|
|
542
|
-
path,
|
|
543
|
-
};
|
|
544
|
-
} catch (e) {
|
|
545
|
-
console.warn('Failed to derive wallet identity keys:', e);
|
|
546
|
-
return { xpub: '', peerId: '', path };
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
function getCurrentWalletSigningAccounts(wallet = getCurrentWallet()) {
|
|
551
|
-
if (!wallet) return [];
|
|
552
|
-
return state.activeAccounts.filter(a => a.active && getAccountWalletId(a) === wallet.id && isSigningAccountForWallet(a, wallet));
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
function getCurrentWalletSignatureKey(wallet = getCurrentWallet()) {
|
|
556
|
-
if (!state.hdRoot || !wallet) return null;
|
|
557
|
-
const accountIndex = wallet.accountIndex;
|
|
558
|
-
try {
|
|
559
|
-
const path = buildSigningPath(501, accountIndex, 0);
|
|
560
|
-
const derived = deriveHDKey(path);
|
|
561
|
-
return {
|
|
562
|
-
privateKey: derived.privateKey(),
|
|
563
|
-
accountIndex,
|
|
564
|
-
index: 0,
|
|
565
|
-
path,
|
|
566
|
-
};
|
|
567
|
-
} catch (e) {
|
|
568
|
-
console.warn('Failed to derive selected wallet signature key:', e);
|
|
569
|
-
return null;
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
|
|
573
529
|
function updatePathDisplay() {
|
|
574
530
|
const coin = $('hd-coin')?.value;
|
|
575
531
|
const account = $('hd-account')?.value || '0';
|
|
@@ -821,60 +777,30 @@ function updateCustomPathDefault() {
|
|
|
821
777
|
input.dataset.autogenerated = 'true';
|
|
822
778
|
}
|
|
823
779
|
|
|
824
|
-
function fitWalletSelectorToSelectedLabel(select) {
|
|
825
|
-
if (!select) return;
|
|
826
|
-
const selected = select.options[select.selectedIndex];
|
|
827
|
-
const label = selected?.textContent || '';
|
|
828
|
-
const width = Math.max(72, Math.min(260, (label.length * 8) + 46));
|
|
829
|
-
select.style.width = `${width}px`;
|
|
830
|
-
}
|
|
831
|
-
|
|
832
780
|
function renderWalletSelector() {
|
|
833
|
-
const
|
|
834
|
-
if (
|
|
781
|
+
const select = $('wallet-active-select');
|
|
782
|
+
if (!select) return;
|
|
835
783
|
ensureWalletNamesNormalized();
|
|
836
784
|
|
|
837
785
|
const currentWallet = getCurrentWallet();
|
|
838
786
|
if (!currentWallet) {
|
|
839
|
-
|
|
787
|
+
select.innerHTML = '';
|
|
840
788
|
return;
|
|
841
789
|
}
|
|
842
790
|
state.activeWalletId = currentWallet.id;
|
|
843
791
|
|
|
792
|
+
select.innerHTML = '';
|
|
844
793
|
const displayCurrency = state.walletFiatCurrency || getSelectedCurrency();
|
|
845
794
|
const activeWallets = getActiveWallets();
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
option.textContent = wallet.id === state.activeWalletId
|
|
853
|
-
? wallet.name
|
|
854
|
-
: `${wallet.name} (${formatCurrencyValue(walletValue, displayCurrency)})`;
|
|
855
|
-
select.appendChild(option);
|
|
856
|
-
});
|
|
857
|
-
select.value = String(state.activeWalletId);
|
|
858
|
-
fitWalletSelectorToSelectedLabel(select);
|
|
795
|
+
activeWallets.forEach((wallet) => {
|
|
796
|
+
const option = document.createElement('option');
|
|
797
|
+
option.value = String(wallet.id);
|
|
798
|
+
const walletValue = state.walletFiatTotals[wallet.id] ?? 0;
|
|
799
|
+
option.textContent = `${wallet.name} (${formatCurrencyValue(walletValue, displayCurrency)})`;
|
|
800
|
+
select.appendChild(option);
|
|
859
801
|
});
|
|
802
|
+
select.value = String(state.activeWalletId);
|
|
860
803
|
updateCustomPathWalletLabel();
|
|
861
|
-
updateIdentityWalletKeys();
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
function updateWalletBondDisplay(currency = state.walletFiatCurrency || getSelectedCurrency()) {
|
|
865
|
-
const valueEl = $('wallet-bond-value');
|
|
866
|
-
const wallet = getCurrentWallet();
|
|
867
|
-
const walletValue = wallet ? state.walletFiatTotals?.[wallet.id] ?? 0 : 0;
|
|
868
|
-
if (valueEl) valueEl.textContent = formatCurrencyValue(walletValue, currency);
|
|
869
|
-
}
|
|
870
|
-
|
|
871
|
-
function updateIdentityWalletKeys() {
|
|
872
|
-
const identity = getCurrentWalletIdentity();
|
|
873
|
-
const xpubEl = $('identity-wallet-xpub');
|
|
874
|
-
const peerIdEl = $('identity-wallet-peerid');
|
|
875
|
-
|
|
876
|
-
if (xpubEl) setTruncatedValue(xpubEl, identity.xpub || 'N/A');
|
|
877
|
-
if (peerIdEl) setTruncatedValue(peerIdEl, identity.peerId || 'N/A');
|
|
878
804
|
}
|
|
879
805
|
|
|
880
806
|
function sleep(ms) {
|
|
@@ -1295,7 +1221,6 @@ function hideWalletOverlays() {
|
|
|
1295
1221
|
function showWalletMainView() {
|
|
1296
1222
|
const main = $('wallet-main-view');
|
|
1297
1223
|
hideWalletOverlays();
|
|
1298
|
-
closeAssetActionOverlay();
|
|
1299
1224
|
if (main) main.style.display = 'block';
|
|
1300
1225
|
}
|
|
1301
1226
|
|
|
@@ -1598,49 +1523,6 @@ function closeWalletActionMenus() {
|
|
|
1598
1523
|
$('wallet-receive-menu')?.classList.remove('visible');
|
|
1599
1524
|
}
|
|
1600
1525
|
|
|
1601
|
-
function closeAssetActionOverlay() {
|
|
1602
|
-
const overlay = $('wallet-asset-action-overlay');
|
|
1603
|
-
if (overlay) overlay.style.display = 'none';
|
|
1604
|
-
state.selectedWalletAssetIdx = null;
|
|
1605
|
-
}
|
|
1606
|
-
|
|
1607
|
-
function showAssetActionOverlay(acct, idx) {
|
|
1608
|
-
const overlay = $('wallet-asset-action-overlay');
|
|
1609
|
-
if (!overlay || !acct) return;
|
|
1610
|
-
|
|
1611
|
-
state.selectedWalletAssetIdx = idx;
|
|
1612
|
-
const icon = CHAIN_ICONS[acct.name] || { symbol: '?' };
|
|
1613
|
-
const fullName = CHAIN_FULL_NAMES[acct.name] || acct.name;
|
|
1614
|
-
const pathLabel = acct.path || `m/44'/${acct.coinType}'/${acct.account}'/0/${acct.index}`;
|
|
1615
|
-
|
|
1616
|
-
const titleEl = $('wallet-asset-action-title');
|
|
1617
|
-
const pathEl = $('wallet-asset-action-path');
|
|
1618
|
-
const addressEl = $('wallet-asset-action-address');
|
|
1619
|
-
if (titleEl) titleEl.textContent = `${icon.symbol} ${fullName}`;
|
|
1620
|
-
if (pathEl) pathEl.textContent = pathLabel;
|
|
1621
|
-
if (addressEl) {
|
|
1622
|
-
addressEl.textContent = acct.address || '';
|
|
1623
|
-
addressEl.title = acct.address || '';
|
|
1624
|
-
}
|
|
1625
|
-
|
|
1626
|
-
const sendBtn = $('wallet-asset-send');
|
|
1627
|
-
const receiveBtn = $('wallet-asset-receive');
|
|
1628
|
-
if (sendBtn) {
|
|
1629
|
-
sendBtn.onclick = () => {
|
|
1630
|
-
closeAssetActionOverlay();
|
|
1631
|
-
showSendView(idx);
|
|
1632
|
-
};
|
|
1633
|
-
}
|
|
1634
|
-
if (receiveBtn) {
|
|
1635
|
-
receiveBtn.onclick = () => {
|
|
1636
|
-
closeAssetActionOverlay();
|
|
1637
|
-
showReceiveModal(acct);
|
|
1638
|
-
};
|
|
1639
|
-
}
|
|
1640
|
-
|
|
1641
|
-
overlay.style.display = 'flex';
|
|
1642
|
-
}
|
|
1643
|
-
|
|
1644
1526
|
function renderAccountsList() {
|
|
1645
1527
|
const listEl = $('wallet-accounts-list');
|
|
1646
1528
|
const emptyEl = $('wallet-accounts-empty');
|
|
@@ -1689,7 +1571,7 @@ function renderAccountsList() {
|
|
|
1689
1571
|
'</div>';
|
|
1690
1572
|
|
|
1691
1573
|
row.addEventListener('click', () => {
|
|
1692
|
-
|
|
1574
|
+
showReceiveModal(acct);
|
|
1693
1575
|
});
|
|
1694
1576
|
|
|
1695
1577
|
listEl.appendChild(row);
|
|
@@ -2146,6 +2028,7 @@ async function updateWalletBondTotal() {
|
|
|
2146
2028
|
const currency = getSelectedCurrency();
|
|
2147
2029
|
const prices = await fetchCryptoPrices(currency);
|
|
2148
2030
|
|
|
2031
|
+
let total = 0;
|
|
2149
2032
|
const walletTotals = {};
|
|
2150
2033
|
let hasPositiveBalance = false;
|
|
2151
2034
|
let missingPriceForFundedAccount = false;
|
|
@@ -2162,20 +2045,27 @@ async function updateWalletBondTotal() {
|
|
|
2162
2045
|
}
|
|
2163
2046
|
|
|
2164
2047
|
const fiatValue = bal * price;
|
|
2048
|
+
total += fiatValue;
|
|
2165
2049
|
const walletId = getAccountWalletId(acct);
|
|
2166
2050
|
walletTotals[walletId] = (walletTotals[walletId] || 0) + fiatValue;
|
|
2167
2051
|
}
|
|
2168
2052
|
|
|
2169
|
-
|
|
2170
|
-
if (hasPositiveBalance && pricedTotal <= 0 && missingPriceForFundedAccount) {
|
|
2053
|
+
if (hasPositiveBalance && total <= 0 && missingPriceForFundedAccount) {
|
|
2171
2054
|
throw new Error('Funded accounts found but fiat pricing is unavailable');
|
|
2172
2055
|
}
|
|
2173
2056
|
|
|
2174
2057
|
state.walletFiatTotals = walletTotals;
|
|
2175
2058
|
state.walletFiatCurrency = currency;
|
|
2176
2059
|
|
|
2177
|
-
|
|
2060
|
+
const formatted = formatCurrencyValue(total, currency);
|
|
2061
|
+
if (valueEl) valueEl.textContent = formatted;
|
|
2178
2062
|
renderWalletSelector();
|
|
2063
|
+
|
|
2064
|
+
// Also update the header bond total
|
|
2065
|
+
const accountTotalEl = $('account-total-value');
|
|
2066
|
+
if (accountTotalEl) {
|
|
2067
|
+
accountTotalEl.textContent = 'Bond: ' + formatted;
|
|
2068
|
+
}
|
|
2179
2069
|
} catch (e) {
|
|
2180
2070
|
console.warn('Bond total calculation failed:', e);
|
|
2181
2071
|
// Keep last known totals if pricing endpoint is temporarily unavailable.
|
|
@@ -2183,7 +2073,10 @@ async function updateWalletBondTotal() {
|
|
|
2183
2073
|
const cachedTotal = Object.values(cachedTotals).reduce((sum, v) => sum + (Number.isFinite(v) ? v : 0), 0);
|
|
2184
2074
|
if (cachedTotal > 0) {
|
|
2185
2075
|
const displayCurrency = state.walletFiatCurrency || getSelectedCurrency();
|
|
2186
|
-
|
|
2076
|
+
const formatted = formatCurrencyValue(cachedTotal, displayCurrency);
|
|
2077
|
+
if (valueEl) valueEl.textContent = formatted;
|
|
2078
|
+
const accountTotalEl = $('account-total-value');
|
|
2079
|
+
if (accountTotalEl) accountTotalEl.textContent = 'Bond: ' + formatted;
|
|
2187
2080
|
} else if (valueEl && !valueEl.textContent) {
|
|
2188
2081
|
valueEl.textContent = '$0.00';
|
|
2189
2082
|
}
|
|
@@ -2666,6 +2559,21 @@ function login(keys) {
|
|
|
2666
2559
|
if (xpubEl) {
|
|
2667
2560
|
setTruncatedValue(xpubEl, state.hdRoot.toXpub() || 'N/A');
|
|
2668
2561
|
}
|
|
2562
|
+
// Populate wallet tab xpub display
|
|
2563
|
+
const walletTabXpubEl = $('wallet-tab-xpub');
|
|
2564
|
+
if (walletTabXpubEl) {
|
|
2565
|
+
setTruncatedValue(walletTabXpubEl, state.hdRoot.toXpub() || 'N/A');
|
|
2566
|
+
}
|
|
2567
|
+
// Populate wallet tab PeerID display
|
|
2568
|
+
const walletTabPeerIdEl = $('wallet-tab-peerid');
|
|
2569
|
+
const peerIdRow = $('ph-portfolio-peerid-row');
|
|
2570
|
+
if (walletTabPeerIdEl && peerIdRow) {
|
|
2571
|
+
const peerIdStr = deriveAccountPeerId();
|
|
2572
|
+
if (peerIdStr) {
|
|
2573
|
+
setTruncatedValue(walletTabPeerIdEl, peerIdStr);
|
|
2574
|
+
peerIdRow.style.display = '';
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2669
2577
|
populateAccountAddressDropdown();
|
|
2670
2578
|
if (xprvEl) {
|
|
2671
2579
|
xprvEl.textContent = 'Hidden (click reveal)';
|
|
@@ -2909,9 +2817,43 @@ function downloadData(data, filename, mimeType) {
|
|
|
2909
2817
|
// Wallet Address Population & Balance Fetching
|
|
2910
2818
|
// =============================================================================
|
|
2911
2819
|
|
|
2820
|
+
// Account header — show xpub only
|
|
2912
2821
|
function populateAccountAddressDropdown() {
|
|
2913
|
-
|
|
2914
|
-
|
|
2822
|
+
const addrEl = $('account-address-display');
|
|
2823
|
+
if (!addrEl) return;
|
|
2824
|
+
|
|
2825
|
+
const xpubStr = state.hdRoot ? state.hdRoot.toXpub() : '';
|
|
2826
|
+
addrEl.textContent = `${xpubStr.slice(0,10)}...${xpubStr.slice(-10)}`;
|
|
2827
|
+
addrEl.title = xpubStr;
|
|
2828
|
+
|
|
2829
|
+
const copyBtn = $('account-address-copy');
|
|
2830
|
+
if (copyBtn) {
|
|
2831
|
+
copyBtn.onclick = async () => {
|
|
2832
|
+
if (xpubStr && await safeCopyText(xpubStr)) {
|
|
2833
|
+
copyBtn.title = 'Copied!';
|
|
2834
|
+
setTimeout(() => { copyBtn.title = 'Copy xpub'; }, 1500);
|
|
2835
|
+
}
|
|
2836
|
+
};
|
|
2837
|
+
}
|
|
2838
|
+
|
|
2839
|
+
// Populate PeerID row (derived from account-level secp256k1 key)
|
|
2840
|
+
const peerIdStr = deriveAccountPeerId();
|
|
2841
|
+
const peerIdRow = $('account-peerid-row');
|
|
2842
|
+
const peerIdEl = $('account-peerid-display');
|
|
2843
|
+
if (peerIdStr && peerIdRow && peerIdEl) {
|
|
2844
|
+
peerIdRow.style.display = '';
|
|
2845
|
+
peerIdEl.textContent = `${peerIdStr.slice(0,8)}...${peerIdStr.slice(-8)}`;
|
|
2846
|
+
peerIdEl.title = peerIdStr;
|
|
2847
|
+
}
|
|
2848
|
+
const peerCopyBtn = $('account-peerid-copy');
|
|
2849
|
+
if (peerCopyBtn) {
|
|
2850
|
+
peerCopyBtn.onclick = async () => {
|
|
2851
|
+
if (peerIdStr && await safeCopyText(peerIdStr)) {
|
|
2852
|
+
peerCopyBtn.title = 'Copied!';
|
|
2853
|
+
setTimeout(() => { peerCopyBtn.title = 'Copy PeerID'; }, 1500);
|
|
2854
|
+
}
|
|
2855
|
+
};
|
|
2856
|
+
}
|
|
2915
2857
|
}
|
|
2916
2858
|
|
|
2917
2859
|
function populateWalletAddresses() {
|
|
@@ -3370,11 +3312,10 @@ function generateVCard(info, { skipPhoto = false } = {}) {
|
|
|
3370
3312
|
}
|
|
3371
3313
|
|
|
3372
3314
|
if (info.includeKeys && state.wallet?.x25519) {
|
|
3373
|
-
const identity = getCurrentWalletIdentity();
|
|
3374
3315
|
person.KEY = [
|
|
3375
|
-
// Always include
|
|
3376
|
-
...(
|
|
3377
|
-
XPUB:
|
|
3316
|
+
// Always include xPub
|
|
3317
|
+
...(state.hdRoot?.toXpub ? [{
|
|
3318
|
+
XPUB: state.hdRoot.toXpub(),
|
|
3378
3319
|
LABEL: '',
|
|
3379
3320
|
}] : []),
|
|
3380
3321
|
// X25519 encryption key
|
|
@@ -3383,7 +3324,8 @@ function generateVCard(info, { skipPhoto = false } = {}) {
|
|
|
3383
3324
|
LABEL: 'X25519',
|
|
3384
3325
|
},
|
|
3385
3326
|
// Active accounts from wallet scan
|
|
3386
|
-
...
|
|
3327
|
+
...state.activeAccounts
|
|
3328
|
+
.filter(a => a.active && isSigningAccount(a))
|
|
3387
3329
|
.flatMap(a => {
|
|
3388
3330
|
const entries = [];
|
|
3389
3331
|
const pathLabel = a.path || `m/44'/${a.coinType}'/${a.account}'/0/${a.index}`;
|
|
@@ -3404,9 +3346,8 @@ function generateVCard(info, { skipPhoto = false } = {}) {
|
|
|
3404
3346
|
return entries;
|
|
3405
3347
|
}),
|
|
3406
3348
|
];
|
|
3407
|
-
} else if (info.xpubOnly) {
|
|
3408
|
-
|
|
3409
|
-
if (identity.xpub) person.KEY = [{ XPUB: identity.xpub, LABEL: '' }];
|
|
3349
|
+
} else if (info.xpubOnly && state.hdRoot?.toXpub) {
|
|
3350
|
+
person.KEY = [{ XPUB: state.hdRoot.toXpub(), LABEL: '' }];
|
|
3410
3351
|
}
|
|
3411
3352
|
|
|
3412
3353
|
const note = info.includeKeys
|
|
@@ -3458,16 +3399,15 @@ function getSignableBody(vcardText) {
|
|
|
3458
3399
|
}
|
|
3459
3400
|
|
|
3460
3401
|
function signVCard(vcardText) {
|
|
3461
|
-
|
|
3462
|
-
if (!signatureKey?.privateKey) return vcardText;
|
|
3402
|
+
if (!state.wallet?.ed25519?.privateKey) return vcardText;
|
|
3463
3403
|
|
|
3464
3404
|
const body = getSignableBody(vcardText);
|
|
3465
3405
|
const messageBytes = new TextEncoder().encode(body);
|
|
3466
|
-
const signature = hdWallet().curves.ed25519.sign(messageBytes,
|
|
3406
|
+
const signature = hdWallet().curves.ed25519.sign(messageBytes, state.wallet.ed25519.privateKey);
|
|
3467
3407
|
const sigB64 = toBase64(signature);
|
|
3468
3408
|
|
|
3469
|
-
// Encode signature +
|
|
3470
|
-
const sigValue = `${sigB64}:501
|
|
3409
|
+
// Encode signature + derivation path (coinType=501, account=0, index=0)
|
|
3410
|
+
const sigValue = `${sigB64}:501:0:0`;
|
|
3471
3411
|
|
|
3472
3412
|
// Find highest itemN and key index
|
|
3473
3413
|
let maxItem = 0;
|
|
@@ -3836,8 +3776,8 @@ function isPasskeySupported() {
|
|
|
3836
3776
|
|
|
3837
3777
|
// Track selected remember method (pin or passkey) for each login type
|
|
3838
3778
|
const rememberMethod = {
|
|
3839
|
-
password: '
|
|
3840
|
-
seed: '
|
|
3779
|
+
password: 'passkey',
|
|
3780
|
+
seed: 'passkey'
|
|
3841
3781
|
};
|
|
3842
3782
|
|
|
3843
3783
|
function setupLoginHandlers() {
|
|
@@ -4283,7 +4223,7 @@ function setupMainAppHandlers() {
|
|
|
4283
4223
|
// Modal close handlers
|
|
4284
4224
|
$qa('.modal').forEach(modal => {
|
|
4285
4225
|
modal.addEventListener('click', (e) => {
|
|
4286
|
-
if (e.target === modal || e.target.
|
|
4226
|
+
if (e.target === modal || e.target.classList.contains('modal-close')) {
|
|
4287
4227
|
modal.classList.remove('active');
|
|
4288
4228
|
}
|
|
4289
4229
|
});
|
|
@@ -4292,7 +4232,7 @@ function setupMainAppHandlers() {
|
|
|
4292
4232
|
// Account modal tab switching
|
|
4293
4233
|
$qa('.modal-tab[data-modal-tab]').forEach(tab => {
|
|
4294
4234
|
tab.addEventListener('click', () => {
|
|
4295
|
-
$qa('.modal-tab').forEach(t => t.classList.remove('active'));
|
|
4235
|
+
$qa('.modal-tab[data-modal-tab]').forEach(t => t.classList.remove('active'));
|
|
4296
4236
|
$qa('.modal-tab-content').forEach(c => c.classList.remove('active'));
|
|
4297
4237
|
tab.classList.add('active');
|
|
4298
4238
|
const target = $(tab.dataset.modalTab);
|
|
@@ -4710,12 +4650,10 @@ function setupMainAppHandlers() {
|
|
|
4710
4650
|
if (targetEl) {
|
|
4711
4651
|
try {
|
|
4712
4652
|
let value = '';
|
|
4713
|
-
if (targetId === 'wallet-xpub') {
|
|
4653
|
+
if (targetId === 'wallet-xpub' || targetId === 'wallet-tab-xpub') {
|
|
4714
4654
|
value = state.hdRoot?.toXpub?.() || '';
|
|
4715
|
-
} else if (targetId === '
|
|
4716
|
-
value =
|
|
4717
|
-
} else if (targetId === 'identity-wallet-peerid') {
|
|
4718
|
-
value = getCurrentWalletIdentity().peerId || '';
|
|
4655
|
+
} else if (targetId === 'wallet-tab-peerid') {
|
|
4656
|
+
value = deriveAccountPeerId() || '';
|
|
4719
4657
|
} else if (targetId === 'wallet-xprv') {
|
|
4720
4658
|
if (targetEl.dataset.revealed !== 'true') {
|
|
4721
4659
|
alert('Reveal the xprv first to copy it.');
|
|
@@ -4808,45 +4746,74 @@ function setupMainAppHandlers() {
|
|
|
4808
4746
|
});
|
|
4809
4747
|
|
|
4810
4748
|
// Wallet tab controls
|
|
4811
|
-
|
|
4749
|
+
$('wallet-active-select')?.addEventListener('change', (e) => {
|
|
4812
4750
|
const walletId = Number.parseInt(e.target.value, 10);
|
|
4813
4751
|
if (Number.isNaN(walletId)) return;
|
|
4814
4752
|
state.activeWalletId = walletId;
|
|
4815
4753
|
closeWalletActionMenus();
|
|
4816
|
-
closeAssetActionOverlay();
|
|
4817
4754
|
renderWalletSelector();
|
|
4818
|
-
updateWalletBondDisplay();
|
|
4819
4755
|
renderAccountsList();
|
|
4820
4756
|
updateCustomPathDefault();
|
|
4821
|
-
};
|
|
4822
|
-
$('account-wallet-select')?.addEventListener('change', handleWalletSelectChange);
|
|
4823
|
-
$('wallet-active-select')?.addEventListener('change', handleWalletSelectChange);
|
|
4824
|
-
$('wallet-manage-tab')?.addEventListener('click', () => {
|
|
4825
|
-
closeWalletActionMenus();
|
|
4826
|
-
closeAssetActionOverlay();
|
|
4827
|
-
$qa('.modal-tab').forEach(t => t.classList.remove('active'));
|
|
4828
|
-
$qa('.modal-tab-content').forEach(c => c.classList.remove('active'));
|
|
4829
|
-
$('wallet-manage-tab')?.classList.add('active');
|
|
4830
|
-
$('wallet-tab-content')?.classList.add('active');
|
|
4831
|
-
showWalletsView();
|
|
4832
4757
|
});
|
|
4833
4758
|
$('wallet-manage-btn')?.addEventListener('click', () => {
|
|
4834
4759
|
closeWalletActionMenus();
|
|
4835
|
-
closeAssetActionOverlay();
|
|
4836
4760
|
showWalletsView();
|
|
4837
4761
|
});
|
|
4838
4762
|
$('wallet-scan-btn')?.addEventListener('click', () => {
|
|
4839
4763
|
scanActiveAccounts();
|
|
4840
4764
|
});
|
|
4841
|
-
$('wallet-
|
|
4765
|
+
const sendAction = $('wallet-send-action');
|
|
4766
|
+
const receiveAction = $('wallet-receive-action');
|
|
4767
|
+
$('wallet-send-btn')?.addEventListener('click', (e) => {
|
|
4768
|
+
e.stopPropagation();
|
|
4769
|
+
updateWalletActionMenus();
|
|
4770
|
+
const sendMenu = $('wallet-send-menu');
|
|
4771
|
+
const receiveMenu = $('wallet-receive-menu');
|
|
4772
|
+
if (!sendMenu || !receiveMenu) return;
|
|
4773
|
+
const nextVisible = !sendMenu.classList.contains('visible');
|
|
4774
|
+
receiveMenu.classList.remove('visible');
|
|
4775
|
+
sendMenu.classList.toggle('visible', nextVisible);
|
|
4776
|
+
});
|
|
4777
|
+
$('wallet-receive-btn-main')?.addEventListener('click', (e) => {
|
|
4778
|
+
e.stopPropagation();
|
|
4779
|
+
updateWalletActionMenus();
|
|
4780
|
+
const sendMenu = $('wallet-send-menu');
|
|
4781
|
+
const receiveMenu = $('wallet-receive-menu');
|
|
4782
|
+
if (!sendMenu || !receiveMenu) return;
|
|
4783
|
+
const nextVisible = !receiveMenu.classList.contains('visible');
|
|
4784
|
+
sendMenu.classList.remove('visible');
|
|
4785
|
+
receiveMenu.classList.toggle('visible', nextVisible);
|
|
4786
|
+
});
|
|
4787
|
+
$qa('#wallet-send-menu .ph-action-menu-item').forEach((btn) => {
|
|
4788
|
+
btn.addEventListener('click', (e) => {
|
|
4789
|
+
e.stopPropagation();
|
|
4790
|
+
const chain = btn.dataset.chain;
|
|
4791
|
+
const acct = getWalletAccountForChain(chain);
|
|
4792
|
+
closeWalletActionMenus();
|
|
4793
|
+
if (!acct) return;
|
|
4794
|
+
showSendView(state.activeAccounts.indexOf(acct));
|
|
4795
|
+
});
|
|
4796
|
+
});
|
|
4797
|
+
$qa('#wallet-receive-menu .ph-action-menu-item').forEach((btn) => {
|
|
4798
|
+
btn.addEventListener('click', (e) => {
|
|
4799
|
+
e.stopPropagation();
|
|
4800
|
+
const chain = btn.dataset.chain;
|
|
4801
|
+
const acct = getWalletAccountForChain(chain);
|
|
4802
|
+
closeWalletActionMenus();
|
|
4803
|
+
if (!acct) return;
|
|
4804
|
+
showReceiveModal(acct);
|
|
4805
|
+
});
|
|
4806
|
+
});
|
|
4807
|
+
_root.addEventListener('click', (e) => {
|
|
4808
|
+
if (sendAction?.contains(e.target) || receiveAction?.contains(e.target)) return;
|
|
4809
|
+
closeWalletActionMenus();
|
|
4810
|
+
});
|
|
4842
4811
|
$('wallet-export-btn-main')?.addEventListener('click', () => {
|
|
4843
4812
|
closeWalletActionMenus();
|
|
4844
|
-
closeAssetActionOverlay();
|
|
4845
4813
|
showExportView();
|
|
4846
4814
|
});
|
|
4847
4815
|
$('wallet-advanced-btn-main')?.addEventListener('click', () => {
|
|
4848
4816
|
closeWalletActionMenus();
|
|
4849
|
-
closeAssetActionOverlay();
|
|
4850
4817
|
showAdvancedView();
|
|
4851
4818
|
});
|
|
4852
4819
|
$('wallet-wallets-back')?.addEventListener('click', () => {
|
|
@@ -6024,27 +5991,14 @@ export async function createWalletUI(rootElement, options = {}) {
|
|
|
6024
5991
|
return {
|
|
6025
5992
|
/** Open the login modal */
|
|
6026
5993
|
openLogin() {
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
if (accountModal) accountModal.classList.add('active');
|
|
6030
|
-
return;
|
|
6031
|
-
}
|
|
6032
|
-
const loginModal = document.getElementById('login-modal');
|
|
6033
|
-
if (loginModal) {
|
|
6034
|
-
loginModal.classList.add('active');
|
|
6035
|
-
const storedTab = loginModal.querySelector('[data-method="stored"]');
|
|
6036
|
-
if (storedTab && storedTab.style.display !== 'none') storedTab.click();
|
|
6037
|
-
}
|
|
5994
|
+
const modal = document.getElementById('login-modal');
|
|
5995
|
+
if (modal) modal.classList.add('active');
|
|
6038
5996
|
},
|
|
6039
5997
|
/** Open the account / keys modal (requires login first) */
|
|
6040
5998
|
openAccount() {
|
|
6041
5999
|
const modal = document.getElementById('keys-modal');
|
|
6042
6000
|
if (modal) modal.classList.add('active');
|
|
6043
6001
|
},
|
|
6044
|
-
/** Clear the wallet session; host applications own any visible logout control */
|
|
6045
|
-
logout() {
|
|
6046
|
-
logout();
|
|
6047
|
-
},
|
|
6048
6002
|
/** Remove all injected wallet UI elements from the DOM */
|
|
6049
6003
|
destroy() {
|
|
6050
6004
|
const container = document.getElementById('hd-wallet-ui-container');
|