${domains.map(d => {
const name = typeof d === 'string' ? d : (d.domain || d.name || String(d));
const isFav = favourite && name === favourite;
return `
${esc(name)}.sol
${isFav ? '
★ FAVOURITE
' : ''}
`;
}).join('')}
`;
} catch(err) {
results.innerHTML = errorHTML(`Network error: ${err.message}`);
}
}
// ─── WALLET ─────────────────────────────────────────────────
let connectedProvider = null;
function getAvailableWallets() {
const found = [];
const seen = new Set();
function add(name, icon, provider, url) {
if (!provider || seen.has(provider)) return;
seen.add(provider);
found.push({ name, icon, provider, url });
}
// ── Specific well-known injection points ──
// Phantom
try {
const p = window.phantom?.solana;
if (p && p.isPhantom) add('PHANTOM', '👻', p, 'https://phantom.app');
} catch(e) {}
// Solflare
try {
const s = window.solflare;
if (s && s.isSolflare) add('SOLFLARE', '🔆', s, 'https://solflare.com');
} catch(e) {}
// Backpack
try {
const b = window.backpack;
if (b && b.isBackpack) add('BACKPACK', '🎒', b, 'https://backpack.app');
} catch(e) {}
// Coinbase
try {
if (window.coinbaseSolana) add('COINBASE', '🔵', window.coinbaseSolana, 'https://coinbase.com/wallet');
} catch(e) {}
// Trust
try {
const t = window.trustwallet?.solana;
if (t) add('TRUST', '🛡️', t, 'https://trustwallet.com');
} catch(e) {}
// ── Generic window.solana (Jupiter, MetaMask Snap, and others inject here) ──
try {
const ws = window.solana;
if (ws && !seen.has(ws)) {
// Try to identify what it is
if (ws.isJupiter) add('JUPITER', '🪐', ws, 'https://jup.ag');
else if (ws.isMetaMask) add('METAMASK', '🦊', ws, 'https://metamask.io');
else if (ws.isPhantom) { /* already caught above */ }
else if (ws.isSolflare) { /* already caught above */ }
else if (ws.isBackpack) { /* already caught above */ }
else add('SOLANA WALLET', '◈', ws, '#');
}
} catch(e) {}
// ── Jupiter specific paths ──
try {
const j = window.jupiter?.solana;
if (j && !seen.has(j)) add('JUPITER', '🪐', j, 'https://jup.ag');
} catch(e) {}
// ── MetaMask ethereum.solana path ──
try {
if (window.ethereum?.isMetaMask && window.ethereum?.solana && !seen.has(window.ethereum.solana)) {
add('METAMASK', '🦊', window.ethereum.solana, 'https://metamask.io');
}
} catch(e) {}
// ── Multi-provider array (some wallets use this) ──
try {
const providers = window.solana?.providers;
if (Array.isArray(providers)) {
for (const p of providers) {
if (seen.has(p)) continue;
if (p.isPhantom) add('PHANTOM', '👻', p, 'https://phantom.app');
else if (p.isJupiter) add('JUPITER', '🪐', p, 'https://jup.ag');
else if (p.isSolflare) add('SOLFLARE', '🔆', p, 'https://solflare.com');
else if (p.isBackpack) add('BACKPACK', '🎒', p, 'https://backpack.app');
else if (p.isMetaMask) add('METAMASK', '🦊', p, 'https://metamask.io');
else add('WALLET', '◈', p, '#');
}
}
} catch(e) {}
// ── Wallet Standard discovery (modern wallets) ──
try {
const walletStandard = window.navigator?.wallets;
if (walletStandard && typeof walletStandard[Symbol.iterator] === 'function') {
for (const w of walletStandard) {
if (w.features?.['standard:connect'] && !seen.has(w)) {
const name = (w.name || 'WALLET').toUpperCase();
add(name, w.icon || '◈', w, w.url || '#');
}
}
}
} catch(e) {}
return found;
}
// All known wallets for install links
const KNOWN_WALLETS = [
{ name: 'PHANTOM', icon: '👻', url: 'https://phantom.app' },
{ name: 'JUPITER', icon: '🪐', url: 'https://jup.ag' },
{ name: 'SOLFLARE', icon: '🔆', url: 'https://solflare.com' },
{ name: 'BACKPACK', icon: '🎒', url: 'https://backpack.app' },
{ name: 'COINBASE', icon: '🔵', url: 'https://coinbase.com/wallet' },
{ name: 'TRUST', icon: '🛡️', url: 'https://trustwallet.com' },
{ name: 'METAMASK', icon: '🦊', url: 'https://metamask.io' },
];
function initWallet() {
const btn = $('#wallet-btn');
if (!btn) return;
btn.addEventListener('click', toggleWallet);
createWalletModal();
}
function createWalletModal() {
const modal = document.createElement('div');
modal.id = 'wallet-modal';
modal.className = 'sol-modal hidden';
modal.innerHTML = `
SELECT WALLET
`;
document.body.appendChild(modal);
modal.querySelector('.sol-modal-backdrop').addEventListener('click', closeModal);
modal.querySelector('#modal-close').addEventListener('click', closeModal);
}
function openModal() {
const modal = $('#wallet-modal');
const list = $('#wallet-list');
// Small delay to let async provider injection complete
setTimeout(() => {
const available = getAvailableWallets();
const detectedNames = new Set(available.map(w => w.name));
let html = '';
if (available.length > 0) {
html += '
DETECTED
';
html += available.map(w => `
`).join('');
}
const notInstalled = KNOWN_WALLETS.filter(w => !detectedNames.has(w.name));
if (notInstalled.length > 0) {
html += '
NOT INSTALLED
';
html += notInstalled.map(w => `
${w.icon}${w.name}INSTALL ↗
`).join('');
}
if (available.length === 0) {
html = `
NO SOLANA WALLETS DETECTED
Install a Solana wallet extension to connect. If you just installed one, refresh the page.