Files
Arkie-Library-Frontend/src/wallet/AutoInjectedLogin.tsx
2026-06-04 09:55:19 +08:00

87 lines
2.4 KiB
TypeScript

import { useEffect } from "react";
import {
connectInjectedWallet,
getInjectedWallet,
isImTokenBrowser,
signInWithInjectedWallet,
type WalletKind,
} from "./injected";
import { localWalletToken, useWallet } from "./WalletProvider";
const AUTO_LOGIN_PARAM = "autoLogin";
const ETHEREUM_WAIT_MS = 8000;
const ETHEREUM_POLL_MS = 200;
function parseKind(value: string | null): WalletKind | null {
if (value === "tokenPocket" || value === "metaMask" || value === "imToken") {
return value;
}
return null;
}
function stripAutoLoginParam(): void {
const url = new URL(window.location.href);
url.searchParams.delete(AUTO_LOGIN_PARAM);
const qs = url.searchParams.toString();
const next = url.pathname + (qs ? `?${qs}` : "") + url.hash;
window.history.replaceState({}, "", next);
}
function waitForInjected(kind: WalletKind): Promise<boolean> {
return new Promise((resolve) => {
const start = Date.now();
const tick = () => {
if (getInjectedWallet(kind)) {
resolve(true);
return;
}
if (Date.now() - start >= ETHEREUM_WAIT_MS) {
resolve(false);
return;
}
window.setTimeout(tick, ETHEREUM_POLL_MS);
};
tick();
});
}
export function AutoInjectedLogin() {
const { completeLogin, status } = useWallet();
useEffect(() => {
if (typeof window === "undefined") return;
const params = new URLSearchParams(window.location.search);
const explicitKind = parseKind(params.get(AUTO_LOGIN_PARAM));
const kind = explicitKind ?? (isImTokenBrowser() ? "imToken" : null);
if (!kind) return;
if (status === "loading") return;
if (explicitKind) stripAutoLoginParam();
if (status === "loggedIn") return;
let cancelled = false;
void waitForInjected(kind).then(async (ready) => {
if (cancelled || !ready) return;
try {
if (kind === "imToken") {
const address = await connectInjectedWallet(kind);
if (cancelled) return;
completeLogin(localWalletToken(address), address);
return;
}
const res = await signInWithInjectedWallet(kind);
if (cancelled) return;
completeLogin(res.token, res.wallet);
} catch (err) {
console.warn("[wallet-autologin] failed", err);
}
});
return () => {
cancelled = true;
};
}, [completeLogin, status]);
return null;
}