Wallet diagnostics: a check page, and an error that names the signer
Two sign-in failures with different causes and no way to tell them apart from the outside, so stop guessing and get the data off the member's device. /wallet-check reports what the page can actually see: whether window.ethereum exists, which wallet flags are set, which EIP-6963 wallets announced, the accounts and chain the wallet returns — and critically, any CSP violation. Our script-src is 'self' with no 'unsafe-inline', and a wallet browser that injects its provider via a script tag would be blocked silently, producing symptoms identical to "no wallet installed". The company dApp sends no CSP at all, which is a plausible reason it connects where we do not. This page will confirm or kill that theory rather than us theorising further. "Signature does not match this wallet" was true but useless — it never said WHICH wallet signed. It now names both the address the page asked for and the address that actually signed, which identifies the classic multi-account case (wallet signs with the selected account, not the one the page picked up) in one glance. Verified for the case in hand: 0x20E0…2248 IS the wallet registered to position #52 on-chain, so ownership was never the problem. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex"><title>Wallet check</title><link rel="icon" type="image/png" href="/favicon.png"><link rel="stylesheet" href="/styles.css">
|
||||
<style>
|
||||
.wc{max-width:640px;margin:0 auto;padding:22px 18px 60px}
|
||||
.wc h1{font-size:24px;margin:6px 0 6px}
|
||||
.wc .lede{color:var(--muted);font-size:14.5px;line-height:1.55;margin-bottom:16px}
|
||||
.row{border:1px solid var(--line);border-radius:10px;padding:11px 13px;margin-bottom:9px}
|
||||
.row .k{font-size:11px;font-weight:800;letter-spacing:1.2px;text-transform:uppercase;color:var(--muted);margin-bottom:4px}
|
||||
.row .v{font-size:15px;font-weight:700;word-break:break-all}
|
||||
.yes{color:var(--teal)} .no{color:#f0a05a}
|
||||
pre{background:var(--bg,#0b1d2e);border:1px solid var(--line);border-radius:9px;padding:10px;
|
||||
font-size:11.5px;line-height:1.5;overflow-x:auto;white-space:pre-wrap;word-break:break-all;margin-top:10px}
|
||||
.btn-row{margin:14px 0 4px}
|
||||
</style></head>
|
||||
<body>
|
||||
<header class="wrap nav"><a class="brand" href="/"><img class="brand-mark" src="/logo.jpg" alt="RM Circle" width="38" height="38"><span><span id="brandName">RM Circle</span><small>Wallet check</small></span></a></header>
|
||||
<main class="wc">
|
||||
<h1>Wallet check</h1>
|
||||
<p class="lede">This page doesn't sign anything or ask for anything. It just reports what your browser can see, so we can work out why sign-in isn't working. Open it the same way you were opening the dashboard, then screenshot this whole page.</p>
|
||||
|
||||
<div id="rows"></div>
|
||||
|
||||
<div class="btn-row"><button id="ask" class="btn btn-primary">Ask the wallet for its address</button></div>
|
||||
<div id="askOut"></div>
|
||||
|
||||
<pre id="dump">collecting…</pre>
|
||||
</main>
|
||||
<script src="/rmc-wallet.js"></script>
|
||||
<script src="/wallet-check.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,80 @@
|
||||
// Diagnostic page for wallet sign-in failures. Reports what the page can
|
||||
// actually see, from the member's own device, instead of us guessing.
|
||||
//
|
||||
// It captures the one thing we cannot infer from the outside: whether a CSP
|
||||
// violation is firing when the wallet tries to inject its provider. Our
|
||||
// script-src is 'self' with no 'unsafe-inline', and wallet browsers that inject
|
||||
// via a <script> tag would be blocked silently — no error the member could see,
|
||||
// and identical symptoms to "no wallet installed".
|
||||
(function () {
|
||||
'use strict';
|
||||
var violations = [];
|
||||
window.addEventListener('securitypolicyviolation', function (e) {
|
||||
violations.push(e.violatedDirective + ' blocked ' + (e.blockedURI || '(inline)') +
|
||||
(e.sourceFile ? ' from ' + e.sourceFile : ''));
|
||||
render();
|
||||
});
|
||||
|
||||
function row(k, v, good) {
|
||||
return '<div class="row"><div class="k">' + k + '</div><div class="v ' +
|
||||
(good === true ? 'yes' : good === false ? 'no' : '') + '">' + v + '</div></div>';
|
||||
}
|
||||
function esc(s) {
|
||||
return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
|
||||
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c];
|
||||
});
|
||||
}
|
||||
|
||||
var announced = [];
|
||||
window.addEventListener('eip6963:announceProvider', function (e) {
|
||||
try { announced.push(e.detail.info.name + ' (' + e.detail.info.rdns + ')'); } catch (x) {}
|
||||
render();
|
||||
});
|
||||
try { window.dispatchEvent(new Event('eip6963:requestProvider')); } catch (x) {}
|
||||
|
||||
function render() {
|
||||
var eth = window.ethereum;
|
||||
var flags = [];
|
||||
if (eth) {
|
||||
['isMetaMask', 'isTrust', 'isTrustWallet', 'isCoinbaseWallet', 'isSafePal', 'isPhantom', 'isRabby']
|
||||
.forEach(function (f) { if (eth[f]) flags.push(f); });
|
||||
if (eth.providers && eth.providers.length) flags.push('providers[' + eth.providers.length + ']');
|
||||
}
|
||||
var html = '';
|
||||
html += row('window.ethereum present', eth ? 'YES' : 'NO', !!eth);
|
||||
html += row('wallet flags', flags.length ? esc(flags.join(', ')) : '(none)');
|
||||
html += row('EIP-6963 wallets announced', announced.length ? esc(announced.join(' · ')) : '(none)');
|
||||
html += row('CSP violations seen', violations.length ? esc(violations.join(' | ')) : 'none', violations.length ? false : true);
|
||||
html += row('page address', esc(location.href));
|
||||
document.getElementById('rows').innerHTML = html;
|
||||
|
||||
document.getElementById('dump').textContent =
|
||||
'UA: ' + navigator.userAgent + '\n' +
|
||||
'ethereum: ' + (eth ? 'yes' : 'no') + '\n' +
|
||||
'flags: ' + (flags.join(',') || '-') + '\n' +
|
||||
'eip6963: ' + (announced.join(',') || '-') + '\n' +
|
||||
'csp: ' + (violations.join(' | ') || 'none') + '\n' +
|
||||
'href: ' + location.href;
|
||||
}
|
||||
|
||||
document.getElementById('ask').addEventListener('click', async function () {
|
||||
var out = document.getElementById('askOut');
|
||||
out.innerHTML = '';
|
||||
try {
|
||||
var eth = await window.RMCWallet.pick();
|
||||
if (!eth) { out.innerHTML = row('result', 'No provider found — the page cannot see a wallet', false); return; }
|
||||
var accs = await eth.request({ method: 'eth_requestAccounts' });
|
||||
var chain = await eth.request({ method: 'eth_chainId' });
|
||||
out.innerHTML = row('accounts returned', esc(JSON.stringify(accs))) +
|
||||
row('first account', esc(accs && accs[0] || '(none)')) +
|
||||
row('selectedAddress', esc(eth.selectedAddress || '(not exposed)')) +
|
||||
row('chain id', esc(chain) + (chain === '0x89' ? ' — Polygon ✓' : ' — NOT Polygon'), chain === '0x89');
|
||||
} catch (e) {
|
||||
out.innerHTML = row('error', esc(e && (e.message || e.code || String(e))), false);
|
||||
}
|
||||
render();
|
||||
});
|
||||
|
||||
setTimeout(render, 400);
|
||||
render();
|
||||
})();
|
||||
Reference in New Issue
Block a user