fix: keep desktop browser-wallet on direct injected; add login diagnostics
Revert desktop primary back to the direct injected sign (no WalletConnect relay, which could spin forever) — reliable for a BNB-chain extension. Add console diagnostics ([wallet-login] ...) and provider enumeration so a stuck/no-popup flow can be pinpointed. WalletConnect stays as the explicit mobile MetaMask/ imToken option. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -146,18 +146,6 @@ export function WalletLoginModal() {
|
|||||||
.finally(() => setState("idle"));
|
.finally(() => setState("idle"));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Desktop: open the RainbowKit modal — it discovers every installed wallet
|
|
||||||
// via EIP-6963 (robust when several extensions fight over window.ethereum)
|
|
||||||
// and also offers a WalletConnect QR. Fall back to the raw injected flow only
|
|
||||||
// when WalletConnect has no project id configured.
|
|
||||||
const connectBrowserWallet = () => {
|
|
||||||
if (wc.available) {
|
|
||||||
wc.start();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
void signInjected();
|
|
||||||
};
|
|
||||||
|
|
||||||
const openApp = (kind: WalletKind) => {
|
const openApp = (kind: WalletKind) => {
|
||||||
setError("");
|
setError("");
|
||||||
setOpeningWallet(kind);
|
setOpeningWallet(kind);
|
||||||
@@ -213,29 +201,20 @@ export function WalletLoginModal() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-5 grid gap-3">
|
<div className="mt-5 grid gap-3">
|
||||||
{/* Browser wallet: in a wallet's in-app browser we sign directly with
|
{/* Browser wallet: sign directly with the injected provider — the
|
||||||
the injected provider; on desktop we open the RainbowKit picker so
|
reliable path for a BNB-chain extension (desktop) or a wallet's
|
||||||
the user can choose among installed extensions reliably. */}
|
in-app browser. No WalletConnect relay involved. */}
|
||||||
{mobileDevice && hasInjected ? (
|
{!mobileDevice || hasInjected ? (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => void signInjected()}
|
onClick={() => void signInjected()}
|
||||||
disabled={busy}
|
disabled={busy}
|
||||||
className="flex items-center justify-center gap-2 rounded-2xl bg-ark-gold px-4 py-4 text-base font-bold text-black transition hover:bg-ark-gold2 disabled:cursor-wait disabled:opacity-70"
|
className="flex items-center justify-center gap-2 rounded-2xl bg-ark-gold px-4 py-4 text-base font-bold text-black transition hover:bg-ark-gold2 disabled:cursor-wait disabled:opacity-70"
|
||||||
>
|
>
|
||||||
{state === "signing" ? t("walletSigning") : t("walletUseCurrent")}
|
{state === "signing"
|
||||||
</button>
|
|
||||||
) : !mobileDevice ? (
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={connectBrowserWallet}
|
|
||||||
disabled={busy || wc.state !== "idle"}
|
|
||||||
className="flex items-center justify-center gap-2 rounded-2xl bg-ark-gold px-4 py-4 text-base font-bold text-black transition hover:bg-ark-gold2 disabled:cursor-wait disabled:opacity-70"
|
|
||||||
>
|
|
||||||
{wc.state === "connecting"
|
|
||||||
? t("walletConnecting")
|
|
||||||
: wc.state === "signing" || state === "signing"
|
|
||||||
? t("walletSigning")
|
? t("walletSigning")
|
||||||
|
: mobileDevice
|
||||||
|
? t("walletUseCurrent")
|
||||||
: t("walletInjected")}
|
: t("walletInjected")}
|
||||||
</button>
|
</button>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -34,30 +34,66 @@ export function getInjectedWallet(kind?: WalletKind): EthereumProvider | null {
|
|||||||
return match ?? null;
|
return match ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Diagnostic: log what injected providers the browser exposes. */
|
||||||
|
export function logWalletProviders(): void {
|
||||||
|
const ethereum = getInjectedEthereum();
|
||||||
|
const list = (
|
||||||
|
ethereum?.providers?.length
|
||||||
|
? ethereum.providers
|
||||||
|
: ethereum
|
||||||
|
? [ethereum]
|
||||||
|
: []
|
||||||
|
).map((p) => ({
|
||||||
|
isMetaMask: Boolean(p.isMetaMask),
|
||||||
|
isTokenPocket: Boolean(p.isTokenPocket),
|
||||||
|
isImToken: Boolean(p.isImToken),
|
||||||
|
}));
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.info("[wallet-login] providers", {
|
||||||
|
hasEthereum: Boolean(ethereum),
|
||||||
|
count: list.length,
|
||||||
|
list,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export async function signInWithInjectedWallet(kind?: WalletKind): Promise<{
|
export async function signInWithInjectedWallet(kind?: WalletKind): Promise<{
|
||||||
token: string;
|
token: string;
|
||||||
wallet: string;
|
wallet: string;
|
||||||
}> {
|
}> {
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
console.info("[wallet-login] start injected", { kind });
|
||||||
|
logWalletProviders();
|
||||||
const ethereum = getInjectedWallet(kind);
|
const ethereum = getInjectedWallet(kind);
|
||||||
if (!ethereum) throw new Error("No injected wallet found");
|
if (!ethereum) {
|
||||||
|
console.warn("[wallet-login] no injected provider found");
|
||||||
|
throw new Error("No injected wallet found");
|
||||||
|
}
|
||||||
|
|
||||||
// Login is signature-only (EIP-191 personal_sign). The backend verifies the
|
// Login is signature-only (EIP-191 personal_sign). The backend verifies the
|
||||||
// recovered address and never inspects chainId, so we deliberately do NOT
|
// recovered address and never inspects chainId, so we deliberately do NOT
|
||||||
// switch or add any chain — that only adds a failure-prone wallet popup.
|
// switch or add any chain — that only adds a failure-prone wallet popup.
|
||||||
|
console.info("[wallet-login] requesting accounts (eth_requestAccounts)…");
|
||||||
const accounts = await ethereum.request<string[]>({
|
const accounts = await ethereum.request<string[]>({
|
||||||
method: "eth_requestAccounts",
|
method: "eth_requestAccounts",
|
||||||
});
|
});
|
||||||
|
console.info("[wallet-login] accounts", accounts);
|
||||||
const address = accounts[0];
|
const address = accounts[0];
|
||||||
if (!address) throw new Error("No wallet account returned");
|
if (!address) throw new Error("No wallet account returned");
|
||||||
|
|
||||||
|
console.info("[wallet-login] requesting nonce for", address);
|
||||||
const nonce = await requestWalletNonce(address);
|
const nonce = await requestWalletNonce(address);
|
||||||
|
console.info("[wallet-login] got nonce, requesting personal_sign…");
|
||||||
const signature = await ethereum.request<string>({
|
const signature = await ethereum.request<string>({
|
||||||
method: "personal_sign",
|
method: "personal_sign",
|
||||||
params: [nonce.message, address],
|
params: [nonce.message, address],
|
||||||
});
|
});
|
||||||
return verifyWalletSignature({
|
console.info("[wallet-login] signed, verifying with backend…");
|
||||||
|
const result = await verifyWalletSignature({
|
||||||
address,
|
address,
|
||||||
message: nonce.message,
|
message: nonce.message,
|
||||||
signature,
|
signature,
|
||||||
});
|
});
|
||||||
|
console.info("[wallet-login] verified, wallet =", result.wallet);
|
||||||
|
return result;
|
||||||
|
/* eslint-enable no-console */
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user