diff --git a/public/assets/wallet.js b/public/assets/wallet.js index f53005d..dac589b 100644 --- a/public/assets/wallet.js +++ b/public/assets/wallet.js @@ -52,12 +52,51 @@ window.IAPWallet = (function () { card.appendChild(cancel); back.appendChild(card); document.body.appendChild(back); }); } + // ── WalletConnect: works in any normal mobile browser (no in-app dApp browser + // needed) and on desktop via QR. Lazy-loaded UMD; the returned object is a + // plain EIP-1193 provider, so everything downstream is unchanged. + let wcSdkPromise = null, wcProvider = null; + function loadWcSdk() { + const ready = () => (window['@walletconnect/ethereum-provider'] || {}).EthereumProvider; + if (ready()) return Promise.resolve(ready()); + if (wcSdkPromise) return wcSdkPromise; + wcSdkPromise = new Promise((resolve, reject) => { + const s = document.createElement('script'); + s.src = 'https://cdn.jsdelivr.net/npm/@walletconnect/ethereum-provider@2.21.1/dist/index.umd.js'; + s.async = true; + s.onload = () => { const EP = ready(); EP ? resolve(EP) : reject(new Error('WalletConnect failed to load.')); }; + s.onerror = () => reject(new Error('Could not load WalletConnect. Check your connection and try again.')); + document.head.appendChild(s); + }); + return wcSdkPromise; + } + async function makeWalletConnect(c) { + const projectId = String(c.walletConnectProjectId || '').trim(); + if (!projectId) throw new Error('WalletConnect is not configured yet.'); + const EP = await loadWcSdk(); + const chainId = Number(c.chainId); + if (!wcProvider) { + wcProvider = await EP.init({ + projectId, chains: [chainId], optionalChains: [chainId], showQrModal: true, + rpcMap: { [chainId]: c.rpc }, + metadata: { name: c.siteName || 'InstantAdPay', description: c.tagline || 'Advertise and earn, paid on-chain.', + url: location.origin, icons: [location.origin + '/logo-icon.png'] } + }); + } + if (!wcProvider.session) await wcProvider.connect(); // QR on desktop, opens the wallet app on mobile + return wcProvider; + } async function ensureProvider() { if (CHOSEN && CHOSEN.provider) return CHOSEN.provider; const list = providerList(); + let cfg = null; + try { cfg = await IAP.getConfig(); } catch (e) {} + const wcOn = !!(cfg && String(cfg.walletConnectProjectId || '').trim()); + if (wcOn) list.push({ info: { name: 'WalletConnect — scan a QR or open your wallet app', __wc: true } }); if (!list.length) throw new Error('No wallet found. Open this page in your wallet app (Trust, MetaMask, SafePal, Phantom, OKX, TokenPocket) or install a wallet extension.'); - CHOSEN = list.length === 1 ? list[0] : await pickModal(list); - if (!CHOSEN) throw new Error('No wallet selected.'); + const pick = list.length === 1 ? list[0] : await pickModal(list); + if (!pick) throw new Error('No wallet selected.'); + CHOSEN = (pick.info && pick.info.__wc) ? { info: pick.info, provider: await makeWalletConnect(cfg) } : pick; return CHOSEN.provider; } function eth() { diff --git a/public/index.html b/public/index.html index 97bcc92..b96fdee 100644 --- a/public/index.html +++ b/public/index.html @@ -439,7 +439,7 @@ - + diff --git a/public/my.html b/public/my.html index cf73582..be2752e 100644 --- a/public/my.html +++ b/public/my.html @@ -690,7 +690,7 @@ - + diff --git a/server.js b/server.js index 8a76606..242c1a9 100644 --- a/server.js +++ b/server.js @@ -162,7 +162,7 @@ const MIME = { '.html': 'text/html; charset=utf-8', '.css': 'text/css', '.js': ' '.png': 'image/png', '.jpg': 'image/jpeg', '.svg': 'image/svg+xml', '.webp': 'image/webp', '.ico': 'image/x-icon', '.json': 'application/json', '.mp4': 'video/mp4', '.woff2': 'font/woff2', '.gif': 'image/gif', '.webm': 'video/webm', '.txt': 'text/plain; charset=utf-8', '.xml': 'application/xml; charset=utf-8' }; -const CSP = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; media-src 'self' https: blob:; connect-src 'self'; font-src 'self' data: https://fonts.gstatic.com; form-action 'self'; frame-src https: http:"; +const CSP = "default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; media-src 'self' https: blob:; connect-src 'self' https://*.walletconnect.com wss://*.walletconnect.com https://*.walletconnect.org wss://*.walletconnect.org https://*.web3modal.org https://*.reown.com wss://*.reown.com; font-src 'self' data: https://fonts.gstatic.com; form-action 'self'; frame-src https: http:"; function baseHeaders(extra) { return Object.assign({ 'Content-Security-Policy': CSP, 'X-Content-Type-Options': 'nosniff', 'Referrer-Policy': 'strict-origin-when-cross-origin' }, extra || {});