From e735c1f5e44ba7a70e8b0abe7c80699c264f6012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rn=20Andre=20Tangen=20=40gorillatron?= Date: Tue, 6 Feb 2024 12:51:19 +0100 Subject: [PATCH] Filter out eth accounts and show error notification when user connects one --- lib/state/notifications.ts | 84 ++++++++++----------- lib/state/{wallet.ts => wallet.tsx} | 109 +++++++++++++++++++--------- 2 files changed, 118 insertions(+), 75 deletions(-) rename lib/state/{wallet.ts => wallet.tsx} (84%) diff --git a/lib/state/notifications.ts b/lib/state/notifications.ts index 79e6843c4..bf337ca7c 100644 --- a/lib/state/notifications.ts +++ b/lib/state/notifications.ts @@ -45,7 +45,7 @@ export type UseNotifications = { * @param options - Options for the notification. */ pushNotification( - content: string, + content: string | ReactNode, options?: { type?: NotificationType; lifetime?: number; @@ -71,56 +71,56 @@ const notificationsAtom = atom([]); */ const store = getDefaultStore(); -/** - * Hook to use the notification state. - * - * @returns UseNotifications - */ -export const useNotifications = (): UseNotifications => { - const atom = useAtom(notificationsAtom); - - const pushNotification: UseNotifications["pushNotification"] = ( +export const pushNotification: UseNotifications["pushNotification"] = ( + content, + options, +) => { + const notification: Notification = { + id: generateGUID(), content, - options, - ) => { - const notification: Notification = { - id: generateGUID(), - content, - autoRemove: options?.autoRemove ?? false, - lifetime: options?.lifetime ?? 100, - type: options?.type ?? "Info", - }; + autoRemove: options?.autoRemove ?? false, + lifetime: options?.lifetime ?? 100, + type: options?.type ?? "Info", + }; - const notifications = store.get(notificationsAtom); + const notifications = store.get(notificationsAtom); - let nextNotifications = [...notifications]; + let nextNotifications = [...notifications]; - const latestNotification = notifications[notifications.length - 1]; + const latestNotification = notifications[notifications.length - 1]; - if (latestNotification?.autoRemove) { - nextNotifications = notifications.slice(0, -1); - } + if (latestNotification?.autoRemove) { + nextNotifications = notifications.slice(0, -1); + } - nextNotifications = [...nextNotifications, notification]; + nextNotifications = [...nextNotifications, notification]; - store.set(notificationsAtom, nextNotifications); + store.set(notificationsAtom, nextNotifications); - return notification; - }; + return notification; +}; - const removeNotification: UseNotifications["removeNotification"] = ( - notification, - ) => { - const notifications = store.get(notificationsAtom); - store.set( - notificationsAtom, - notifications.filter((n) => - typeof notification === "string" - ? n.id !== notification - : n.id !== notification.id, - ), - ); - }; +export const removeNotification: UseNotifications["removeNotification"] = ( + notification, +) => { + const notifications = store.get(notificationsAtom); + store.set( + notificationsAtom, + notifications.filter((n) => + typeof notification === "string" + ? n.id !== notification + : n.id !== notification.id, + ), + ); +}; + +/** + * Hook to use the notification state. + * + * @returns UseNotifications + */ +export const useNotifications = (): UseNotifications => { + const atom = useAtom(notificationsAtom); return { notifications: atom[0], diff --git a/lib/state/wallet.ts b/lib/state/wallet.tsx similarity index 84% rename from lib/state/wallet.ts rename to lib/state/wallet.tsx index 6ca6794ac..a10e51e38 100644 --- a/lib/state/wallet.ts +++ b/lib/state/wallet.tsx @@ -1,28 +1,32 @@ -import { encodeAddress } from "@polkadot/util-crypto"; -import { KeyringPairOrExtSigner } from "@zeitgeistpm/rpc"; -import { tryCatch } from "@zeitgeistpm/utility/dist/option"; -import { atom, getDefaultStore, useAtom } from "jotai"; -import { u8aToHex, stringToHex } from "@polkadot/util"; -import { isString } from "lodash-es"; -import { useMemo } from "react"; -import { persistentAtom } from "./util/persistent-atom"; +import { Keyring } from "@polkadot/api"; +import { InjectedAccount } from "@polkadot/extension-inject/types"; +import { KeyringPair } from "@polkadot/keyring/types"; +import { stringToHex, u8aToHex } from "@polkadot/util"; +import { cryptoWaitReady, encodeAddress } from "@polkadot/util-crypto"; import { BaseDotsamaWallet, PolkadotjsWallet, SubWallet, TalismanWallet, } from "@talismn/connect-wallets"; -import { Keyring } from "@polkadot/api"; -import { cryptoWaitReady } from "@polkadot/util-crypto"; -import { InjectedAccount } from "@polkadot/extension-inject/types"; +import { IProvider } from "@web3auth/base"; +import { KeyringPairOrExtSigner } from "@zeitgeistpm/rpc"; +import { tryCatch } from "@zeitgeistpm/utility/dist/option"; +import { atom, getDefaultStore, useAtom } from "jotai"; import { isPresent } from "lib/types"; -import { KeyringPair } from "@polkadot/keyring/types"; import { PollingTimeout, poll } from "lib/util/poll"; -import { IProvider } from "@web3auth/base"; +import { isString } from "lodash-es"; +import { useMemo } from "react"; +import { persistentAtom } from "./util/persistent-atom"; //Web3Auth -import { web3authAtom } from "./util/web3auth-config"; -import { web3AuthWalletInstance } from "./util/web3auth-config"; +import { isNotNull } from "@zeitgeistpm/utility/dist/null"; +import { + Notification, + pushNotification, + removeNotification, +} from "./notifications"; +import { web3AuthWalletInstance, web3authAtom } from "./util/web3auth-config"; const DAPP_NAME = "zeitgeist"; @@ -227,6 +231,8 @@ export const supportedWallets = [ let accountsSubscriptionUnsub: VoidFunction | undefined | null; +let currentErrorNotification: Readonly | null = null; + /** * Enable a wallet by enabling the extension and setting the wallet atom state to connected. * Also starts subscribing to accounts on the extension and updates the accounts in state. @@ -243,6 +249,7 @@ const enableWallet = async (walletId: string) => { if (!isPresent(wallet)) { return; } + const enablePoll = async (): Promise => { try { const extension = await poll( @@ -283,25 +290,56 @@ const enableWallet = async (walletId: string) => { accountsSubscriptionUnsub = await wallet?.subscribeAccounts((accounts) => { store.set(walletAtom, (state) => { + const hasConnectedEthereumAccount = accounts?.some((account) => { + if ((account as any).type?.toLowerCase() === "ethereum") { + return true; + } + }); + + if (hasConnectedEthereumAccount) { + currentErrorNotification = pushNotification( +
+
Ethereum accounts are unsupported.
+
+ You have a ethereum account connected in your{" "} + {wallet.extensionName} wallet but it will be filtered out as it + is not supported. +
+
, + { + autoRemove: true, + lifetime: 20_000, + type: "Error", + }, + ); + } else if (currentErrorNotification) { + removeNotification(currentErrorNotification); + } + return { ...state, connected: Boolean(accounts && accounts.length > 0), accounts: - accounts?.map((account) => { - return { - ...account, - address: encodeAddress(account.address, 73), - }; - }) ?? [], - errors: + accounts + ?.map((account) => { + try { + return { + ...account, + address: encodeAddress(account.address, 73), + }; + } catch (error) { + return null; + } + }) + .filter(isNotNull) ?? [], + errors: [ accounts?.length === 0 - ? [ - { - extensionName: wallet.extensionName, - type: "NoAccounts", - }, - ] - : [], + ? ({ + extensionName: wallet.extensionName, + type: "NoAccounts", + } satisfies WalletError) + : null, + ].filter(isNotNull), }; }); }); @@ -389,14 +427,19 @@ export const useWallet = (): UseWallet => { } }; - const selectWallet = (wallet: BaseDotsamaWallet | string) => { + const selectWallet = async (wallet: BaseDotsamaWallet | string) => { setUserConfig({ ...userConfig, walletId: isString(wallet) ? wallet : wallet.extensionName, }); - wallet === "web3auth" - ? loadWeb3AuthWallet() - : enableWallet(isString(wallet) ? wallet : wallet.extensionName); + + if (wallet === "web3auth") { + loadWeb3AuthWallet(); + } else { + const error = await enableWallet( + isString(wallet) ? wallet : wallet.extensionName, + ); + } }; const disconnectWallet = async () => {