From 52dad8638a70c6e6aa5f086211482939d8b52e48 Mon Sep 17 00:00:00 2001 From: hemanthghs Date: Wed, 18 Sep 2024 12:49:56 +0530 Subject: [PATCH] add reducer for metamask connection --- .../components/main-layout/ConnectWallet.tsx | 41 ++-- .../components/main-layout/FixedLayout.tsx | 28 ++- .../src/store/features/wallet/walletSlice.ts | 223 ++++++++++-------- frontend/src/utils/constants.ts | 5 + 4 files changed, 159 insertions(+), 138 deletions(-) diff --git a/frontend/src/components/main-layout/ConnectWallet.tsx b/frontend/src/components/main-layout/ConnectWallet.tsx index fa8100e58..01b641b20 100644 --- a/frontend/src/components/main-layout/ConnectWallet.tsx +++ b/frontend/src/components/main-layout/ConnectWallet.tsx @@ -1,11 +1,12 @@ import { useAppDispatch, useAppSelector } from '@/custom-hooks/StateHooks'; import { + establishMetamaskConnection, establishWalletConnection, setConnectWalletOpen, setIsLoading, } from '@/store/features/wallet/walletSlice'; import { networks } from '@/utils/chainsInfo'; -import { SUPPORTED_WALLETS } from '@/utils/constants'; +import { NotSupportedMetamaskChainIds, SUPPORTED_WALLETS } from '@/utils/constants'; import { getLocalNetworks } from '@/utils/localStorage'; import { connectSnap, @@ -38,50 +39,44 @@ const ConnectWallet = () => { const tryConnectWallet = async (walletName: string) => { if (walletName === 'metamask') { - const notSupoortedMetamaskChainIds = ['agoric-3', 'evmos_9001-2', 'desmos-mainnet'] dispatch(setIsLoading()); - try { const snapInstalled = await getSnap(); if (!snapInstalled) { await connectSnap(); // Initiates installation if not already present } - } catch (error) { - console.log('Unable to install snap', error) - } - try { for (let i = 0; i < networks.length; i++) { - console.time("Function execution time"); - const chainId: string = networks[i].config.chainId; - if (notSupoortedMetamaskChainIds.indexOf(chainId) <= -1) { + if (NotSupportedMetamaskChainIds.indexOf(chainId) <= -1) { try { - await experimentalSuggestChain(networks[i].config, { + await experimentalSuggestChain(networks[i].config, { force: false, }); + dispatch( + establishMetamaskConnection({ + walletName, + network: networks[i], + }) + ); } catch (error) { console.log('Error while connecting ', chainId); } } - - console.timeEnd("Function execution time"); } - - } catch (error) { console.log('trying to connect wallet ', error); } + } else { + dispatch( + establishWalletConnection({ + walletName, + networks: [...networks, ...getLocalNetworks()], + }) + ); } - - dispatch( - establishWalletConnection({ - walletName, - networks: [...networks, ...getLocalNetworks()], - }) - ); }; - + return ( { const isLoading = useAppSelector((state) => state.wallet.isLoading); const walletState = useAppSelector((state) => state.wallet.status); - const notSupoortedMetamaskChainIds = ['agoric-3', 'evmos_9001-2', 'desmos-mainnet'] const tryConnectWallet = async (walletName: string) => { if (walletName === 'metamask') { @@ -57,29 +57,33 @@ const FixedLayout = ({ children }: { children: React.ReactNode }) => { for (let i = 0; i < networks.length; i++) { const chainId: string = networks[i].config.chainId; - if (notSupoortedMetamaskChainIds.indexOf(chainId) <= -1) { - + if (NotSupportedMetamaskChainIds.indexOf(chainId) <= -1) { try { await experimentalSuggestChain(networks[i].config, { force: false, }); + dispatch( + establishMetamaskConnection({ + walletName, + network: networks[i], + }) + ); } catch (error) { console.log('Error while connecting ', chainId); } } - } } catch (error) { console.log('trying to connect wallet ', error); } + } else { + dispatch( + establishWalletConnection({ + walletName, + networks: [...networks, ...getLocalNetworks()], + }) + ); } - - dispatch( - establishWalletConnection({ - walletName, - networks: [...networks, ...getLocalNetworks()], - }) - ); }; useEffect(() => { diff --git a/frontend/src/store/features/wallet/walletSlice.ts b/frontend/src/store/features/wallet/walletSlice.ts index 314ff3ecd..205d8a6ad 100644 --- a/frontend/src/store/features/wallet/walletSlice.ts +++ b/frontend/src/store/features/wallet/walletSlice.ts @@ -14,6 +14,7 @@ import { getAddressByPrefix } from '@/utils/address'; import { getAuthzMode } from '@/utils/localStorage'; import { enableAuthzMode } from '../authz/authzSlice'; import { enableFeegrantMode } from '../feegrant/feegrantSlice'; +import { NotSupportedMetamaskChainIds } from '@/utils/constants'; declare let window: WalletWindow; @@ -87,97 +88,51 @@ export const establishWalletConnection = createAsyncThunk( const chainInfos: Record = {}; const nameToChainIDs: Record = {}; let anyNetworkAddress = ''; - const notSupoortedMetamaskChainIds = [ - 'agoric-3', - 'evmos_9001-2', - 'desmos-mainnet', - ]; for (let i = 0; i < networks.length; i++) { const chainId = networks[i].config.chainId; - - if (data.walletName === 'metamask') { - try { - if (notSupoortedMetamaskChainIds.indexOf(chainId) === -1) { - const walletInfo = await getKey(chainId); - const chainInfo: ChainInfo = { - walletInfo: { - algo: walletInfo?.algo, - bech32Address: walletInfo?.address, - pubKey: Buffer.from(walletInfo?.pubkey).toString('base64'), - isKeystone: '', - isNanoLedger: false, - name: walletInfo?.address || '', - }, - network: networks[i], - }; - - setConnected(); - setWalletName(data.walletName); - dispatch(addChainInfo({ chainId, chainInfo })); - dispatch( - addNameToChainIDs({ - chainName: networks[i].config.chainName - .toLowerCase() - .split(' ') - .join(''), - chainId, - }) - ); - } - } catch (error) { - console.log( - `unable to connect to network ${networks[i].config.chainName}: `, - error - ); + try { + if ( + (data.walletName === 'keplr' || + data.walletName === 'cosmostation') && + networks[i].keplrExperimental + ) { + await window.wallet.experimentalSuggestChain(networks[i].config); } - } else { - try { - if ( - (data.walletName === 'keplr' || - data.walletName === 'cosmostation') && - networks[i].keplrExperimental - ) { - await window.wallet.experimentalSuggestChain(networks[i].config); - } - if (data.walletName === 'leap' && networks[i].leapExperimental) { - await window.wallet.experimentalSuggestChain(networks[i].config); - } - await getWalletAmino(chainId); - const walletInfo = await window.wallet.getKey(chainId); - walletInfo.pubKey = Buffer.from(walletInfo?.pubKey).toString( - 'base64' - ); - walletName = walletInfo?.name; - isNanoLedger = walletInfo?.isNanoLedger || false; - chainInfos[chainId] = { - walletInfo: walletInfo, - network: networks[i], - }; - if (anyNetworkAddress === '') - anyNetworkAddress = walletInfo?.bech32Address || ''; - nameToChainIDs[ - networks[i].config.chainName.toLowerCase().split(' ').join('') - ] = chainId; - } catch (error) { - console.log( - `unable to connect to network ${networks[i].config.chainName}: `, - error - ); - dispatch( - setError({ - type: 'error', - message: `Unable to connect to network ${networks[i].config.chainName}`, - }) - ); + if (data.walletName === 'leap' && networks[i].leapExperimental) { + await window.wallet.experimentalSuggestChain(networks[i].config); } + await getWalletAmino(chainId); + const walletInfo = await window.wallet.getKey(chainId); + walletInfo.pubKey = Buffer.from(walletInfo?.pubKey).toString( + 'base64' + ); + walletName = walletInfo?.name; + isNanoLedger = walletInfo?.isNanoLedger || false; + chainInfos[chainId] = { + walletInfo: walletInfo, + network: networks[i], + }; + if (anyNetworkAddress === '') + anyNetworkAddress = walletInfo?.bech32Address || ''; + nameToChainIDs[ + networks[i].config.chainName.toLowerCase().split(' ').join('') + ] = chainId; + } catch (error) { + console.log( + `unable to connect to network ${networks[i].config.chainName}: `, + error + ); + dispatch( + setError({ + type: 'error', + message: `Unable to connect to network ${networks[i].config.chainName}`, + }) + ); } } - if ( - data.walletName !== 'metamask' && - Object.keys(chainInfos).length === 0 - ) { + if (Object.keys(chainInfos).length === 0) { dispatch( setError({ type: 'error', @@ -186,27 +141,89 @@ export const establishWalletConnection = createAsyncThunk( ); return rejectWithValue('Permission denied for all the networks'); } else { - if (data.walletName !== 'metamask') { - setConnected(); - setWalletName(data.walletName); + setConnected(); + setWalletName(data.walletName); + + const cosmosAddress = getAddressByPrefix(anyNetworkAddress, 'cosmos'); + const authzMode = getAuthzMode(cosmosAddress); + if (authzMode.isAuthzModeOn) + dispatch(enableAuthzMode({ address: authzMode.authzAddress })); + const feegrantMode = getFeegrantMode(cosmosAddress); + if (feegrantMode.isFeegrantModeOn) + dispatch( + enableFeegrantMode({ address: feegrantMode.feegrantAddress }) + ); - const cosmosAddress = getAddressByPrefix(anyNetworkAddress, 'cosmos'); - const authzMode = getAuthzMode(cosmosAddress); - if (authzMode.isAuthzModeOn) - dispatch(enableAuthzMode({ address: authzMode.authzAddress })); - const feegrantMode = getFeegrantMode(cosmosAddress); - if (feegrantMode.isFeegrantModeOn) - dispatch( - enableFeegrantMode({ address: feegrantMode.feegrantAddress }) - ); + return fulfillWithValue({ + chainInfos, + nameToChainIDs, + walletName, + isNanoLedger, + }); + } + } + } +); - return fulfillWithValue({ - chainInfos, - nameToChainIDs, - walletName, - isNanoLedger, - }); +export const establishMetamaskConnection = createAsyncThunk( + 'wallet/metamask-connection', + async ( + data: { + network: Network; + walletName: string; + }, + { rejectWithValue, dispatch } + ) => { + if (!isWalletInstalled(data.walletName)) { + dispatch(setError({ type: 'error', message: 'Wallet is not installed' })); + return rejectWithValue('wallet is not installed'); + } else { + window.wallet.defaultOptions = { + sign: { + preferNoSetMemo: true, + disableBalanceCheck: true, + }, + }; + const chainId = data.network.config.chainId; + try { + await window.wallet.enable(chainId); + } catch (error) { + console.log('caught', error); + } + + try { + if (NotSupportedMetamaskChainIds.indexOf(chainId) === -1) { + const walletInfo = await getKey(chainId); + const chainInfo: ChainInfo = { + walletInfo: { + algo: walletInfo?.algo, + bech32Address: walletInfo?.address, + pubKey: Buffer.from(walletInfo?.pubkey).toString('base64'), + isKeystone: '', + isNanoLedger: false, + name: walletInfo?.address || '', + }, + network: data.network, + }; + + setConnected(); + setWalletName(data.walletName); + dispatch(addChainInfo({ chainId, chainInfo })); + dispatch( + addNameToChainIDs({ + chainName: data.network.config.chainName + .toLowerCase() + .split(' ') + .join(''), + chainId, + }) + ); } + } catch (error) { + console.log( + `unable to connect to network ${data.network.config.chainName}: `, + error + ); } } } @@ -247,7 +264,7 @@ const walletSlice = createSlice({ action: PayloadAction<{ chainId: string; chainInfo: ChainInfo }> ) => { const { chainId, chainInfo } = action.payload; - state.networks[chainId] = chainInfo; + state.networks = { ...state.networks, [chainId]: chainInfo }; state.connected = true; state.isLoading = false; state.status = TxStatus.IDLE; @@ -264,7 +281,7 @@ const walletSlice = createSlice({ action: PayloadAction<{ chainName: string; chainId: string }> ) => { const { chainName, chainId } = action.payload; - state.nameToChainIDs[chainName] = chainId; + state.nameToChainIDs = { ...state.nameToChainIDs, [chainName]: chainId }; }, }, extraReducers: (builder) => { diff --git a/frontend/src/utils/constants.ts b/frontend/src/utils/constants.ts index 04004ce06..a40821839 100644 --- a/frontend/src/utils/constants.ts +++ b/frontend/src/utils/constants.ts @@ -19,6 +19,11 @@ export const SUPPORTED_WALLETS = [ } ]; +export const NotSupportedMetamaskChainIds = [ + 'agoric-3', + 'evmos_9001-2', + 'desmos-mainnet', +]; export const USD_CURRENCY = 'usd'; export const GAS_FEE = 860000; export const ADD_NETWORK_TEMPLATE_URL =