diff --git a/public/assets/ark-library/wallets/imtoken.svg b/public/assets/ark-library/wallets/imtoken.svg new file mode 100644 index 0000000..012c382 --- /dev/null +++ b/public/assets/ark-library/wallets/imtoken.svg @@ -0,0 +1 @@ + diff --git a/public/assets/ark-library/wallets/tokenpocket.svg b/public/assets/ark-library/wallets/tokenpocket.svg new file mode 100644 index 0000000..5c13e59 --- /dev/null +++ b/public/assets/ark-library/wallets/tokenpocket.svg @@ -0,0 +1 @@ +tokenpocket \ No newline at end of file diff --git a/src/wallet/RainbowWalletProvider.tsx b/src/wallet/RainbowWalletProvider.tsx index f8ecff2..1414aa4 100644 --- a/src/wallet/RainbowWalletProvider.tsx +++ b/src/wallet/RainbowWalletProvider.tsx @@ -7,7 +7,6 @@ import { } from "@rainbow-me/rainbowkit"; import { imTokenWallet, - metaMaskWallet, tokenPocketWallet, } from "@rainbow-me/rainbowkit/wallets"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; @@ -22,7 +21,7 @@ const connectors = connectorsForWallets( [ { groupName: "ARK Library", - wallets: [metaMaskWallet, imTokenWallet, tokenPocketWallet], + wallets: [imTokenWallet, tokenPocketWallet], }, ], { diff --git a/src/wallet/WalletBrandIcon.tsx b/src/wallet/WalletBrandIcon.tsx index ad3fac3..0357ca7 100644 --- a/src/wallet/WalletBrandIcon.tsx +++ b/src/wallet/WalletBrandIcon.tsx @@ -1,11 +1,8 @@ import type { WalletKind } from "./injected"; -type Brand = { bg: string; label: string }; - -const brands: Record = { - tokenPocket: { bg: "#2980FE", label: "TP" }, - metaMask: { bg: "#F6851B", label: "M" }, - imToken: { bg: "#11C4D1", label: "im" }, +const logos: Partial> = { + tokenPocket: "/assets/ark-library/wallets/tokenpocket.svg", + imToken: "/assets/ark-library/wallets/imtoken.svg", }; export function WalletBrandIcon({ @@ -15,14 +12,17 @@ export function WalletBrandIcon({ kind: WalletKind; size?: number; }) { - const brand = brands[kind]; + const logo = logos[kind]; + if (!logo) return null; + return ( - + width={size} + height={size} + className="inline-flex shrink-0 rounded-lg" + /> ); } diff --git a/src/wallet/WalletLoginModal.tsx b/src/wallet/WalletLoginModal.tsx index 1ed82ca..a3a63fa 100644 --- a/src/wallet/WalletLoginModal.tsx +++ b/src/wallet/WalletLoginModal.tsx @@ -1,11 +1,13 @@ -import { QRCodeSVG } from "qrcode.react"; import { LoaderCircle, X } from "lucide-react"; import { useEffect, useState } from "react"; import { useI18n } from "../i18n"; import { walletDeepLink } from "./deepLinks"; -import { getInjectedWallet, type WalletKind } from "./injected"; -import { useWallet } from "./WalletProvider"; -import { useWalletConnectLogin } from "./useWalletConnectLogin"; +import { + connectInjectedWallet, + getInjectedWallet, + type WalletKind, +} from "./injected"; +import { localWalletToken, useWallet } from "./WalletProvider"; import { WalletBrandIcon } from "./WalletBrandIcon"; const AUTO_LOGIN_PARAM = "autoLogin"; @@ -20,7 +22,9 @@ function buildAutoLoginDappUrl(kind: WalletKind): string { return url.toString(); } -const wallets: WalletKind[] = ["tokenPocket", "metaMask", "imToken"]; +const wallets: WalletKind[] = ["tokenPocket", "imToken"]; + +type LoginState = "idle" | "connecting"; function isMobileDevice(): boolean { if (typeof navigator === "undefined") return false; @@ -31,60 +35,66 @@ function isMobileDevice(): boolean { export function WalletLoginModal() { const { t } = useI18n(); - const { closeLoginModal, loginModalOpen } = useWallet(); - const wc = useWalletConnectLogin(); + const { closeLoginModal, completeLogin, loginModalOpen } = useWallet(); const [selected, setSelected] = useState(null); const [mobileDevice, setMobileDevice] = useState(false); - - const resetWalletConnect = wc.reset; + const [state, setState] = useState("idle"); + const [error, setError] = useState(""); useEffect(() => { if (!loginModalOpen) return; setMobileDevice(isMobileDevice()); setSelected(null); - resetWalletConnect(); - }, [loginModalOpen, resetWalletConnect]); + setState("idle"); + setError(""); + }, [loginModalOpen]); if (!loginModalOpen) return null; const walletName = (kind: WalletKind) => t(walletNameKey(kind)); - const walletHint = (kind: WalletKind) => { - if (kind === "tokenPocket") { - return mobileDevice - ? t("walletTpMobileDesc") - : t("walletTokenPocketQrDesc"); - } - return t("walletRainbowFallbackDesc"); - }; - const busy = wc.state !== "idle"; + const walletHint = () => + mobileDevice ? t("walletChooseMobile") : t("walletDesktopHint"); + const busy = state !== "idle"; const close = () => { closeLoginModal(); setSelected(null); - wc.reset(); + setState("idle"); + setError(""); }; const selectWallet = (kind: WalletKind) => { setSelected(kind); - wc.reset(); + setError(""); }; - const startWalletLogin = (kind: WalletKind, mode: "deeplink" | "qr") => { + const loginInjected = async (kind: WalletKind) => { setSelected(kind); - void wc.start(kind, mode); + setState("connecting"); + setError(""); + try { + const address = await connectInjectedWallet(kind); + completeLogin(localWalletToken(address), address); + } catch (err) { + setState("idle"); + setError(err instanceof Error ? err.message : t("walletLoginFailed")); + } }; const openWalletAppDirect = (kind: WalletKind) => { if (getInjectedWallet(kind)) { - startWalletLogin(kind, "deeplink"); + void loginInjected(kind); return; } if (mobileDevice && supportsDirectPull(kind)) { + setSelected(kind); + setError(""); const deeplink = walletDeepLink(kind, buildAutoLoginDappUrl(kind)); window.location.href = deeplink; return; } - startWalletLogin(kind, "deeplink"); + setSelected(kind); + setError(t("walletInstallSelected").replace("{wallet}", walletName(kind))); }; return ( @@ -120,8 +130,7 @@ export function WalletLoginModal() {
{wallets.map((kind) => { const active = selected === kind; - const connecting = active && wc.state === "connecting"; - const signing = active && wc.state === "signing"; + const connecting = active && state === "connecting"; return (
mobileDevice ? selectWallet(kind) - : startWalletLogin(kind, "qr") + : openWalletAppDirect(kind) } - disabled={!wc.available || busy} + disabled={busy} className="flex w-full items-center gap-3 text-left disabled:cursor-wait disabled:opacity-70" > @@ -147,38 +156,24 @@ export function WalletLoginModal() { {walletName(kind)} - {connecting - ? t("walletConnecting") - : signing - ? t("walletSigning") - : walletHint(kind)} + {connecting ? t("walletConnecting") : walletHint()} - {connecting || signing ? ( + {connecting ? ( ) : null} {mobileDevice && active ? ( -
+
-
) : null}
@@ -186,37 +181,9 @@ export function WalletLoginModal() { })}
- {!wc.available ? ( -

- {t("walletRainbowUnavailable")} -

- ) : null} - - {selected && wc.qrUri ? ( -
- -
- ) : null} - - {wc.error ? ( + {error ? (

- {wc.error} -

- ) : null} - - {selected ? ( -
-

Wallet debug

-

state: {wc.state}

-

connected: {wc.isConnected ? "yes" : "no"}

-

address: {wc.address || "-"}

-

qr: {wc.qrUri ? "received" : "-"}

-
- ) : null} - - {selected ? ( -

- {t("walletNetworkWarning")} + {error}

) : null}
@@ -225,7 +192,5 @@ export function WalletLoginModal() { } function walletNameKey(kind: WalletKind): string { - if (kind === "tokenPocket") return "walletTokenPocket"; - if (kind === "metaMask") return "walletMetaMask"; - return "walletImToken"; + return kind === "tokenPocket" ? "walletTokenPocket" : "walletImToken"; }