// Helpers for steering mobile users into a wallet's in-app browser.
//
// On mobile, WalletConnect can silently lose the signature response when the
// browser is backgrounded during signing (the relay WebSocket is torn down).
// The robust fix — used by Polymarket itself — is to open the dApp *inside*
// the wallet's own browser: there is no app switching, the wallet injects an
// EIP-1193 provider, and signing happens natively with no relay involved.
export function isMobile(): boolean {
if (typeof navigator === 'undefined') return false;
return /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
}
// An injected EIP-1193 provider means we're already inside a wallet's in-app
// browser (mobile) or a desktop extension — either way, no banner is needed.
export function hasInjectedProvider(): boolean {
if (typeof window === 'undefined') return false;
return !!(window as { ethereum?: unknown }).ethereum;
}
// Show the "open in wallet" banner only for mobile users without an injected
// provider — exactly the population that hits the WalletConnect signing bug.
export function shouldSuggestWalletBrowser(): boolean {
return isMobile() && !hasInjectedProvider();
}
export interface WalletDeepLink {
name: string;
url: string;
}
// Each wallet uses its own deep-link scheme — there is no standard. We preserve
// the current path/query so the user lands on the same page inside the wallet.
export function buildWalletDeepLinks(): WalletDeepLink[] {
if (typeof window === 'undefined') return [];
const { host, pathname, search } = window.location;
const bare = `${host}${pathname}${search}`; // no scheme — MetaMask format
const full = `https://${bare}`;
const encoded = encodeURIComponent(full);
return [
{ name: 'MetaMask', url: `https://metamask.app.link/dapp/${bare}` },
{ name: 'Coinbase', url: `https://go.cb-w.com/dapp?cb_url=${encoded}` },
{ name: 'Trust', url: `https://link.trustwallet.com/open_url?url=${encoded}` },
];
}
📜 Git History
6c47fa4chore: local Polikopi project home + Phase 1 redesign artifacts12 days ago