import { requestWalletNonce, verifyWalletSignature } from "./api"; export type WalletKind = "tokenPocket" | "metaMask" | "imToken"; const bnbChainIdHex = "0x38"; export type EthereumProvider = { isMetaMask?: boolean; isTokenPocket?: boolean; isImToken?: boolean; providers?: EthereumProvider[]; request: (args: { method: string; params?: unknown[]; }) => Promise; }; export function getInjectedEthereum(): EthereumProvider | null { if (typeof window === "undefined") return null; const maybeWindow = window as typeof window & { ethereum?: EthereumProvider }; return maybeWindow.ethereum ?? null; } export function getInjectedWallet(kind?: WalletKind): EthereumProvider | null { const ethereum = getInjectedEthereum(); if (!ethereum || !kind) return ethereum; const providers = ethereum.providers?.length ? ethereum.providers : [ethereum]; const match = providers.find((provider) => { if (kind === "metaMask") return provider.isMetaMask; if (kind === "tokenPocket") return provider.isTokenPocket; if (kind === "imToken") return provider.isImToken; return false; }); return match ?? null; } async function ensureBnbChain(ethereum: EthereumProvider): Promise { try { await ethereum.request({ method: "wallet_switchEthereumChain", params: [{ chainId: bnbChainIdHex }], }); } catch (error) { const code = (error as { code?: number | string }).code; if (code !== 4902 && code !== "4902") throw error; await ethereum.request({ method: "wallet_addEthereumChain", params: [ { blockExplorerUrls: ["https://bscscan.com"], chainId: bnbChainIdHex, chainName: "BNB Smart Chain", nativeCurrency: { decimals: 18, name: "BNB", symbol: "BNB" }, rpcUrls: ["https://bsc-dataseed.binance.org"], }, ], }); } } export async function signInWithInjectedWallet(kind?: WalletKind): Promise<{ token: string; wallet: string; }> { const ethereum = getInjectedWallet(kind); if (!ethereum) throw new Error("No injected wallet found"); await ensureBnbChain(ethereum); const accounts = await ethereum.request({ method: "eth_requestAccounts", }); const address = accounts[0]; if (!address) throw new Error("No wallet account returned"); const nonce = await requestWalletNonce(address); const signature = await ethereum.request({ method: "personal_sign", params: [nonce.message, address], }); return verifyWalletSignature({ address, message: nonce.message, signature, }); }