From ce276fd4bf5aa498766c4e289a63d1beebfb1190 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 16 Oct 2023 12:55:20 +0200 Subject: [PATCH 1/9] wip: walletprovider type narrowing --- src/context/WalletProvider/Coinbase/config.ts | 5 +- .../WalletProvider/DemoWallet/config.ts | 5 +- .../KeepKey/components/Connect.tsx | 4 +- src/context/WalletProvider/KeepKey/config.ts | 9 +- src/context/WalletProvider/Keplr/config.ts | 5 +- src/context/WalletProvider/Ledger/config.ts | 5 +- src/context/WalletProvider/MetaMask/config.ts | 10 ++- .../MobileWallet/components/MobileLoad.tsx | 7 +- .../WalletProvider/MobileWallet/config.ts | 5 +- .../NativeWallet/components/NativeLoad.tsx | 4 +- .../WalletProvider/NativeWallet/config.ts | 5 +- .../WalletProvider/WalletConnectV2/config.ts | 5 +- src/context/WalletProvider/WalletContext.tsx | 3 +- src/context/WalletProvider/WalletProvider.tsx | 83 +++++++++++-------- src/context/WalletProvider/XDEFI/config.ts | 5 +- src/context/WalletProvider/actions.ts | 5 +- src/context/WalletProvider/config.ts | 37 ++++++++- src/context/WalletProvider/types.ts | 30 +++++++ 18 files changed, 173 insertions(+), 59 deletions(-) create mode 100644 src/context/WalletProvider/types.ts diff --git a/src/context/WalletProvider/Coinbase/config.ts b/src/context/WalletProvider/Coinbase/config.ts index 3bd4c962415..e15368c503b 100644 --- a/src/context/WalletProvider/Coinbase/config.ts +++ b/src/context/WalletProvider/Coinbase/config.ts @@ -1,7 +1,10 @@ +import type { CoinbaseAdapter } from '@shapeshiftoss/hdwallet-coinbase' import { CoinbaseIcon } from 'components/Icons/CoinbaseIcon' import type { SupportedWalletInfo } from 'context/WalletProvider/config' -export const CoinbaseConfig: Omit = { +type CoinbaseConfigType = Omit, 'routes'> + +export const CoinbaseConfig: CoinbaseConfigType = { adapters: [ { loadAdapter: () => import('@shapeshiftoss/hdwallet-coinbase').then(m => m.CoinbaseAdapter), diff --git a/src/context/WalletProvider/DemoWallet/config.ts b/src/context/WalletProvider/DemoWallet/config.ts index 7b4d55aa3c5..9b29cd29f51 100644 --- a/src/context/WalletProvider/DemoWallet/config.ts +++ b/src/context/WalletProvider/DemoWallet/config.ts @@ -1,7 +1,10 @@ +import type { NativeAdapter } from '@shapeshiftoss/hdwallet-native' import { FoxIcon } from 'components/Icons/FoxIcon' import type { SupportedWalletInfo } from 'context/WalletProvider/config' -export const DemoConfig: Omit = { +type DemoConfigType = Omit, 'routes'> + +export const DemoConfig: DemoConfigType = { adapters: [ { loadAdapter: () => import('@shapeshiftoss/hdwallet-native').then(m => m.NativeAdapter), diff --git a/src/context/WalletProvider/KeepKey/components/Connect.tsx b/src/context/WalletProvider/KeepKey/components/Connect.tsx index 7c00aa36c34..4313d1f2bc1 100644 --- a/src/context/WalletProvider/KeepKey/components/Connect.tsx +++ b/src/context/WalletProvider/KeepKey/components/Connect.tsx @@ -57,6 +57,7 @@ export const KeepKeyConnect = () => { const wallet = await (async () => { try { const sdk = await setupKeepKeySDK() + // @ts-ignore TODO(gomes): FIXME, most likely borked because of WebUSBKeepKeyAdapter const wallet = await firstAdapter.pairDevice(sdk) if (!wallet) { setErrorLoading('walletProvider.errors.walletNotFound') @@ -65,7 +66,8 @@ export const KeepKeyConnect = () => { return wallet } catch (e) { const secondAdapter = await getAdapter(KeyManager.KeepKey, 1) - const wallet = await secondAdapter?.pairDevice().catch((err: Error) => { + // @ts-ignore TODO(gomes): FIXME, most likely borked because of WebUSBKeepKeyAdapter + const wallet = await secondAdapter?.pairDevice().catch(err => { if (err.name === 'ConflictingApp') { setErrorLoading('walletProvider.keepKey.connect.conflictingApp') return diff --git a/src/context/WalletProvider/KeepKey/config.ts b/src/context/WalletProvider/KeepKey/config.ts index 15c46e95f91..bba4e42846c 100644 --- a/src/context/WalletProvider/KeepKey/config.ts +++ b/src/context/WalletProvider/KeepKey/config.ts @@ -1,7 +1,14 @@ +import type { KkRestAdapter } from '@keepkey/hdwallet-keepkey-rest' +import type { WebUSBKeepKeyAdapter } from '@shapeshiftoss/hdwallet-keepkey-webusb' import { KeepKeyIcon } from 'components/Icons/KeepKeyIcon' import type { SupportedWalletInfo } from 'context/WalletProvider/config' -export const KeepKeyConfig: Omit = { +type KeepKeyConfigType = Omit< + SupportedWalletInfo, + 'routes' +> + +export const KeepKeyConfig: KeepKeyConfigType = { adapters: [ { loadAdapter: () => import('@keepkey/hdwallet-keepkey-rest').then(m => m.KkRestAdapter), diff --git a/src/context/WalletProvider/Keplr/config.ts b/src/context/WalletProvider/Keplr/config.ts index af5b0bf502c..15910552d1f 100644 --- a/src/context/WalletProvider/Keplr/config.ts +++ b/src/context/WalletProvider/Keplr/config.ts @@ -1,7 +1,10 @@ +import type { KeplrAdapter } from '@shapeshiftoss/hdwallet-keplr' import { KeplrIcon } from 'components/Icons/KeplrIcon' import type { SupportedWalletInfo } from 'context/WalletProvider/config' -export const KeplrConfig: Omit = { +type KeplrConfigType = Omit, 'routes'> + +export const KeplrConfig: KeplrConfigType = { adapters: [ { loadAdapter: () => import('@shapeshiftoss/hdwallet-keplr').then(m => m.KeplrAdapter), diff --git a/src/context/WalletProvider/Ledger/config.ts b/src/context/WalletProvider/Ledger/config.ts index 790986e6990..09191864ea6 100644 --- a/src/context/WalletProvider/Ledger/config.ts +++ b/src/context/WalletProvider/Ledger/config.ts @@ -1,7 +1,10 @@ +import type { WebUSBLedgerAdapter } from '@shapeshiftoss/hdwallet-ledger-webusb' import { LedgerIcon } from 'components/Icons/LedgerIcon' import type { SupportedWalletInfo } from 'context/WalletProvider/config' -export const LedgerConfig: Omit = { +type LedgerConfigType = Omit, 'routes'> + +export const LedgerConfig: LedgerConfigType = { adapters: [ { loadAdapter: () => diff --git a/src/context/WalletProvider/MetaMask/config.ts b/src/context/WalletProvider/MetaMask/config.ts index 0b078f552c5..baf4636bd80 100644 --- a/src/context/WalletProvider/MetaMask/config.ts +++ b/src/context/WalletProvider/MetaMask/config.ts @@ -1,11 +1,19 @@ +import type { MetaMaskAdapter } from '@shapeshiftoss/hdwallet-metamask' +import type { MetaMaskAdapter as MetaMaskMultiChainAdapter } from '@shapeshiftoss/hdwallet-shapeshift-multichain' import { getConfig } from 'config' import { MetaMaskIcon } from 'components/Icons/MetaMaskIcon' import type { SupportedWalletInfo } from 'context/WalletProvider/config' -export const MetaMaskConfig: Omit = { +type MetaMaskConfigType = Omit< + SupportedWalletInfo, + 'routes' +> + +export const MetaMaskConfig: MetaMaskConfigType = { adapters: [ { loadAdapter: () => + // @ts-ignore TODO(gomes): FIXME getConfig().REACT_APP_EXPERIMENTAL_MM_SNAPPY_FINGERS ? import('@shapeshiftoss/hdwallet-shapeshift-multichain').then(m => m.MetaMaskAdapter) : import('@shapeshiftoss/hdwallet-metamask').then(m => m.MetaMaskAdapter), diff --git a/src/context/WalletProvider/MobileWallet/components/MobileLoad.tsx b/src/context/WalletProvider/MobileWallet/components/MobileLoad.tsx index 56e45c84006..f224b22d534 100644 --- a/src/context/WalletProvider/MobileWallet/components/MobileLoad.tsx +++ b/src/context/WalletProvider/MobileWallet/components/MobileLoad.tsx @@ -62,11 +62,12 @@ export const MobileLoad = ({ history }: RouteComponentProps) => { try { const revoker = await getWallet(deviceId) if (!revoker?.mnemonic) throw new Error(`Mobile wallet not found: ${deviceId}`) + if (!revoker?.id) throw new Error(`Revoker ID not found: ${deviceId}`) const wallet = await adapter.pairDevice(revoker.id) - await wallet.loadDevice({ mnemonic: revoker.mnemonic }) - if (!(await wallet.isInitialized())) { - await wallet.initialize() + await wallet?.loadDevice({ mnemonic: revoker.mnemonic }) + if (!(await wallet?.isInitialized())) { + await wallet?.initialize() } dispatch({ type: WalletActions.SET_WALLET, diff --git a/src/context/WalletProvider/MobileWallet/config.ts b/src/context/WalletProvider/MobileWallet/config.ts index dc79935ee61..42ef0fd351d 100644 --- a/src/context/WalletProvider/MobileWallet/config.ts +++ b/src/context/WalletProvider/MobileWallet/config.ts @@ -1,7 +1,10 @@ +import type { NativeAdapter } from '@shapeshiftoss/hdwallet-native' import { FoxIcon } from 'components/Icons/FoxIcon' import type { SupportedWalletInfo } from 'context/WalletProvider/config' -export const MobileConfig: Omit = { +type MobileConfigType = Omit, 'routes'> + +export const MobileConfig: MobileConfigType = { adapters: [ { loadAdapter: () => import('@shapeshiftoss/hdwallet-native').then(m => m.NativeAdapter), diff --git a/src/context/WalletProvider/NativeWallet/components/NativeLoad.tsx b/src/context/WalletProvider/NativeWallet/components/NativeLoad.tsx index 5ed1693ee12..0e8edbf8a91 100644 --- a/src/context/WalletProvider/NativeWallet/components/NativeLoad.tsx +++ b/src/context/WalletProvider/NativeWallet/components/NativeLoad.tsx @@ -75,11 +75,11 @@ export const NativeLoad = ({ history }: RouteComponentProps) => { const { name, icon } = NativeConfig try { const wallet = await adapter.pairDevice(deviceId) - if (!(await wallet.isInitialized())) { + if (!(await wallet?.isInitialized())) { // This will trigger the password modal and the modal will set the wallet on state // after the wallet has been decrypted. If we set it now, `getPublicKeys` calls will // return null, and we don't have a retry mechanism - await wallet.initialize() + await wallet?.initialize() } else { dispatch({ type: WalletActions.SET_WALLET, diff --git a/src/context/WalletProvider/NativeWallet/config.ts b/src/context/WalletProvider/NativeWallet/config.ts index 52c1f9a44c9..8d588ebb8ca 100644 --- a/src/context/WalletProvider/NativeWallet/config.ts +++ b/src/context/WalletProvider/NativeWallet/config.ts @@ -1,7 +1,10 @@ +import type { NativeAdapter } from '@shapeshiftoss/hdwallet-native' import { FoxIcon } from 'components/Icons/FoxIcon' // Ensure the import path is correct import type { SupportedWalletInfo } from 'context/WalletProvider/config' -export const NativeConfig: Omit = { +type NativeConfigType = Omit, 'routes'> + +export const NativeConfig: NativeConfigType = { adapters: [ { loadAdapter: () => import('@shapeshiftoss/hdwallet-native').then(m => m.NativeAdapter), diff --git a/src/context/WalletProvider/WalletConnectV2/config.ts b/src/context/WalletProvider/WalletConnectV2/config.ts index 9b86d655567..d2d7cb6a677 100644 --- a/src/context/WalletProvider/WalletConnectV2/config.ts +++ b/src/context/WalletProvider/WalletConnectV2/config.ts @@ -1,4 +1,5 @@ import { CHAIN_REFERENCE } from '@shapeshiftoss/caip' +import type { WalletConnectV2Adapter } from '@shapeshiftoss/hdwallet-walletconnectv2' import { getConfig } from 'config' import type { Chain } from 'viem/chains' import { arbitrum, avalanche, bsc, gnosis, mainnet, optimism, polygon } from 'viem/chains' @@ -7,7 +8,9 @@ import type { SupportedWalletInfo } from 'context/WalletProvider/config' import type { EthereumProviderOptions } from './constants' -export const WalletConnectV2Config: Omit = { +type WalletConnectV2ConfigType = Omit, 'routes'> + +export const WalletConnectV2Config: WalletConnectV2ConfigType = { adapters: [ { loadAdapter: () => diff --git a/src/context/WalletProvider/WalletContext.tsx b/src/context/WalletProvider/WalletContext.tsx index 4002eeb79ce..c4e9cbf23a3 100644 --- a/src/context/WalletProvider/WalletContext.tsx +++ b/src/context/WalletProvider/WalletContext.tsx @@ -3,11 +3,12 @@ import { createContext } from 'react' import type { ActionTypes } from './actions' import type { KeyManager } from './KeyManager' +import type { GetAdapter } from './types' import type { DeviceState, InitialState, KeyManagerWithProvider } from './WalletProvider' export interface IWalletContext { state: InitialState - getAdapter: (keyManager: KeyManager, index?: number) => Promise + getAdapter: GetAdapter dispatch: React.Dispatch connect: (adapter: KeyManager) => void create: (adapter: KeyManager) => void diff --git a/src/context/WalletProvider/WalletProvider.tsx b/src/context/WalletProvider/WalletProvider.tsx index 33ca1a35b38..7084abeffdd 100644 --- a/src/context/WalletProvider/WalletProvider.tsx +++ b/src/context/WalletProvider/WalletProvider.tsx @@ -40,17 +40,11 @@ import { setLocalWalletTypeAndDeviceId, } from './local-wallet' import { useNativeEventHandler } from './NativeWallet/hooks/useNativeEventHandler' +import type { AdaptersByKeyManager, GetAdapter } from './types' import type { IWalletContext } from './WalletContext' import { WalletContext } from './WalletContext' import { WalletViewsRouter } from './WalletViewsRouter' -type GenericAdapter = { - initialize: (...args: any[]) => Promise - pairDevice: (...args: any[]) => Promise -} - -export type Adapters = Map - export type WalletInfo = { name: string icon: ComponentWithAs<'svg', IconProps> @@ -95,7 +89,7 @@ export type KeyManagerWithProvider = export interface InitialState { keyring: Keyring - adapters: Adapters | null + adapters: AdaptersByKeyManager | null wallet: HDWallet | null modalType: KeyManager | null connectedType: KeyManager | null @@ -359,28 +353,27 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX // Internal state, for memoization purposes only const [walletType, setWalletType] = useState(null) - const getAdapter = useCallback( - async (keyManager: KeyManager, index: number = 0) => { - let currentStateAdapters = state.adapters ?? new Map() + const getAdapter: GetAdapter = useCallback( + async (keyManager, index: number = 0) => { + let currentStateAdapters = state.adapters ?? ({} as AdaptersByKeyManager) // Check if adapter is already in the state - let adapterInstance = currentStateAdapters.get(keyManager)?.[index] - const currentKeyManagerAdapters = currentStateAdapters.get(keyManager) ?? [] + let adapterInstance = currentStateAdapters[keyManager]?.[index] + const currentKeyManagerAdapters = currentStateAdapters[keyManager] ?? [] if (!adapterInstance) { // If not, create a new instance of the adapter try { const Adapter = await SUPPORTED_WALLETS[keyManager].adapters[index].loadAdapter() + const keyManagerOptions = getKeyManagerOptions(keyManager, isDarkMode) + // @ts-ignore tsc is drunk as well, not narrowing to the specific adapter and its KeyManager options here // eslint is drunk, this isn't a hook // eslint-disable-next-line react-hooks/rules-of-hooks - adapterInstance = Adapter.useKeyring( - state.keyring, - getKeyManagerOptions(keyManager, isDarkMode), - ) + adapterInstance = Adapter.useKeyring(state.keyring, keyManagerOptions) if (adapterInstance) { currentKeyManagerAdapters[index] = adapterInstance - currentStateAdapters.set(keyManager, currentKeyManagerAdapters) + currentStateAdapters[keyManager] = currentKeyManagerAdapters // Set it in wallet state for later use dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentStateAdapters }) } @@ -410,12 +403,13 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX const localWalletDeviceId = getLocalWalletDeviceId() if (localWalletType && localWalletDeviceId) { ;(async () => { - const currentAdapters = state.adapters ?? new Map() - const adapter = await getAdapter(localWalletType) + const currentAdapters = state.adapters ?? ({} as AdaptersByKeyManager) + const _adapter = await getAdapter(localWalletType) - if (adapter) { + if (_adapter) { try { - currentAdapters.set(localWalletType, [adapter]) + // @ts-ignore TODO(gomes): FIXME, most likely borked because of WebUSBKeepKeyAdapter + currentAdapters[localWalletType] = [_adapter] dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) } catch (e) { console.error(e) @@ -426,9 +420,11 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX switch (localWalletType) { case KeyManager.Mobile: try { + // Get the adapter again in each switch case to narrow down the adapter type + const mobileAdapter = await getAdapter(localWalletType) const w = await getWallet(localWalletDeviceId) if (w && w.mnemonic && w.label) { - const localMobileWallet = await adapter.pairDevice(localWalletDeviceId) + const localMobileWallet = await mobileAdapter?.pairDevice(localWalletDeviceId) if (localMobileWallet) { localMobileWallet.loadDevice({ label: w.label, mnemonic: w.mnemonic }) @@ -460,7 +456,9 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX } break case KeyManager.Native: - const localNativeWallet = await adapter.pairDevice(localWalletDeviceId) + // Get the adapter again in each switch case to narrow down the adapter type + const nativeAdapter = await getAdapter(localWalletType) + const localNativeWallet = await nativeAdapter?.pairDevice(localWalletDeviceId) if (localNativeWallet) { /** * This will eventually fire an event, which the ShapeShift wallet @@ -481,10 +479,11 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX const localKeepKeyWallet = await (async () => { const maybeWallet = state.keyring.get(localWalletDeviceId) if (maybeWallet) return maybeWallet - const keepKeyAdapters = state.adapters?.get(KeyManager.KeepKey) - if (!keepKeyAdapters) return + const keepKeyAdapter = await getAdapter(KeyManager.KeepKey) + if (!keepKeyAdapter) return const sdk = await setupKeepKeySDK() - return await keepKeyAdapters[0]?.pairDevice(sdk) + // @ts-ignore TODO(gomes): FIXME, most likely borked because of WebUSBKeepKeyAdapter + return await keepKeyAdapter.pairDevice(sdk) })() /** @@ -522,7 +521,9 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) break case KeyManager.MetaMask: - const localMetaMaskWallet = await adapter?.pairDevice() + // Get the adapter again in each switch case to narrow down the adapter type + const metamaskAdapter = await getAdapter(localWalletType) + const localMetaMaskWallet = await metamaskAdapter?.pairDevice() if (localMetaMaskWallet) { const { name, icon } = SUPPORTED_WALLETS[KeyManager.MetaMask] try { @@ -549,7 +550,9 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) break case KeyManager.Coinbase: - const localCoinbaseWallet = await adapter?.pairDevice() + // Get the adapter again in each switch case to narrow down the adapter type + const coinbaseAdapter = await getAdapter(localWalletType) + const localCoinbaseWallet = await coinbaseAdapter?.pairDevice() if (localCoinbaseWallet) { const { name, icon } = SUPPORTED_WALLETS[KeyManager.Coinbase] try { @@ -576,7 +579,9 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) break case KeyManager.XDefi: - const localXDEFIWallet = await adapter?.pairDevice() + // Get the adapter again in each switch case to narrow down the adapter type + const xdefiAdapter = await getAdapter(localWalletType) + const localXDEFIWallet = await xdefiAdapter?.pairDevice() if (localXDEFIWallet) { const { name, icon } = SUPPORTED_WALLETS[KeyManager.XDefi] try { @@ -602,7 +607,9 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) break case KeyManager.Keplr: - const localKeplrWallet = await adapter?.pairDevice() + // Get the adapter again in each switch case to narrow down the adapter type + const keplrAdapter = await getAdapter(localWalletType) + const localKeplrWallet = await keplrAdapter?.pairDevice() if (localKeplrWallet) { const { name, icon } = SUPPORTED_WALLETS[KeyManager.Keplr] try { @@ -628,9 +635,11 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) break case KeyManager.WalletConnectV2: { + // Get the adapter again in each switch case to narrow down the adapter type + const walletConnectV2Adapter = await getAdapter(localWalletType) // Re-trigger the modal on refresh await onProviderChange(KeyManager.WalletConnectV2) - const localWalletConnectWallet = await adapter?.pairDevice() + const localWalletConnectWallet = await walletConnectV2Adapter?.pairDevice() if (localWalletConnectWallet) { const { name, icon } = SUPPORTED_WALLETS[KeyManager.WalletConnectV2] try { @@ -674,7 +683,8 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX const handleAccountsOrChainChanged = useCallback(async () => { if (!walletType || !state.adapters) return - const localWallet = await state.adapters.get(walletType)?.[0]?.pairDevice() + const adapter = await getAdapter(walletType) + const localWallet = await adapter?.pairDevice() if (!localWallet) return @@ -695,7 +705,7 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX connectedType: walletType, }, }) - }, [state, walletType]) + }, [getAdapter, state.adapters, walletType]) const setProviderEvents = useCallback( async (maybeProvider: InitialState['provider']) => { @@ -704,7 +714,8 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX maybeProvider?.on?.('accountsChanged', handleAccountsOrChainChanged) maybeProvider?.on?.('chainChanged', handleAccountsOrChainChanged) - const wallet = await state.adapters?.get(walletType)?.[0]?.pairDevice() + const adapter = await getAdapter(walletType) + const wallet = await adapter?.pairDevice() if (wallet) { const oldDisconnect = wallet.disconnect.bind(wallet) wallet.disconnect = () => { @@ -714,7 +725,7 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX } } }, - [state.adapters, walletType, handleAccountsOrChainChanged], + [walletType, handleAccountsOrChainChanged, getAdapter], ) // Register a MetaMask-like (EIP-1193) provider on wallet connect or load diff --git a/src/context/WalletProvider/XDEFI/config.ts b/src/context/WalletProvider/XDEFI/config.ts index 5a25bc9765d..82a2710f25e 100644 --- a/src/context/WalletProvider/XDEFI/config.ts +++ b/src/context/WalletProvider/XDEFI/config.ts @@ -1,7 +1,10 @@ +import type { XDEFIAdapter } from '@shapeshiftoss/hdwallet-xdefi' import { XDEFIIcon } from 'components/Icons/XDEFIIcon' import type { SupportedWalletInfo } from 'context/WalletProvider/config' -export const XDEFIConfig: Omit = { +type XDEFIConfigType = Omit, 'routes'> + +export const XDEFIConfig: XDEFIConfigType = { adapters: [ { loadAdapter: () => import('@shapeshiftoss/hdwallet-xdefi').then(m => m.XDEFIAdapter), diff --git a/src/context/WalletProvider/actions.ts b/src/context/WalletProvider/actions.ts index 2d44f456643..bb4304ef550 100644 --- a/src/context/WalletProvider/actions.ts +++ b/src/context/WalletProvider/actions.ts @@ -2,7 +2,8 @@ import type { HDWallet } from '@shapeshiftoss/hdwallet-core' import type { PinMatrixRequestType } from './KeepKey/KeepKeyTypes' import type { KeyManager } from './KeyManager' -import type { Adapters, DeviceState, InitialState, WalletInfo } from './WalletProvider' +import type { AdaptersByKeyManager } from './types' +import type { DeviceState, InitialState, WalletInfo } from './WalletProvider' export enum WalletActions { SET_ADAPTERS = 'SET_ADAPTERS', @@ -30,7 +31,7 @@ export enum WalletActions { } export type ActionTypes = - | { type: WalletActions.SET_ADAPTERS; payload: Adapters } + | { type: WalletActions.SET_ADAPTERS; payload: AdaptersByKeyManager } | { type: WalletActions.SET_WALLET payload: WalletInfo & { diff --git a/src/context/WalletProvider/config.ts b/src/context/WalletProvider/config.ts index d19b10ecbd4..076cffdaace 100644 --- a/src/context/WalletProvider/config.ts +++ b/src/context/WalletProvider/config.ts @@ -1,4 +1,14 @@ import type { ComponentWithAs, IconProps } from '@chakra-ui/react' +import type { KkRestAdapter } from '@keepkey/hdwallet-keepkey-rest' +import type { CoinbaseAdapter } from '@shapeshiftoss/hdwallet-coinbase' +import type { WebUSBKeepKeyAdapter } from '@shapeshiftoss/hdwallet-keepkey-webusb' +import type { KeplrAdapter } from '@shapeshiftoss/hdwallet-keplr' +import type { WebUSBLedgerAdapter as LedgerAdapter } from '@shapeshiftoss/hdwallet-ledger-webusb' +import type { MetaMaskAdapter } from '@shapeshiftoss/hdwallet-metamask' +import type { NativeAdapter } from '@shapeshiftoss/hdwallet-native' +import type { MetaMaskAdapter as MetaMaskMultiChainAdapter } from '@shapeshiftoss/hdwallet-shapeshift-multichain' +import type { WalletConnectV2Adapter } from '@shapeshiftoss/hdwallet-walletconnectv2' +import type { XDEFIAdapter } from '@shapeshiftoss/hdwallet-xdefi' import { getConfig } from 'config' import type { RouteProps } from 'react-router-dom' import { WalletConnectedRoutes } from 'components/Layout/Header/NavBar/hooks/useMenuRoutes' @@ -75,10 +85,9 @@ import { XDEFIConnect } from './XDEFI/components/Connect' import { XDEFIFailure } from './XDEFI/components/Failure' import { XDEFIConfig } from './XDEFI/config' -export interface SupportedWalletInfo { +export type SupportedWalletInfo = { adapters: { - // TODO(gomes): can we type this? - loadAdapter: () => Promise + loadAdapter: () => Promise }[] supportsMobile?: 'browser' | 'app' | 'both' icon: ComponentWithAs<'svg', IconProps> @@ -89,7 +98,26 @@ export interface SupportedWalletInfo { connectedWalletMenuInitialPath?: WalletConnectedRoutes connectedMenuComponent?: React.ComponentType } -export const SUPPORTED_WALLETS: Record = { + +export type SupportedWalletInfoByKeyManager = { + [KeyManager.Coinbase]: SupportedWalletInfo + // Native, Mobile, and Demo wallets are all native wallets + [KeyManager.Native]: SupportedWalletInfo + [KeyManager.Mobile]: SupportedWalletInfo + [KeyManager.Demo]: SupportedWalletInfo + // TODO(gomes): export WebUSBKeepKeyAdapter as a type in hdwallet, not a declare const + // this effectively means we keep on importing the akschual package for now + [KeyManager.KeepKey]: SupportedWalletInfo + [KeyManager.Keplr]: SupportedWalletInfo + [KeyManager.Ledger]: SupportedWalletInfo + [KeyManager.MetaMask]: SupportedWalletInfo< + typeof MetaMaskAdapter | typeof MetaMaskMultiChainAdapter + > + [KeyManager.WalletConnectV2]: SupportedWalletInfo + [KeyManager.XDefi]: SupportedWalletInfo +} + +export const SUPPORTED_WALLETS: SupportedWalletInfoByKeyManager = { [KeyManager.Mobile]: { ...MobileConfig, routes: [ @@ -150,6 +178,7 @@ export const SUPPORTED_WALLETS: Record = { ], connectedWalletMenuInitialPath: WalletConnectedRoutes.KeepKey, }, + // @ts-ignore TODO(gomes): FIXME [KeyManager.MetaMask]: { ...MetaMaskConfig, routes: [ diff --git a/src/context/WalletProvider/types.ts b/src/context/WalletProvider/types.ts new file mode 100644 index 00000000000..653a82642cf --- /dev/null +++ b/src/context/WalletProvider/types.ts @@ -0,0 +1,30 @@ +import type { KkRestAdapter } from '@keepkey/hdwallet-keepkey-rest' +import type { CoinbaseAdapter } from '@shapeshiftoss/hdwallet-coinbase' +import type { WebUSBKeepKeyAdapter } from '@shapeshiftoss/hdwallet-keepkey-webusb' +import type { KeplrAdapter } from '@shapeshiftoss/hdwallet-keplr' +import type { WebUSBLedgerAdapter } from '@shapeshiftoss/hdwallet-ledger-webusb' +import type { MetaMaskAdapter } from '@shapeshiftoss/hdwallet-metamask' +import type { NativeAdapter } from '@shapeshiftoss/hdwallet-native' +import type { MetaMaskAdapter as MetaMaskMultiChainAdapter } from '@shapeshiftoss/hdwallet-shapeshift-multichain' +import type { WalletConnectV2Adapter } from '@shapeshiftoss/hdwallet-walletconnectv2' +import type { XDEFIAdapter } from '@shapeshiftoss/hdwallet-xdefi' + +import type { KeyManager } from './KeyManager' + +export type AdaptersByKeyManager = { + [KeyManager.Mobile]: [NativeAdapter] + [KeyManager.Native]: [NativeAdapter] + [KeyManager.Demo]: [NativeAdapter] + [KeyManager.KeepKey]: [KkRestAdapter | typeof WebUSBKeepKeyAdapter] + [KeyManager.Ledger]: [WebUSBLedgerAdapter] + [KeyManager.Keplr]: [KeplrAdapter] + [KeyManager.WalletConnectV2]: [WalletConnectV2Adapter] + [KeyManager.MetaMask]: [MetaMaskAdapter | MetaMaskMultiChainAdapter] + [KeyManager.Coinbase]: [CoinbaseAdapter] + [KeyManager.XDefi]: [XDEFIAdapter] +} + +export type GetAdapter = ( + keyManager: K, + index?: number, +) => Promise From c654e321658f8fcf385e8787cd428af00fb758ed Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 16 Oct 2023 15:48:36 +0200 Subject: [PATCH 2/9] feat: cast KKRestAdapter type --- src/context/WalletProvider/KeepKey/components/Connect.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/context/WalletProvider/KeepKey/components/Connect.tsx b/src/context/WalletProvider/KeepKey/components/Connect.tsx index 4313d1f2bc1..3f00b8090b6 100644 --- a/src/context/WalletProvider/KeepKey/components/Connect.tsx +++ b/src/context/WalletProvider/KeepKey/components/Connect.tsx @@ -6,6 +6,7 @@ import { ModalBody, ModalHeader, } from '@chakra-ui/react' +import type { KkRestAdapter } from '@keepkey/hdwallet-keepkey-rest' import type { Event } from '@shapeshiftoss/hdwallet-core' import { useCallback, useState } from 'react' import { CircularProgress } from 'components/CircularProgress/CircularProgress' @@ -52,12 +53,12 @@ export const KeepKeyConnect = () => { setError(null) setLoading(true) - const firstAdapter = await getAdapter(KeyManager.KeepKey) + const firstAdapter = (await getAdapter(KeyManager.KeepKey)) as KkRestAdapter | null if (firstAdapter) { const wallet = await (async () => { try { const sdk = await setupKeepKeySDK() - // @ts-ignore TODO(gomes): FIXME, most likely borked because of WebUSBKeepKeyAdapter + if (!sdk) throw new Error('Failed to setup KeepKey SDK') const wallet = await firstAdapter.pairDevice(sdk) if (!wallet) { setErrorLoading('walletProvider.errors.walletNotFound') From 37d33a546d4bfdc81ad9339dbf6161c7b796756b Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 16 Oct 2023 15:59:40 +0200 Subject: [PATCH 3/9] feat: cast multichain adapter as MetaMaskAdapter --- src/context/WalletProvider/MetaMask/config.ts | 11 ++++------- src/context/WalletProvider/types.ts | 3 +-- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/context/WalletProvider/MetaMask/config.ts b/src/context/WalletProvider/MetaMask/config.ts index baf4636bd80..fa183c97024 100644 --- a/src/context/WalletProvider/MetaMask/config.ts +++ b/src/context/WalletProvider/MetaMask/config.ts @@ -1,21 +1,18 @@ import type { MetaMaskAdapter } from '@shapeshiftoss/hdwallet-metamask' -import type { MetaMaskAdapter as MetaMaskMultiChainAdapter } from '@shapeshiftoss/hdwallet-shapeshift-multichain' import { getConfig } from 'config' import { MetaMaskIcon } from 'components/Icons/MetaMaskIcon' import type { SupportedWalletInfo } from 'context/WalletProvider/config' -type MetaMaskConfigType = Omit< - SupportedWalletInfo, - 'routes' -> +type MetaMaskConfigType = Omit, 'routes'> export const MetaMaskConfig: MetaMaskConfigType = { adapters: [ { loadAdapter: () => - // @ts-ignore TODO(gomes): FIXME getConfig().REACT_APP_EXPERIMENTAL_MM_SNAPPY_FINGERS - ? import('@shapeshiftoss/hdwallet-shapeshift-multichain').then(m => m.MetaMaskAdapter) + ? import('@shapeshiftoss/hdwallet-shapeshift-multichain').then( + m => m.MetaMaskAdapter as typeof MetaMaskAdapter, + ) : import('@shapeshiftoss/hdwallet-metamask').then(m => m.MetaMaskAdapter), }, ], diff --git a/src/context/WalletProvider/types.ts b/src/context/WalletProvider/types.ts index 653a82642cf..6ce4ef51a23 100644 --- a/src/context/WalletProvider/types.ts +++ b/src/context/WalletProvider/types.ts @@ -5,7 +5,6 @@ import type { KeplrAdapter } from '@shapeshiftoss/hdwallet-keplr' import type { WebUSBLedgerAdapter } from '@shapeshiftoss/hdwallet-ledger-webusb' import type { MetaMaskAdapter } from '@shapeshiftoss/hdwallet-metamask' import type { NativeAdapter } from '@shapeshiftoss/hdwallet-native' -import type { MetaMaskAdapter as MetaMaskMultiChainAdapter } from '@shapeshiftoss/hdwallet-shapeshift-multichain' import type { WalletConnectV2Adapter } from '@shapeshiftoss/hdwallet-walletconnectv2' import type { XDEFIAdapter } from '@shapeshiftoss/hdwallet-xdefi' @@ -19,7 +18,7 @@ export type AdaptersByKeyManager = { [KeyManager.Ledger]: [WebUSBLedgerAdapter] [KeyManager.Keplr]: [KeplrAdapter] [KeyManager.WalletConnectV2]: [WalletConnectV2Adapter] - [KeyManager.MetaMask]: [MetaMaskAdapter | MetaMaskMultiChainAdapter] + [KeyManager.MetaMask]: [MetaMaskAdapter] [KeyManager.Coinbase]: [CoinbaseAdapter] [KeyManager.XDefi]: [XDEFIAdapter] } From 628fc0efb928cebc5e4a4c33cd049ff95945d8ad Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 16 Oct 2023 16:10:00 +0200 Subject: [PATCH 4/9] feat: rm ts-ignore --- src/context/WalletProvider/WalletProvider.tsx | 526 ++++++++++-------- 1 file changed, 287 insertions(+), 239 deletions(-) diff --git a/src/context/WalletProvider/WalletProvider.tsx b/src/context/WalletProvider/WalletProvider.tsx index 7084abeffdd..554a63ad9a3 100644 --- a/src/context/WalletProvider/WalletProvider.tsx +++ b/src/context/WalletProvider/WalletProvider.tsx @@ -404,276 +404,324 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX if (localWalletType && localWalletDeviceId) { ;(async () => { const currentAdapters = state.adapters ?? ({} as AdaptersByKeyManager) - const _adapter = await getAdapter(localWalletType) - - if (_adapter) { - try { - // @ts-ignore TODO(gomes): FIXME, most likely borked because of WebUSBKeepKeyAdapter - currentAdapters[localWalletType] = [_adapter] - dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) - } catch (e) { - console.error(e) - } - // Fixes issue with wallet `type` being null when the wallet is loaded from state - dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) - switch (localWalletType) { - case KeyManager.Mobile: - try { - // Get the adapter again in each switch case to narrow down the adapter type - const mobileAdapter = await getAdapter(localWalletType) - const w = await getWallet(localWalletDeviceId) - if (w && w.mnemonic && w.label) { - const localMobileWallet = await mobileAdapter?.pairDevice(localWalletDeviceId) - - if (localMobileWallet) { - localMobileWallet.loadDevice({ label: w.label, mnemonic: w.mnemonic }) - const { name, icon } = MobileConfig - dispatch({ - type: WalletActions.SET_WALLET, - payload: { - wallet: localMobileWallet, - name, - icon, - deviceId: w.id || localWalletDeviceId, - meta: { label: w.label }, - connectedType: KeyManager.Mobile, - }, - }) - dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) - // Turn off the loading spinner for the wallet button in - dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) - } else { - disconnect() - } - } else { - // in the case we return a null from the mobile app and fail to get the wallet - // we want to disconnect and return the user back to the splash screen - disconnect() - } - } catch (e) { - console.error(e) - } - break - case KeyManager.Native: + switch (localWalletType) { + case KeyManager.Mobile: + try { // Get the adapter again in each switch case to narrow down the adapter type - const nativeAdapter = await getAdapter(localWalletType) - const localNativeWallet = await nativeAdapter?.pairDevice(localWalletDeviceId) - if (localNativeWallet) { - /** - * This will eventually fire an event, which the ShapeShift wallet - * password modal will be shown - */ - await localNativeWallet.initialize() - } else { - disconnect() + const mobileAdapter = await getAdapter(localWalletType) + + if (mobileAdapter) { + currentAdapters[localWalletType] = [mobileAdapter] + dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) + // Fixes issue with wallet `type` being null when the wallet is loaded from state + dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) } - break - // We don't want to pairDevice() for ledger here - this will run on app load and won't work, as WebUSB `requestPermission` must be - // called from a user gesture. Instead, we'll pair the device when the user clicks the "Pair Device` button in Ledger `` - // case KeyManager.Ledger: - // const ledgerWallet = await state.adapters.get(KeyManager.Ledger)?.[0].pairDevice() - // return ledgerWallet - case KeyManager.KeepKey: - try { - const localKeepKeyWallet = await (async () => { - const maybeWallet = state.keyring.get(localWalletDeviceId) - if (maybeWallet) return maybeWallet - const keepKeyAdapter = await getAdapter(KeyManager.KeepKey) - if (!keepKeyAdapter) return - const sdk = await setupKeepKeySDK() - // @ts-ignore TODO(gomes): FIXME, most likely borked because of WebUSBKeepKeyAdapter - return await keepKeyAdapter.pairDevice(sdk) - })() - - /** - * if localKeepKeyWallet is not null it means - * KeepKey remained connected during the reload - */ - if (localKeepKeyWallet) { - const { name, icon } = SUPPORTED_WALLETS[KeyManager.KeepKey] - const deviceId = await localKeepKeyWallet.getDeviceID() - // This gets the firmware version needed for some KeepKey "supportsX" functions - await localKeepKeyWallet.getFeatures() - // Show the label from the wallet instead of a generic name - const label = (await localKeepKeyWallet.getLabel()) || name - - await localKeepKeyWallet.initialize() + const w = await getWallet(localWalletDeviceId) + if (w && w.mnemonic && w.label) { + const localMobileWallet = await mobileAdapter?.pairDevice(localWalletDeviceId) + if (localMobileWallet) { + localMobileWallet.loadDevice({ label: w.label, mnemonic: w.mnemonic }) + const { name, icon } = MobileConfig dispatch({ type: WalletActions.SET_WALLET, payload: { - wallet: localKeepKeyWallet, + wallet: localMobileWallet, name, icon, - deviceId, - meta: { label }, - connectedType: KeyManager.KeepKey, + deviceId: w.id || localWalletDeviceId, + meta: { label: w.label }, + connectedType: KeyManager.Mobile, }, }) dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) + // Turn off the loading spinner for the wallet button in + dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) } else { disconnect() } - } catch (e) { + } else { + // in the case we return a null from the mobile app and fail to get the wallet + // we want to disconnect and return the user back to the splash screen disconnect() } - dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) - break - case KeyManager.MetaMask: - // Get the adapter again in each switch case to narrow down the adapter type - const metamaskAdapter = await getAdapter(localWalletType) - const localMetaMaskWallet = await metamaskAdapter?.pairDevice() - if (localMetaMaskWallet) { - const { name, icon } = SUPPORTED_WALLETS[KeyManager.MetaMask] - try { - await localMetaMaskWallet.initialize() - const deviceId = await localMetaMaskWallet.getDeviceID() - dispatch({ - type: WalletActions.SET_WALLET, - payload: { - wallet: localMetaMaskWallet, - name, - icon, - deviceId, - connectedType: KeyManager.MetaMask, - }, - }) - dispatch({ type: WalletActions.SET_IS_LOCKED, payload: false }) - dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) - } catch (e) { - disconnect() - } + } catch (e) { + console.error(e) + } + break + case KeyManager.Native: + // Get the adapter again in each switch case to narrow down the adapter type + const nativeAdapter = await getAdapter(localWalletType) + if (nativeAdapter) { + currentAdapters[localWalletType] = [nativeAdapter] + dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) + // Fixes issue with wallet `type` being null when the wallet is loaded from state + dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) + } + + const localNativeWallet = await nativeAdapter?.pairDevice(localWalletDeviceId) + if (localNativeWallet) { + /** + * This will eventually fire an event, which the ShapeShift wallet + * password modal will be shown + */ + await localNativeWallet.initialize() + } else { + disconnect() + } + break + // We don't want to pairDevice() for ledger here - this will run on app load and won't work, as WebUSB `requestPermission` must be + // called from a user gesture. Instead, we'll pair the device when the user clicks the "Pair Device` button in Ledger `` + // case KeyManager.Ledger: + // const ledgerWallet = await state.adapters.get(KeyManager.Ledger)?.[0].pairDevice() + // return ledgerWallet + case KeyManager.KeepKey: + try { + const localKeepKeyWallet = await (async () => { + const maybeWallet = state.keyring.get(localWalletDeviceId) + if (maybeWallet) return maybeWallet + // Get the adapter again in each switch case to narrow down the adapter type + const keepKeyAdapter = await getAdapter(KeyManager.KeepKey) + if (!keepKeyAdapter) return + + currentAdapters[localWalletType] = [keepKeyAdapter] + dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) + // Fixes issue with wallet `type` being null when the wallet is loaded from state + dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) + + const sdk = await setupKeepKeySDK() + // @ts-ignore TODO(gomes): FIXME, most likely borked because of WebUSBKeepKeyAdapter + return await keepKeyAdapter.pairDevice(sdk) + })() + + /** + * if localKeepKeyWallet is not null it means + * KeepKey remained connected during the reload + */ + if (localKeepKeyWallet) { + const { name, icon } = SUPPORTED_WALLETS[KeyManager.KeepKey] + const deviceId = await localKeepKeyWallet.getDeviceID() + // This gets the firmware version needed for some KeepKey "supportsX" functions + await localKeepKeyWallet.getFeatures() + // Show the label from the wallet instead of a generic name + const label = (await localKeepKeyWallet.getLabel()) || name + + await localKeepKeyWallet.initialize() + + dispatch({ + type: WalletActions.SET_WALLET, + payload: { + wallet: localKeepKeyWallet, + name, + icon, + deviceId, + meta: { label }, + connectedType: KeyManager.KeepKey, + }, + }) + dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) } else { disconnect() } - dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) - break - case KeyManager.Coinbase: - // Get the adapter again in each switch case to narrow down the adapter type - const coinbaseAdapter = await getAdapter(localWalletType) - const localCoinbaseWallet = await coinbaseAdapter?.pairDevice() - if (localCoinbaseWallet) { - const { name, icon } = SUPPORTED_WALLETS[KeyManager.Coinbase] - try { - await localCoinbaseWallet.initialize() - const deviceId = await localCoinbaseWallet.getDeviceID() - dispatch({ - type: WalletActions.SET_WALLET, - payload: { - wallet: localCoinbaseWallet, - name, - icon, - deviceId, - connectedType: KeyManager.Coinbase, - }, - }) - dispatch({ type: WalletActions.SET_IS_LOCKED, payload: false }) - dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) - } catch (e) { - disconnect() - } - } else { + } catch (e) { + disconnect() + } + dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) + break + case KeyManager.MetaMask: + // Get the adapter again in each switch case to narrow down the adapter type + const metamaskAdapter = await getAdapter(localWalletType) + + if (metamaskAdapter) { + currentAdapters[localWalletType] = [metamaskAdapter] + dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) + // Fixes issue with wallet `type` being null when the wallet is loaded from state + dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) + } + + const localMetaMaskWallet = await metamaskAdapter?.pairDevice() + if (localMetaMaskWallet) { + const { name, icon } = SUPPORTED_WALLETS[KeyManager.MetaMask] + try { + await localMetaMaskWallet.initialize() + const deviceId = await localMetaMaskWallet.getDeviceID() + dispatch({ + type: WalletActions.SET_WALLET, + payload: { + wallet: localMetaMaskWallet, + name, + icon, + deviceId, + connectedType: KeyManager.MetaMask, + }, + }) + dispatch({ type: WalletActions.SET_IS_LOCKED, payload: false }) + dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) + } catch (e) { disconnect() } - dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) - break - case KeyManager.XDefi: - // Get the adapter again in each switch case to narrow down the adapter type - const xdefiAdapter = await getAdapter(localWalletType) - const localXDEFIWallet = await xdefiAdapter?.pairDevice() - if (localXDEFIWallet) { - const { name, icon } = SUPPORTED_WALLETS[KeyManager.XDefi] - try { - await localXDEFIWallet.initialize() - const deviceId = await localXDEFIWallet.getDeviceID() - dispatch({ - type: WalletActions.SET_WALLET, - payload: { - wallet: localXDEFIWallet, - name, - icon, - deviceId, - connectedType: KeyManager.XDefi, - }, - }) - dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) - } catch (e) { - disconnect() - } - } else { + } else { + disconnect() + } + dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) + break + case KeyManager.Coinbase: + // Get the adapter again in each switch case to narrow down the adapter type + const coinbaseAdapter = await getAdapter(localWalletType) + + if (coinbaseAdapter) { + currentAdapters[localWalletType] = [coinbaseAdapter] + dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) + // Fixes issue with wallet `type` being null when the wallet is loaded from state + dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) + } + + const localCoinbaseWallet = await coinbaseAdapter?.pairDevice() + if (localCoinbaseWallet) { + const { name, icon } = SUPPORTED_WALLETS[KeyManager.Coinbase] + try { + await localCoinbaseWallet.initialize() + const deviceId = await localCoinbaseWallet.getDeviceID() + dispatch({ + type: WalletActions.SET_WALLET, + payload: { + wallet: localCoinbaseWallet, + name, + icon, + deviceId, + connectedType: KeyManager.Coinbase, + }, + }) + dispatch({ type: WalletActions.SET_IS_LOCKED, payload: false }) + dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) + } catch (e) { disconnect() } - dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) - break - case KeyManager.Keplr: - // Get the adapter again in each switch case to narrow down the adapter type - const keplrAdapter = await getAdapter(localWalletType) - const localKeplrWallet = await keplrAdapter?.pairDevice() - if (localKeplrWallet) { - const { name, icon } = SUPPORTED_WALLETS[KeyManager.Keplr] - try { - await localKeplrWallet.initialize() - const deviceId = await localKeplrWallet.getDeviceID() - dispatch({ - type: WalletActions.SET_WALLET, - payload: { - wallet: localKeplrWallet, - name, - icon, - deviceId, - connectedType: KeyManager.Keplr, - }, - }) - dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) - } catch (e) { - disconnect() - } - } else { + } else { + disconnect() + } + dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) + break + case KeyManager.XDefi: + // Get the adapter again in each switch case to narrow down the adapter type + const xdefiAdapter = await getAdapter(localWalletType) + + if (xdefiAdapter) { + currentAdapters[localWalletType] = [xdefiAdapter] + dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) + // Fixes issue with wallet `type` being null when the wallet is loaded from state + dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) + } + + const localXDEFIWallet = await xdefiAdapter?.pairDevice() + if (localXDEFIWallet) { + const { name, icon } = SUPPORTED_WALLETS[KeyManager.XDefi] + try { + await localXDEFIWallet.initialize() + const deviceId = await localXDEFIWallet.getDeviceID() + dispatch({ + type: WalletActions.SET_WALLET, + payload: { + wallet: localXDEFIWallet, + name, + icon, + deviceId, + connectedType: KeyManager.XDefi, + }, + }) + dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) + } catch (e) { disconnect() } - dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) - break - case KeyManager.WalletConnectV2: { - // Get the adapter again in each switch case to narrow down the adapter type - const walletConnectV2Adapter = await getAdapter(localWalletType) - // Re-trigger the modal on refresh - await onProviderChange(KeyManager.WalletConnectV2) - const localWalletConnectWallet = await walletConnectV2Adapter?.pairDevice() - if (localWalletConnectWallet) { - const { name, icon } = SUPPORTED_WALLETS[KeyManager.WalletConnectV2] - try { - await localWalletConnectWallet.initialize() - const deviceId = await localWalletConnectWallet.getDeviceID() - dispatch({ - type: WalletActions.SET_WALLET, - payload: { - wallet: localWalletConnectWallet, - name, - icon, - deviceId, - connectedType: KeyManager.WalletConnectV2, - }, - }) - dispatch({ type: WalletActions.SET_IS_LOCKED, payload: false }) - dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) - } catch (e) { - disconnect() - } - } else { + } else { + disconnect() + } + dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) + break + case KeyManager.Keplr: + // Get the adapter again in each switch case to narrow down the adapter type + const keplrAdapter = await getAdapter(localWalletType) + + if (keplrAdapter) { + currentAdapters[localWalletType] = [keplrAdapter] + dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) + // Fixes issue with wallet `type` being null when the wallet is loaded from state + dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) + } + + const localKeplrWallet = await keplrAdapter?.pairDevice() + if (localKeplrWallet) { + const { name, icon } = SUPPORTED_WALLETS[KeyManager.Keplr] + try { + await localKeplrWallet.initialize() + const deviceId = await localKeplrWallet.getDeviceID() + dispatch({ + type: WalletActions.SET_WALLET, + payload: { + wallet: localKeplrWallet, + name, + icon, + deviceId, + connectedType: KeyManager.Keplr, + }, + }) + dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) + } catch (e) { disconnect() } - dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) - break + } else { + disconnect() } - default: - /** - * The fall-through case also handles clearing - * any demo wallet state on refresh/rerender. - */ + dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) + break + case KeyManager.WalletConnectV2: { + // Get the adapter again in each switch case to narrow down the adapter type + const walletConnectV2Adapter = await getAdapter(localWalletType) + + if (walletConnectV2Adapter) { + currentAdapters[localWalletType] = [walletConnectV2Adapter] + dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) + // Fixes issue with wallet `type` being null when the wallet is loaded from state + dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) + } + + // Re-trigger the modal on refresh + await onProviderChange(KeyManager.WalletConnectV2) + const localWalletConnectWallet = await walletConnectV2Adapter?.pairDevice() + if (localWalletConnectWallet) { + const { name, icon } = SUPPORTED_WALLETS[KeyManager.WalletConnectV2] + try { + await localWalletConnectWallet.initialize() + const deviceId = await localWalletConnectWallet.getDeviceID() + dispatch({ + type: WalletActions.SET_WALLET, + payload: { + wallet: localWalletConnectWallet, + name, + icon, + deviceId, + connectedType: KeyManager.WalletConnectV2, + }, + }) + dispatch({ type: WalletActions.SET_IS_LOCKED, payload: false }) + dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) + } catch (e) { + disconnect() + } + } else { disconnect() - break + } + dispatch({ type: WalletActions.SET_LOCAL_WALLET_LOADING, payload: false }) + break } + default: + /** + * The fall-through case also handles clearing + * any demo wallet state on refresh/rerender. + */ + disconnect() + break } })() } From 79707ca77b5c27f480e64bfe10c33d468c94d475 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 16 Oct 2023 19:17:00 +0200 Subject: [PATCH 5/9] fix: infinite dispatch --- src/context/WalletProvider/WalletProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context/WalletProvider/WalletProvider.tsx b/src/context/WalletProvider/WalletProvider.tsx index 554a63ad9a3..f67952b3d55 100644 --- a/src/context/WalletProvider/WalletProvider.tsx +++ b/src/context/WalletProvider/WalletProvider.tsx @@ -900,7 +900,7 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX }) }, []) - useEffect(() => load(), [load, state.adapters, state.keyring]) + useEffect(() => load(), [load, state.keyring]) useKeyringEventHandler(state) useNativeEventHandler(state, dispatch) From a6f6b91cf80839a42efc6f6a381bfb79798742db Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 16 Oct 2023 21:41:37 +0200 Subject: [PATCH 6/9] feat: rm useless ts-ignore --- src/context/WalletProvider/config.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/context/WalletProvider/config.ts b/src/context/WalletProvider/config.ts index 076cffdaace..db292dfc251 100644 --- a/src/context/WalletProvider/config.ts +++ b/src/context/WalletProvider/config.ts @@ -178,7 +178,6 @@ export const SUPPORTED_WALLETS: SupportedWalletInfoByKeyManager = { ], connectedWalletMenuInitialPath: WalletConnectedRoutes.KeepKey, }, - // @ts-ignore TODO(gomes): FIXME [KeyManager.MetaMask]: { ...MetaMaskConfig, routes: [ From e57f316b618e0e623a49a81650b40f0edb3c5a2e Mon Sep 17 00:00:00 2001 From: woodenfurniture <125113430+woodenfurniture@users.noreply.github.com> Date: Tue, 17 Oct 2023 07:53:43 +1100 Subject: [PATCH 7/9] wip --- .../KeepKey/components/Connect.tsx | 9 +++--- src/context/WalletProvider/WalletProvider.tsx | 32 +++++++++---------- src/context/WalletProvider/actions.ts | 2 +- src/context/WalletProvider/types.ts | 24 +++++++------- 4 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/context/WalletProvider/KeepKey/components/Connect.tsx b/src/context/WalletProvider/KeepKey/components/Connect.tsx index 3f00b8090b6..ecbf9452fba 100644 --- a/src/context/WalletProvider/KeepKey/components/Connect.tsx +++ b/src/context/WalletProvider/KeepKey/components/Connect.tsx @@ -6,7 +6,6 @@ import { ModalBody, ModalHeader, } from '@chakra-ui/react' -import type { KkRestAdapter } from '@keepkey/hdwallet-keepkey-rest' import type { Event } from '@shapeshiftoss/hdwallet-core' import { useCallback, useState } from 'react' import { CircularProgress } from 'components/CircularProgress/CircularProgress' @@ -53,7 +52,9 @@ export const KeepKeyConnect = () => { setError(null) setLoading(true) - const firstAdapter = (await getAdapter(KeyManager.KeepKey)) as KkRestAdapter | null + const keepKeyAdapters = await getAdapter(KeyManager.KeepKey) + if (!keepKeyAdapters) return + const { rest: firstAdapter, usb: secondAdapter } = keepKeyAdapters if (firstAdapter) { const wallet = await (async () => { try { @@ -66,9 +67,9 @@ export const KeepKeyConnect = () => { } return wallet } catch (e) { - const secondAdapter = await getAdapter(KeyManager.KeepKey, 1) + // const secondAdapter = await getAdapter(KeyManager.KeepKey, 1) // @ts-ignore TODO(gomes): FIXME, most likely borked because of WebUSBKeepKeyAdapter - const wallet = await secondAdapter?.pairDevice().catch(err => { + const wallet = await secondAdapter.pairDevice().catch(err => { if (err.name === 'ConflictingApp') { setErrorLoading('walletProvider.keepKey.connect.conflictingApp') return diff --git a/src/context/WalletProvider/WalletProvider.tsx b/src/context/WalletProvider/WalletProvider.tsx index f67952b3d55..6c2a25503a9 100644 --- a/src/context/WalletProvider/WalletProvider.tsx +++ b/src/context/WalletProvider/WalletProvider.tsx @@ -89,7 +89,7 @@ export type KeyManagerWithProvider = export interface InitialState { keyring: Keyring - adapters: AdaptersByKeyManager | null + adapters: Partial wallet: HDWallet | null modalType: KeyManager | null connectedType: KeyManager | null @@ -110,7 +110,7 @@ export interface InitialState { const initialState: InitialState = { keyring: new Keyring(), - adapters: null, + adapters: {}, wallet: null, modalType: null, connectedType: null, @@ -354,12 +354,11 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX const [walletType, setWalletType] = useState(null) const getAdapter: GetAdapter = useCallback( - async (keyManager, index: number = 0) => { - let currentStateAdapters = state.adapters ?? ({} as AdaptersByKeyManager) + async (keyManager, index) => { + let currentStateAdapters = state.adapters // ?? ({} as AdaptersByKeyManager) // Check if adapter is already in the state - let adapterInstance = currentStateAdapters[keyManager]?.[index] - const currentKeyManagerAdapters = currentStateAdapters[keyManager] ?? [] + let adapterInstance = currentStateAdapters[keyManager] if (!adapterInstance) { // If not, create a new instance of the adapter @@ -372,8 +371,7 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX adapterInstance = Adapter.useKeyring(state.keyring, keyManagerOptions) if (adapterInstance) { - currentKeyManagerAdapters[index] = adapterInstance - currentStateAdapters[keyManager] = currentKeyManagerAdapters + currentStateAdapters[keyManager] = adapterInstance // Set it in wallet state for later use dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentStateAdapters }) } @@ -409,10 +407,10 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX case KeyManager.Mobile: try { // Get the adapter again in each switch case to narrow down the adapter type - const mobileAdapter = await getAdapter(localWalletType) + const mobileAdapter = await getAdapter(localWalletType, 0) if (mobileAdapter) { - currentAdapters[localWalletType] = [mobileAdapter] + currentAdapters[localWalletType] = mobileAdapter dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) // Fixes issue with wallet `type` being null when the wallet is loaded from state dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) @@ -454,7 +452,7 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX // Get the adapter again in each switch case to narrow down the adapter type const nativeAdapter = await getAdapter(localWalletType) if (nativeAdapter) { - currentAdapters[localWalletType] = [nativeAdapter] + currentAdapters[localWalletType] = nativeAdapter dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) // Fixes issue with wallet `type` being null when the wallet is loaded from state dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) @@ -485,7 +483,7 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX const keepKeyAdapter = await getAdapter(KeyManager.KeepKey) if (!keepKeyAdapter) return - currentAdapters[localWalletType] = [keepKeyAdapter] + currentAdapters[localWalletType] = keepKeyAdapter dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) // Fixes issue with wallet `type` being null when the wallet is loaded from state dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) @@ -534,7 +532,7 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX const metamaskAdapter = await getAdapter(localWalletType) if (metamaskAdapter) { - currentAdapters[localWalletType] = [metamaskAdapter] + currentAdapters[localWalletType] = metamaskAdapter dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) // Fixes issue with wallet `type` being null when the wallet is loaded from state dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) @@ -571,7 +569,7 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX const coinbaseAdapter = await getAdapter(localWalletType) if (coinbaseAdapter) { - currentAdapters[localWalletType] = [coinbaseAdapter] + currentAdapters[localWalletType] = coinbaseAdapter dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) // Fixes issue with wallet `type` being null when the wallet is loaded from state dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) @@ -608,7 +606,7 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX const xdefiAdapter = await getAdapter(localWalletType) if (xdefiAdapter) { - currentAdapters[localWalletType] = [xdefiAdapter] + currentAdapters[localWalletType] = xdefiAdapter dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) // Fixes issue with wallet `type` being null when the wallet is loaded from state dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) @@ -644,7 +642,7 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX const keplrAdapter = await getAdapter(localWalletType) if (keplrAdapter) { - currentAdapters[localWalletType] = [keplrAdapter] + currentAdapters[localWalletType] = keplrAdapter dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) // Fixes issue with wallet `type` being null when the wallet is loaded from state dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) @@ -680,7 +678,7 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX const walletConnectV2Adapter = await getAdapter(localWalletType) if (walletConnectV2Adapter) { - currentAdapters[localWalletType] = [walletConnectV2Adapter] + currentAdapters[localWalletType] = walletConnectV2Adapter dispatch({ type: WalletActions.SET_ADAPTERS, payload: currentAdapters }) // Fixes issue with wallet `type` being null when the wallet is loaded from state dispatch({ type: WalletActions.SET_CONNECTOR_TYPE, payload: localWalletType }) diff --git a/src/context/WalletProvider/actions.ts b/src/context/WalletProvider/actions.ts index bb4304ef550..e78fcbe4958 100644 --- a/src/context/WalletProvider/actions.ts +++ b/src/context/WalletProvider/actions.ts @@ -31,7 +31,7 @@ export enum WalletActions { } export type ActionTypes = - | { type: WalletActions.SET_ADAPTERS; payload: AdaptersByKeyManager } + | { type: WalletActions.SET_ADAPTERS; payload: Partial } | { type: WalletActions.SET_WALLET payload: WalletInfo & { diff --git a/src/context/WalletProvider/types.ts b/src/context/WalletProvider/types.ts index 6ce4ef51a23..d3354076be7 100644 --- a/src/context/WalletProvider/types.ts +++ b/src/context/WalletProvider/types.ts @@ -11,19 +11,19 @@ import type { XDEFIAdapter } from '@shapeshiftoss/hdwallet-xdefi' import type { KeyManager } from './KeyManager' export type AdaptersByKeyManager = { - [KeyManager.Mobile]: [NativeAdapter] - [KeyManager.Native]: [NativeAdapter] - [KeyManager.Demo]: [NativeAdapter] - [KeyManager.KeepKey]: [KkRestAdapter | typeof WebUSBKeepKeyAdapter] - [KeyManager.Ledger]: [WebUSBLedgerAdapter] - [KeyManager.Keplr]: [KeplrAdapter] - [KeyManager.WalletConnectV2]: [WalletConnectV2Adapter] - [KeyManager.MetaMask]: [MetaMaskAdapter] - [KeyManager.Coinbase]: [CoinbaseAdapter] - [KeyManager.XDefi]: [XDEFIAdapter] + [KeyManager.Mobile]: NativeAdapter + [KeyManager.Native]: NativeAdapter + [KeyManager.Demo]: NativeAdapter + [KeyManager.KeepKey]: KkRestAdapter | typeof WebUSBKeepKeyAdapter + [KeyManager.Ledger]: WebUSBLedgerAdapter + [KeyManager.Keplr]: KeplrAdapter + [KeyManager.WalletConnectV2]: WalletConnectV2Adapter + [KeyManager.MetaMask]: MetaMaskAdapter + [KeyManager.Coinbase]: CoinbaseAdapter + [KeyManager.XDefi]: XDEFIAdapter } export type GetAdapter = ( keyManager: K, - index?: number, -) => Promise + index: K extends KeyManager.KeepKey ? 0 | 1 : 0, // only used for keepkey +) => Promise From 764ea6bc3b272fcb6870312f624e43b93a040288 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 16 Oct 2023 23:15:07 +0200 Subject: [PATCH 8/9] feat: gm, she compiles again --- src/context/WalletProvider/KeepKey/components/Connect.tsx | 7 +++---- src/context/WalletProvider/WalletProvider.tsx | 4 +++- src/context/WalletProvider/types.ts | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/context/WalletProvider/KeepKey/components/Connect.tsx b/src/context/WalletProvider/KeepKey/components/Connect.tsx index ecbf9452fba..ea9130b95b1 100644 --- a/src/context/WalletProvider/KeepKey/components/Connect.tsx +++ b/src/context/WalletProvider/KeepKey/components/Connect.tsx @@ -6,6 +6,7 @@ import { ModalBody, ModalHeader, } from '@chakra-ui/react' +import type { KkRestAdapter } from '@keepkey/hdwallet-keepkey-rest' import type { Event } from '@shapeshiftoss/hdwallet-core' import { useCallback, useState } from 'react' import { CircularProgress } from 'components/CircularProgress/CircularProgress' @@ -52,9 +53,7 @@ export const KeepKeyConnect = () => { setError(null) setLoading(true) - const keepKeyAdapters = await getAdapter(KeyManager.KeepKey) - if (!keepKeyAdapters) return - const { rest: firstAdapter, usb: secondAdapter } = keepKeyAdapters + const firstAdapter = (await getAdapter(KeyManager.KeepKey)) as KkRestAdapter | null if (firstAdapter) { const wallet = await (async () => { try { @@ -67,7 +66,7 @@ export const KeepKeyConnect = () => { } return wallet } catch (e) { - // const secondAdapter = await getAdapter(KeyManager.KeepKey, 1) + const secondAdapter = await getAdapter(KeyManager.KeepKey, 1) // @ts-ignore TODO(gomes): FIXME, most likely borked because of WebUSBKeepKeyAdapter const wallet = await secondAdapter.pairDevice().catch(err => { if (err.name === 'ConflictingApp') { diff --git a/src/context/WalletProvider/WalletProvider.tsx b/src/context/WalletProvider/WalletProvider.tsx index 6c2a25503a9..900660e91e9 100644 --- a/src/context/WalletProvider/WalletProvider.tsx +++ b/src/context/WalletProvider/WalletProvider.tsx @@ -354,7 +354,7 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX const [walletType, setWalletType] = useState(null) const getAdapter: GetAdapter = useCallback( - async (keyManager, index) => { + async (keyManager, index = 0) => { let currentStateAdapters = state.adapters // ?? ({} as AdaptersByKeyManager) // Check if adapter is already in the state @@ -381,6 +381,8 @@ export const WalletProvider = ({ children }: { children: React.ReactNode }): JSX } } + if (!adapterInstance) return null + return adapterInstance }, [isDarkMode, state.adapters, state.keyring], diff --git a/src/context/WalletProvider/types.ts b/src/context/WalletProvider/types.ts index d3354076be7..efcfe2d02ff 100644 --- a/src/context/WalletProvider/types.ts +++ b/src/context/WalletProvider/types.ts @@ -25,5 +25,5 @@ export type AdaptersByKeyManager = { export type GetAdapter = ( keyManager: K, - index: K extends KeyManager.KeepKey ? 0 | 1 : 0, // only used for keepkey + index?: K extends KeyManager.KeepKey ? 0 | 1 : 0, // only used for keepkey ) => Promise From 8fbdf902bf5d25df3201ee643b31137cfcf48cd3 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 17 Oct 2023 14:18:31 +0200 Subject: [PATCH 9/9] perf: defi only render current step if active --- src/components/DeFi/components/Steps.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/DeFi/components/Steps.tsx b/src/components/DeFi/components/Steps.tsx index 06358dc94e9..23cdc82506d 100644 --- a/src/components/DeFi/components/Steps.tsx +++ b/src/components/DeFi/components/Steps.tsx @@ -49,6 +49,7 @@ export const Steps: React.FC = ({ const Step = steps[step as DefiStep] if (!Step) return null const Component = Step.component + const isActive = currentStep === index return ( = ({ description={Step?.description} stepNumber={`${index + 1}`} isComplete={currentStep > index} - isActive={currentStep === index} + isActive={isActive} > - + {isActive && } ) })}