diff --git a/apps/namada-interface/src/services/extensionEvents/handlers/keplr.ts b/apps/namada-interface/src/services/extensionEvents/handlers/keplr.ts index 8d7bc073b..9eb06af33 100644 --- a/apps/namada-interface/src/services/extensionEvents/handlers/keplr.ts +++ b/apps/namada-interface/src/services/extensionEvents/handlers/keplr.ts @@ -1,22 +1,15 @@ import { Dispatch } from "react"; -import { chains } from "@anoma/chains"; import { Keplr } from "@anoma/integrations"; import { addAccounts, fetchBalances } from "slices/accounts"; export const KeplrAccountChangedHandler = - (dispatch: Dispatch, integration: Keplr) => - async (event: CustomEventInit) => { - const chainId = event.detail?.chainId; - const chain = chains[chainId]; + (dispatch: Dispatch, integration: Keplr) => async () => { + const accounts = await integration.accounts(); - if (chain.extension.id === "keplr") { - const accounts = await integration.accounts(); - - if (accounts) { - dispatch(addAccounts(accounts)); - dispatch(fetchBalances()); - } + if (accounts) { + dispatch(addAccounts(accounts)); + dispatch(fetchBalances()); } }; diff --git a/apps/namada-interface/src/services/extensionEvents/handlers/metamask.ts b/apps/namada-interface/src/services/extensionEvents/handlers/metamask.ts index e026b1f9b..7d60dae73 100644 --- a/apps/namada-interface/src/services/extensionEvents/handlers/metamask.ts +++ b/apps/namada-interface/src/services/extensionEvents/handlers/metamask.ts @@ -1,22 +1,13 @@ import { Dispatch } from "react"; - -import { chains } from "@anoma/chains"; import { Metamask } from "@anoma/integrations"; - import { addAccounts, fetchBalances } from "slices/accounts"; export const MetamaskAccountChangedHandler = - (dispatch: Dispatch, integration: Metamask) => - async (event: CustomEventInit) => { - const chainId = event.detail?.chainId; - const chain = chains[chainId]; - - if (chain.extension.id === "metamask") { - const accounts = await integration.accounts(); + (dispatch: Dispatch, integration: Metamask) => async () => { + const accounts = await integration.accounts(); - if (accounts) { - dispatch(addAccounts(accounts)); - dispatch(fetchBalances()); - } + if (accounts) { + dispatch(addAccounts(accounts)); + dispatch(fetchBalances()); } }; diff --git a/apps/namada-interface/src/services/extensionEvents/provider.tsx b/apps/namada-interface/src/services/extensionEvents/provider.tsx index a5e346458..b1ccc0e1f 100644 --- a/apps/namada-interface/src/services/extensionEvents/provider.tsx +++ b/apps/namada-interface/src/services/extensionEvents/provider.tsx @@ -1,8 +1,12 @@ import { createContext } from "react"; -import { Events } from "@anoma/types"; -import { defaultChainId } from "@anoma/chains"; -import { Anoma } from "@anoma/integrations"; +import { Events, KeplrEvents, MetamaskEvents } from "@anoma/types"; +import { + defaultChainId, + defaultCosmosChainId, + defaultEthereumChainId, +} from "@anoma/chains"; +import { Anoma, Keplr, Metamask } from "@anoma/integrations"; import { useEventListenerOnce, useIntegration } from "@anoma/hooks"; import { useAppDispatch } from "store"; @@ -11,13 +15,17 @@ import { AnomaTransferCompletedHandler, AnomaTransferStartedHandler, AnomaUpdatedBalancesHandler, -} from "./handlers/anoma"; + KeplrAccountChangedHandler, + MetamaskAccountChangedHandler, +} from "./handlers"; export const ExtensionEventsContext = createContext({}); export const ExtensionEventsProvider: React.FC = (props): JSX.Element => { const dispatch = useAppDispatch(); const anomaIntegration = useIntegration(defaultChainId); + const keplrIntegration = useIntegration(defaultCosmosChainId); + const metamaskIntegration = useIntegration(defaultEthereumChainId); // Instantiate handlers: const anomaAccountChangedHandler = AnomaAccountChangedHandler( @@ -26,14 +34,37 @@ export const ExtensionEventsProvider: React.FC = (props): JSX.Element => { ); const anomaTransferStartedHandler = AnomaTransferStartedHandler(dispatch); const anomaTransferCompletedHandler = AnomaTransferCompletedHandler(dispatch); - const anomaUpdatedBalancesHandler = AnomaUpdatedBalancesHandler(dispatch); + // Keplr handlers + const keplrAccountChangedHandler = KeplrAccountChangedHandler( + dispatch, + keplrIntegration as Keplr + ); + + // Metamask handlers + const metamaskAccountChangedHandler = MetamaskAccountChangedHandler( + dispatch, + metamaskIntegration as Metamask + ); + // Register handlers: useEventListenerOnce(Events.AccountChanged, anomaAccountChangedHandler); useEventListenerOnce(Events.TransferStarted, anomaTransferStartedHandler); useEventListenerOnce(Events.TransferCompleted, anomaTransferCompletedHandler); useEventListenerOnce(Events.UpdatedBalances, anomaUpdatedBalancesHandler); + useEventListenerOnce(KeplrEvents.AccountChanged, keplrAccountChangedHandler); + useEventListenerOnce( + MetamaskEvents.AccountChanged, + metamaskAccountChangedHandler, + false, + (event, handler) => { + window.ethereum.on(event, handler); + }, + (event, handler) => { + window.ethereum.removeListener(event, handler); + } + ); return ( diff --git a/packages/chains/src/index.ts b/packages/chains/src/index.ts index 51a602794..2106ad332 100644 --- a/packages/chains/src/index.ts +++ b/packages/chains/src/index.ts @@ -3,6 +3,8 @@ import namada from "./chains/namada"; import ethereum from "./chains/ethereum"; export const defaultChainId = namada.chainId; +export const defaultCosmosChainId = cosmos.chainId; +export const defaultEthereumChainId = ethereum.chainId; export const chains = { [cosmos.chainId]: cosmos, diff --git a/packages/hooks/src/useEvent.ts b/packages/hooks/src/useEvent.ts index a9a4761c3..1b07bd20a 100644 --- a/packages/hooks/src/useEvent.ts +++ b/packages/hooks/src/useEvent.ts @@ -1,15 +1,25 @@ import { useEffect } from "react"; +type EventHandler = (e: CustomEventInit) => void; +type EventCallback = (event: string, handler: EventHandler) => void; + export const useEventListener = ( event: string, - handler: (e: CustomEventInit) => void, + handler: EventHandler, deps?: React.DependencyList, - useCapture = false + useCapture = false, + registerCallback?: EventCallback, + removeCallback?: EventCallback ): void => { useEffect(() => { - window.addEventListener(event, handler, useCapture); + registerCallback + ? registerCallback(event, handler) + : window.addEventListener(event, handler, useCapture); return () => { + if (removeCallback) { + return removeCallback(event, handler); + } window.removeEventListener(event, handler); }; }, deps); @@ -17,8 +27,17 @@ export const useEventListener = ( export const useEventListenerOnce = ( event: string, - handler: (e: CustomEventInit) => void, - useCapture = false + handler: EventHandler, + useCapture = false, + registerCallback?: EventCallback, + removeCallback?: EventCallback ): void => { - useEventListener(event, handler, [], useCapture); + useEventListener( + event, + handler, + [], + useCapture, + registerCallback, + removeCallback + ); }; diff --git a/packages/types/src/events.ts b/packages/types/src/events.ts index b54c4d15b..5fecc6e84 100644 --- a/packages/types/src/events.ts +++ b/packages/types/src/events.ts @@ -1,8 +1,19 @@ // Constants defining events which may be subscribed to +// Anoma extension events export enum Events { AccountChanged = "anoma-account-changed", TransferStarted = "anoma-transfer-started", TransferCompleted = "anoma-transfer-completed", UpdatedBalances = "anoma-updated-balances", } + +// Keplr extension events +export enum KeplrEvents { + AccountChanged = "keplr_keystorechange", +} + +// Metamask extension window.ethereum events +export enum MetamaskEvents { + AccountChanged = "accountsChanged", +}