From b8d1a96b8521f35b071e076881ceaa56f3edcb0d Mon Sep 17 00:00:00 2001 From: Pedro Rezende Date: Thu, 19 Sep 2024 20:59:51 -0300 Subject: [PATCH] feat(namadillo): starting integration with keplr wallet --- .../App/Transfer/ConnectProviderButton.tsx | 2 +- .../src/App/Transfer/IBCFromNamadaModule.tsx | 27 +++++- .../src/App/Transfer/SelectProviderModal.tsx | 43 ---------- .../src/App/Transfer/SelectWalletModal.tsx | 44 ++++++++++ .../src/App/Transfer/SelectedChain.tsx | 14 ++-- .../src/App/Transfer/SelectedWallet.tsx | 49 +++++++++++ .../src/App/Transfer/TransferDestination.tsx | 8 +- .../src/App/Transfer/TransferModule.tsx | 28 ++++--- .../src/App/Transfer/TransferSource.tsx | 16 ++-- .../namadillo/src/App/Transfer/WalletCard.tsx | 50 +++++++++++ .../src/App/Transfer/__mocks__/providers.ts | 15 ++-- .../Transfer/__tests__/SelectedChain.test.tsx | 12 +-- .../__tests__/SelectedWallet.test.tsx | 82 +++++++++++++++++++ .../__tests__/TransferDestination.test.tsx | 6 +- .../__tests__/TransferSource.test.tsx | 4 +- .../Transfer/__tests__/WalletCard.test.tsx | 79 ++++++++++++++++++ .../namadillo/src/atoms/integrations/atoms.ts | 13 +++ .../namadillo/src/atoms/integrations/index.ts | 1 + .../src/hooks/useExtensionConnect.ts | 4 +- .../src/integrations/assets/keplr.svg | 30 +++++++ apps/namadillo/src/integrations/index.ts | 16 ++++ apps/namadillo/src/lib/query.ts | 7 +- apps/namadillo/src/types.d.ts | 8 +- .../integrations/src/hooks/useIntegration.ts | 47 ++++++----- 24 files changed, 480 insertions(+), 125 deletions(-) delete mode 100644 apps/namadillo/src/App/Transfer/SelectProviderModal.tsx create mode 100644 apps/namadillo/src/App/Transfer/SelectWalletModal.tsx create mode 100644 apps/namadillo/src/App/Transfer/SelectedWallet.tsx create mode 100644 apps/namadillo/src/App/Transfer/WalletCard.tsx create mode 100644 apps/namadillo/src/App/Transfer/__tests__/SelectedWallet.test.tsx create mode 100644 apps/namadillo/src/App/Transfer/__tests__/WalletCard.test.tsx create mode 100644 apps/namadillo/src/atoms/integrations/atoms.ts create mode 100644 apps/namadillo/src/atoms/integrations/index.ts create mode 100644 apps/namadillo/src/integrations/assets/keplr.svg create mode 100644 apps/namadillo/src/integrations/index.ts diff --git a/apps/namadillo/src/App/Transfer/ConnectProviderButton.tsx b/apps/namadillo/src/App/Transfer/ConnectProviderButton.tsx index b5935dd22..211cee4c5 100644 --- a/apps/namadillo/src/App/Transfer/ConnectProviderButton.tsx +++ b/apps/namadillo/src/App/Transfer/ConnectProviderButton.tsx @@ -10,7 +10,7 @@ export const ConnectProviderButton = ({ return ( { + const [selectedWallet, setWallet] = useAtom(selectedIBCWallet); + const [chainId, setChainId] = useAtom(selectedIBCChainAtom); + return (
- {}} /> + {}} + availableWallets={Object.values(wallets)} + selectedWallet={selectedWallet ? wallets[selectedWallet] : undefined} + onChangeWallet={async (wallet: WalletProvider) => { + try { + await integrations[wallet.id].connect(); + setWallet(wallet.id); + if (!chainId) { + setChainId(cosmos.chainId); + } + } catch (err) { + console.error(err); + } + }} + />
); }; diff --git a/apps/namadillo/src/App/Transfer/SelectProviderModal.tsx b/apps/namadillo/src/App/Transfer/SelectProviderModal.tsx deleted file mode 100644 index 88fcb4eb7..000000000 --- a/apps/namadillo/src/App/Transfer/SelectProviderModal.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { SelectModal } from "App/Common/SelectModal"; -import { Provider } from "types"; - -type SelectProviderModalProps = { - onClose: () => void; - providers: Provider[]; - onConnect: (provider: Provider) => void; -}; - -export const SelectProviderModal = ({ - onClose, - onConnect, - providers, -}: SelectProviderModalProps): JSX.Element => { - return ( - -
    - {providers.map((provider: Provider, index) => ( -
  • - -
  • - ))} -
-
- ); -}; diff --git a/apps/namadillo/src/App/Transfer/SelectWalletModal.tsx b/apps/namadillo/src/App/Transfer/SelectWalletModal.tsx new file mode 100644 index 000000000..164e3ea34 --- /dev/null +++ b/apps/namadillo/src/App/Transfer/SelectWalletModal.tsx @@ -0,0 +1,44 @@ +import { integrations } from "@namada/integrations"; +import { SelectModal } from "App/Common/SelectModal"; +import { WalletProvider } from "types"; +import { WalletCard } from "./WalletCard"; + +type SelectWalletModalProps = { + onClose: () => void; + wallets: WalletProvider[]; + onConnect: (wallet: WalletProvider) => void; +}; + +export const SelectWalletModal = ({ + onClose, + onConnect, + wallets, +}: SelectWalletModalProps): JSX.Element => { + const isConnected = (_wallet: WalletProvider): boolean => { + return false; + }; + + const isInstalled = (wallet: WalletProvider): boolean => { + if (wallet.id in integrations) { + return integrations[wallet.id].detect(); + } + return false; + }; + + return ( + +
    + {wallets.map((wallet: WalletProvider, index) => ( +
  • + onConnect(wallet)} + /> +
  • + ))} +
+
+ ); +}; diff --git a/apps/namadillo/src/App/Transfer/SelectedChain.tsx b/apps/namadillo/src/App/Transfer/SelectedChain.tsx index 55c6f1190..e003e3a43 100644 --- a/apps/namadillo/src/App/Transfer/SelectedChain.tsx +++ b/apps/namadillo/src/App/Transfer/SelectedChain.tsx @@ -1,24 +1,24 @@ import clsx from "clsx"; import { GoChevronDown } from "react-icons/go"; -import { Chain, Provider } from "types"; +import { Chain, WalletProvider } from "types"; import { EmptyResourceIcon } from "./EmptyResourceIcon"; type SelectedChainProps = { chain?: Chain; - provider?: Provider; + wallet?: WalletProvider; onClick?: () => void; }; export const SelectedChain = ({ chain, - provider, + wallet, onClick, }: SelectedChainProps): JSX.Element => { const selectorClassList = clsx( `flex items-center gap-2.5 text-white font-light cursor-pointer` ); - const isDisabled = !provider; + const isDisabled = !wallet; return ( + )} + {installed && connected && } + + + ); +}; diff --git a/apps/namadillo/src/App/Transfer/__mocks__/providers.ts b/apps/namadillo/src/App/Transfer/__mocks__/providers.ts index af2cd0157..32d34c5cd 100644 --- a/apps/namadillo/src/App/Transfer/__mocks__/providers.ts +++ b/apps/namadillo/src/App/Transfer/__mocks__/providers.ts @@ -1,12 +1,11 @@ -import { Provider } from "types"; +import { WalletProvider } from "types"; -export const providerMock: Provider = { +export const walletMock: WalletProvider = { + id: "keplr", name: "Keplr", iconUrl: "test.svg", - connected: false, -}; - -export const providerConnectedMock: Provider = { - ...providerMock, - connected: true, + downloadUrl: { + chrome: "https://google.com", + firefox: "https://mozilla.org", + }, }; diff --git a/apps/namadillo/src/App/Transfer/__tests__/SelectedChain.test.tsx b/apps/namadillo/src/App/Transfer/__tests__/SelectedChain.test.tsx index 9008be967..9e9e33b4f 100644 --- a/apps/namadillo/src/App/Transfer/__tests__/SelectedChain.test.tsx +++ b/apps/namadillo/src/App/Transfer/__tests__/SelectedChain.test.tsx @@ -2,7 +2,7 @@ import "@testing-library/jest-dom"; import { fireEvent, render, screen } from "@testing-library/react"; import { SelectedChain } from "App/Transfer/SelectedChain"; import { Chain } from "types"; -import { providerConnectedMock } from "../__mocks__/providers"; +import { walletMock } from "../__mocks__/providers"; describe("Component: SelectedChain", () => { const mockChain: Chain = { @@ -25,7 +25,7 @@ describe("Component: SelectedChain", () => { }); it("renders correctly with no chain selected", () => { - render(); + render(); const button = screen.getByRole("button"); expect(button).toBeInTheDocument(); expect(button).toBeEnabled(); @@ -33,9 +33,7 @@ describe("Component: SelectedChain", () => { }); it("renders correctly with chain selected", () => { - render( - - ); + render(); const button = screen.getByRole("button"); expect(button).toBeInTheDocument(); @@ -56,9 +54,7 @@ describe("Component: SelectedChain", () => { it("calls onClick when the component is clicked", () => { const handleClick = jest.fn(); - render( - - ); + render(); const button = screen.getByRole("button"); fireEvent.click(button); diff --git a/apps/namadillo/src/App/Transfer/__tests__/SelectedWallet.test.tsx b/apps/namadillo/src/App/Transfer/__tests__/SelectedWallet.test.tsx new file mode 100644 index 000000000..33ed1f800 --- /dev/null +++ b/apps/namadillo/src/App/Transfer/__tests__/SelectedWallet.test.tsx @@ -0,0 +1,82 @@ +import { walletMock } from "../__mocks__/providers"; +const testWalletAddress = "0x1234567890abcdefghijkl"; +const mockIntegration = { + detect: jest.fn(), + connect: jest.fn(), + accounts: jest.fn().mockResolvedValue([{ address: testWalletAddress }]), +}; + +// Avoid hoisting +(() => { + jest.mock("@namada/integrations", () => ({ + integrations: { + [walletMock.id]: mockIntegration, + }, + })); +})(); + +import { shortenAddress } from "@namada/utils"; +import { + act, + fireEvent, + render, + screen, + waitFor, +} from "@testing-library/react"; +import { SelectedWallet } from "App/Transfer/SelectedWallet"; + +describe("Component: SelectedWallet", () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + it("should render the wallet icon", async () => { + await act(async () => { + render(); + }); + const walletIcon = screen.getByAltText(/logo/i, { exact: false }); + expect(walletIcon).toBeInTheDocument(); + expect(walletIcon).toHaveAttribute("src", walletMock.iconUrl); + }); + + it("should display the shortened wallet address after loading accounts", async () => { + render(); + + // Wait for the address to be loaded + await waitFor(() => { + expect(mockIntegration.connect).toHaveBeenCalled(); + expect(mockIntegration.accounts).toHaveBeenCalled(); + }); + + // Check if the address is correctly shortened + const shortenedAddress = shortenAddress(testWalletAddress, 8, 6); + expect(screen.getByText(shortenedAddress)).toBeInTheDocument(); + }); + + it("should trigger the onClick function when clicked", async () => { + const onClickMock = jest.fn(); + await act(async () => { + render(); + }); + const walletButton = screen.getByRole("button"); + fireEvent.click(walletButton); + expect(onClickMock).toHaveBeenCalled(); + }); + + it("should handle missing wallet address gracefully", async () => { + //Mock integration to return no accounts + mockIntegration.accounts.mockResolvedValue([]); + + await act(async () => { + render(); + }); + + // Wait for the component to try loading accounts + await waitFor(() => { + expect(mockIntegration.accounts).toHaveBeenCalled(); + }); + + // Check that no address is displayed + expect(screen.queryByText(/0x/i)).toBeNull(); + }); +}); diff --git a/apps/namadillo/src/App/Transfer/__tests__/TransferDestination.test.tsx b/apps/namadillo/src/App/Transfer/__tests__/TransferDestination.test.tsx index fee5a7878..100a1b3c5 100644 --- a/apps/namadillo/src/App/Transfer/__tests__/TransferDestination.test.tsx +++ b/apps/namadillo/src/App/Transfer/__tests__/TransferDestination.test.tsx @@ -5,7 +5,7 @@ import { } from "App/Transfer/__mocks__/chains"; import { TransferDestination } from "App/Transfer/TransferDestination"; import BigNumber from "bignumber.js"; -import { providerMock } from "../__mocks__/providers"; +import { walletMock } from "../__mocks__/providers"; describe("TransferDestination", () => { it("should render the component with the default props", () => { @@ -46,7 +46,7 @@ describe("TransferDestination", () => { ); expect(screen.getByText(/namada shielded/i)).toBeInTheDocument(); @@ -57,7 +57,7 @@ describe("TransferDestination", () => { ); expect(screen.getByText(/namada transparent/i)).toBeInTheDocument(); diff --git a/apps/namadillo/src/App/Transfer/__tests__/TransferSource.test.tsx b/apps/namadillo/src/App/Transfer/__tests__/TransferSource.test.tsx index b21c3c2c0..90c12dee2 100644 --- a/apps/namadillo/src/App/Transfer/__tests__/TransferSource.test.tsx +++ b/apps/namadillo/src/App/Transfer/__tests__/TransferSource.test.tsx @@ -5,7 +5,7 @@ import { } from "App/Transfer/TransferSource"; import BigNumber from "bignumber.js"; import { namadaChainMock } from "../__mocks__/chains"; -import { providerConnectedMock } from "../__mocks__/providers"; +import { walletMock } from "../__mocks__/providers"; describe("Component: TransferSource", () => { it("should render the component with the default props", () => { @@ -45,7 +45,7 @@ describe("Component: TransferSource", () => { const openChainSelectorMock = jest.fn(); setup({ openChainSelector: openChainSelectorMock, - provider: providerConnectedMock, + wallet: walletMock, }); const chain = getEmptyChain(); fireEvent.click(chain); diff --git a/apps/namadillo/src/App/Transfer/__tests__/WalletCard.test.tsx b/apps/namadillo/src/App/Transfer/__tests__/WalletCard.test.tsx new file mode 100644 index 000000000..9f0cc6cda --- /dev/null +++ b/apps/namadillo/src/App/Transfer/__tests__/WalletCard.test.tsx @@ -0,0 +1,79 @@ +import { cleanup, fireEvent, render, screen } from "@testing-library/react"; +import { WalletCard } from "App/Transfer/WalletCard"; +import { walletMock } from "../__mocks__/providers"; + +describe("Component: WalletCard", () => { + it("should render wallet name and icon", () => { + render( + + ); + + expect(screen.getByText("Keplr")).toBeInTheDocument(); + expect(screen.getByRole("img")).toHaveAttribute("src", walletMock.iconUrl); + }); + + const mockUserAgent = (userAgent: string): void => { + const fn = jest.spyOn(navigator, "userAgent", "get"); + fn.mockReturnValue(userAgent); + }; + + it("should show 'Install' with correct link if wallet is not installed", () => { + const chromeUserAgent = `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36`; + const firefoxUserAgent = `Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:130.0) Gecko/20100101 Firefox/130.0`; + + // Render Chrome url + mockUserAgent(chromeUserAgent); + render( + + ); + const chromeLink = screen.getByText(/install/i); + expect(chromeLink).toBeInTheDocument(); + expect(chromeLink).toHaveAttribute("href", walletMock.downloadUrl.chrome); + + // Render firefox url + cleanup(); + jest.clearAllMocks(); + mockUserAgent(firefoxUserAgent); + render( + + ); + const firefoxLink = screen.getByText(/install/i); + expect(firefoxLink).toHaveAttribute("href", walletMock.downloadUrl.firefox); + }); + + it("should show 'Connect' button if wallet is installed but not connected", () => { + const onConnectMock = jest.fn(); + render( + + ); + + const connectButton = screen.getByText(/connect/i); + expect(connectButton).toBeInTheDocument(); + + fireEvent.click(connectButton); + expect(onConnectMock).toHaveBeenCalled(); + }); + + it("should show 'Select' button if wallet is installed and connected", () => { + const onSelectMock = jest.fn(); + render( + + ); + + const selectButton = screen.getByText(/select/i); + expect(selectButton).toBeInTheDocument(); + + fireEvent.click(selectButton); + expect(onSelectMock).toHaveBeenCalled(); + }); +}); diff --git a/apps/namadillo/src/atoms/integrations/atoms.ts b/apps/namadillo/src/atoms/integrations/atoms.ts new file mode 100644 index 000000000..32aa88691 --- /dev/null +++ b/apps/namadillo/src/atoms/integrations/atoms.ts @@ -0,0 +1,13 @@ +import { ExtensionKey } from "@namada/types"; +import { atomWithStorage } from "jotai/utils"; + +// Currently we're just integrating with Keplr, but in the future we might use different wallets +export const selectedIBCWallet = atomWithStorage( + "namadillo:ibc:wallet", + undefined +); + +export const selectedIBCChainAtom = atomWithStorage( + "namadillo:ibc:chainId", + undefined +); diff --git a/apps/namadillo/src/atoms/integrations/index.ts b/apps/namadillo/src/atoms/integrations/index.ts new file mode 100644 index 000000000..4e0d46d9a --- /dev/null +++ b/apps/namadillo/src/atoms/integrations/index.ts @@ -0,0 +1 @@ +export * from "./atoms"; diff --git a/apps/namadillo/src/hooks/useExtensionConnect.ts b/apps/namadillo/src/hooks/useExtensionConnect.ts index 237eb7712..1e5b7d781 100644 --- a/apps/namadillo/src/hooks/useExtensionConnect.ts +++ b/apps/namadillo/src/hooks/useExtensionConnect.ts @@ -1,5 +1,5 @@ import { useIntegrationConnection } from "@namada/integrations"; -import { ChainKey } from "@namada/types"; +import { ExtensionKey } from "@namada/types"; import { ConnectStatus, namadaExtensionConnectionStatus } from "atoms/settings"; import { useAtom } from "jotai"; import { useEffect } from "react"; @@ -11,7 +11,7 @@ type UseConnectOutput = { }; export const useExtensionConnect = ( - chainKey: ChainKey = "namada" + chainKey: ExtensionKey = "namada" ): UseConnectOutput => { const [connectionStatus, setConnectionStatus] = useAtom( namadaExtensionConnectionStatus diff --git a/apps/namadillo/src/integrations/assets/keplr.svg b/apps/namadillo/src/integrations/assets/keplr.svg new file mode 100644 index 000000000..e56c5257c --- /dev/null +++ b/apps/namadillo/src/integrations/assets/keplr.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/namadillo/src/integrations/index.ts b/apps/namadillo/src/integrations/index.ts new file mode 100644 index 000000000..c77d48cda --- /dev/null +++ b/apps/namadillo/src/integrations/index.ts @@ -0,0 +1,16 @@ +import { ExtensionKey } from "@namada/types"; +import { WalletProvider } from "types"; +import keplrSvg from "./assets/keplr.svg"; + +export const wallets: Partial> = { + keplr: { + id: "keplr", + name: "Keplr", + iconUrl: keplrSvg, + downloadUrl: { + chrome: + "https://chromewebstore.google.com/detail/keplr/dmkamcknogkgcdfhhbddcghachkejeap", + firefox: "https://addons.mozilla.org/en-US/firefox/addon/keplr/", + }, + }, +}; diff --git a/apps/namadillo/src/lib/query.ts b/apps/namadillo/src/lib/query.ts index a2cb524a8..b7b26cd93 100644 --- a/apps/namadillo/src/lib/query.ts +++ b/apps/namadillo/src/lib/query.ts @@ -2,6 +2,7 @@ import { getIntegration } from "@namada/integrations"; import { Account, AccountType, + ExtensionKey, Signer, TxMsgValue, TxProps, @@ -138,11 +139,11 @@ export const buildTx = async ( * Asynchronously signs an encoded batch transaction using Namada extension. */ export const signTx = async ( - chain: ChainSettings, + wallet: ExtensionKey, typedEncodedTx: EncodedTxData, owner: string ): Promise => { - const integration = getIntegration(chain.id); + const integration = getIntegration(wallet); const signingClient = integration.signer() as Signer; const store = getDefaultStore(); @@ -190,7 +191,7 @@ export const buildTxPair = async ( queryProps, txFn ); - const signedTxs = await signTx(chain, encodedTxData, owner); + const signedTxs = await signTx(chain.extensionId, encodedTxData, owner); return { signedTxs, encodedTxData, diff --git a/apps/namadillo/src/types.d.ts b/apps/namadillo/src/types.d.ts index 8f18d4a37..162fbbbae 100644 --- a/apps/namadillo/src/types.d.ts +++ b/apps/namadillo/src/types.d.ts @@ -167,10 +167,14 @@ export type ToastNotificationEntryFilter = ( notification: ToastNotification ) => boolean; -export type Provider = { +export type WalletProvider = { + id: ExtensionKey; name: string; iconUrl: string; - connected: boolean; + downloadUrl: { + chrome: string; + firefox: string; + }; }; export type Chain = { diff --git a/packages/integrations/src/hooks/useIntegration.ts b/packages/integrations/src/hooks/useIntegration.ts index d3c178e20..b23b56554 100644 --- a/packages/integrations/src/hooks/useIntegration.ts +++ b/packages/integrations/src/hooks/useIntegration.ts @@ -9,7 +9,7 @@ import { import { chains } from "@namada/chains"; import { useUntil } from "@namada/hooks"; import { Keplr, Metamask, Namada } from "@namada/integrations"; -import { ChainKey, ExtensionKey } from "@namada/types"; +import { ExtensionKey } from "@namada/types"; type ExtensionConnection = ( onSuccess: () => T, @@ -22,18 +22,14 @@ type IntegrationFromExtensionKey = : K extends "metamask" ? Metamask : never; -type IntegrationFromChainKey = IntegrationFromExtensionKey< - (typeof chains)[K]["extension"]["id"] ->; - type Integrations = { - [K in ChainKey]: IntegrationFromChainKey; + [K in ExtensionKey]: IntegrationFromExtensionKey; }; export const integrations: Integrations = { namada: new Namada(chains.namada), - cosmos: new Keplr(chains.cosmos), - ethereum: new Metamask(chains.ethereum), + keplr: new Keplr(chains.cosmos), + metamask: new Metamask(chains.ethereum), }; export const IntegrationsContext = createContext(integrations); @@ -44,9 +40,9 @@ export const IntegrationsContext = createContext(integrations); * @param {ChainIndex} chainKey - Index of chain integration * @returns {InstanceType} Integration API */ -export const useIntegration = ( +export const useIntegration = ( chainKey: K -): IntegrationFromChainKey => { +): IntegrationFromExtensionKey => { return useContext(IntegrationsContext)[chainKey]; }; @@ -55,18 +51,22 @@ export const useIntegration = ( * * @template TSuccess - Success return type. * @template TFail - Fail return type. - * @param {ChainKey} chainKey - Index of a chain integration + * @param {ExtensionKey} extensionKey - Index of a wallet integration * @returns {[InstanceType, boolean, ExtensionConnection]} * Tuple of integration, connection status and connection function. */ -export const useIntegrationConnection = ( - chainKey: K +export const useIntegrationConnection = < + TSuccess, + TFail, + K extends ExtensionKey, +>( + extensionKey: K ): [ - IntegrationFromChainKey, + IntegrationFromExtensionKey, boolean, ExtensionConnection, ] => { - const integration = useIntegration(chainKey); + const integration = useIntegration(extensionKey); const [isConnectingToExtension, setIsConnectingToExtension] = useState(false); const connect: ExtensionConnection = useCallback( @@ -84,7 +84,7 @@ export const useIntegrationConnection = ( } setIsConnectingToExtension(false); }, - [chainKey] + [extensionKey] ); return [integration, isConnectingToExtension, connect]; @@ -97,10 +97,9 @@ type AttachStatusMap = { [key in ExtensionKey]: AttachStatus }; * Hook used for returning attach status of extension */ export const useUntilIntegrationAttached = ( - chainId: ChainKey = "namada", extensionId: ExtensionKey = "namada" ): AttachStatus => { - const integration = useIntegration(chainId); + const integration = useIntegration(extensionId); const [attachStatusMap, setAttachStatus] = useState({ namada: "pending", keplr: "pending", @@ -109,7 +108,7 @@ export const useUntilIntegrationAttached = ( useEffect(() => { setAttachStatus((v) => ({ ...v, [extensionId]: "pending" })); - }, [chainId]); + }, [extensionId]); useUntil( { @@ -142,11 +141,11 @@ export const getIntegrations = (): Integrations => { /** * Returns integration by chainId. To be used outside react components. * - * @param {Chainkey} chainKey - Key of the chain + * @param {ExtensionKey} extensionKey - Key of the wallet * @returns {InstanceType} Integration API */ -export const getIntegration = ( - chainKey: K -): IntegrationFromChainKey => { - return integrations[chainKey]; +export const getIntegration = ( + extensionKey: K +): IntegrationFromExtensionKey => { + return integrations[extensionKey]; };