Skip to content

Commit

Permalink
feat(wallets): reapply "feat(wallets): add metaMask SDK connector (#5028
Browse files Browse the repository at this point in the history
)" (#5215) (#5223)

* Reapply "feat(wallets): add metaMask SDK connector (#5028)" (#5215)

This reverts commit 889b78e.

* chore: update MetaMask SDK to 0.31.4

---------

Co-authored-by: Leandro <[email protected]>
  • Loading branch information
EdouardBougon and alfetopito authored Dec 19, 2024
1 parent 1626a04 commit 28fcda9
Show file tree
Hide file tree
Showing 12 changed files with 681 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import { isMobile, isInjectedWidget } from '@cowprotocol/common-utils'
import {
CoinbaseWalletOption,
InjectedOption as DefaultInjectedOption,
InstallMetaMaskOption,
OpenMetaMaskMobileOption,
MetaMaskSdkOption,
TrezorOption,
WalletConnectV2Option,
getIsInjected,
Expand All @@ -31,14 +30,17 @@ export function ConnectWalletOptions({ tryActivation }: { tryActivation: TryActi

const connectionProps = { darkMode, selectedWallet, tryActivation }

const metaMaskSdkOption = <MetaMaskSdkOption {...connectionProps} />
const coinbaseWalletOption = (!hasCoinbaseEip6963 && <CoinbaseWalletOption {...connectionProps} />) ?? null
const walletConnectionV2Option =
((!isInjectedMobileBrowser || isWidget) && <WalletConnectV2Option {...connectionProps} />) ?? null
const trezorOption = (!isInjectedMobileBrowser && !isMobile && <TrezorOption {...connectionProps} />) ?? null
const injectedOption = (getIsInjected() && <InjectedOptions connectionProps={connectionProps} multiInjectedProviders={multiInjectedProviders} />) ?? null

return (
<>
<InjectedOptions connectionProps={connectionProps} multiInjectedProviders={multiInjectedProviders} />
{injectedOption}
{metaMaskSdkOption}
{walletConnectionV2Option}
{coinbaseWalletOption}
{trezorOption}
Expand All @@ -57,19 +59,13 @@ interface InjectedOptionsProps {
}

function InjectedOptions({ connectionProps, multiInjectedProviders }: InjectedOptionsProps) {
const isInjected = getIsInjected()

if (!isInjected) {
if (!isMobile) {
return <InstallMetaMaskOption />
} else {
return <OpenMetaMaskMobileOption />
}
} else {
if (multiInjectedProviders.length) {
return (
<>
{multiInjectedProviders.map((providerInfo) => {
if (multiInjectedProviders.length) {
return (
<>
{multiInjectedProviders
// Even if we detect the MetaMask Extension, we prefer to use the MetaMask SDK
.filter((providerInfo) => !providerInfo.info.rdns.startsWith('io.metamask'))
.map((providerInfo) => {
return (
<Eip6963Option
key={providerInfo.info.rdns}
Expand All @@ -80,10 +76,9 @@ function InjectedOptions({ connectionProps, multiInjectedProviders }: InjectedOp
/>
)
})}
</>
)
}

return <DefaultInjectedOption {...connectionProps} />
</>
)
}

return <DefaultInjectedOption {...connectionProps} />
}
2 changes: 1 addition & 1 deletion libs/wallet/src/api/state/multiInjectedProvidersAtom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ window.addEventListener('eip6963:announceProvider', (event: Event) => {

jotaiStore.set(multiInjectedProvidersAtom, (prev: EIP6963ProviderDetail[]) => {
const newProvider = providerEvent.detail
const existingProvider = prev.find((p) => p.info.rdns === newProvider.info.uuid)
const existingProvider = prev.find((p) => p.info.rdns === newProvider.info.rdns)

if (existingProvider) return prev

Expand Down
1 change: 1 addition & 0 deletions libs/wallet/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export enum ConnectionType {
INJECTED = 'INJECTED',
WALLET_CONNECT_V2 = 'WALLET_CONNECT_V2',
COINBASE_WALLET = 'COINBASE_WALLET',
METAMASK = 'METAMASK',
GNOSIS_SAFE = 'GNOSIS_SAFE',
TREZOR = 'TREZOR',
}
Expand Down
3 changes: 3 additions & 0 deletions libs/wallet/src/api/utils/connection.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { isMobile } from '@cowprotocol/common-utils'

import { default as MetamaskImage } from '../../api/assets/metamask.png'
import CoinbaseWalletIcon from '../assets/coinbase.svg'
import TrezorIcon from '../assets/trezor.svg'
import WalletConnectIcon from '../assets/walletConnectIcon.svg'
import { ConnectionType } from '../types'

const connectionTypeToName: Record<ConnectionType, string> = {
[ConnectionType.INJECTED]: 'Injected',
[ConnectionType.METAMASK]: 'MetaMask',
[ConnectionType.COINBASE_WALLET]: 'Coinbase Wallet',
[ConnectionType.WALLET_CONNECT_V2]: 'WalletConnect',
[ConnectionType.NETWORK]: 'Network',
Expand All @@ -18,6 +20,7 @@ const IDENTICON_KEY = 'Identicon'

const connectionTypeToIcon: Record<ConnectionType, 'Identicon' | string> = {
[ConnectionType.INJECTED]: IDENTICON_KEY,
[ConnectionType.METAMASK]: MetamaskImage,
[ConnectionType.GNOSIS_SAFE]: IDENTICON_KEY,
[ConnectionType.NETWORK]: IDENTICON_KEY,
[ConnectionType.COINBASE_WALLET]: CoinbaseWalletIcon,
Expand Down
3 changes: 1 addition & 2 deletions libs/wallet/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,14 @@ export { walletConnectConnectionV2 } from './web3-react/connection/walletConnect
// Connect options
export {
InjectedOption,
InstallMetaMaskOption,
OpenMetaMaskMobileOption,
Eip6963Option,
} from './web3-react/connection/injectedOptions'

export { ConnectWalletOption } from './api/pure/ConnectWalletOption'
export { TrezorOption } from './web3-react/connection/trezor'
export { WalletConnectV2Option } from './web3-react/connection/walletConnectV2'
export { CoinbaseWalletOption } from './web3-react/connection/coinbase'
export { MetaMaskSdkOption } from './web3-react/connection/metaMaskSdk'

// State
// TODO: this export is discussable, however it's already used outside
Expand Down
30 changes: 0 additions & 30 deletions libs/wallet/src/web3-react/connection/injectedOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,13 @@ import { useCallback } from 'react'
import { injectedWalletConnection } from './injectedWallet'

import { default as InjectedImage, default as InjectedImageDark } from '../../api/assets/arrow-right.svg'
import { default as MetamaskImage } from '../../api/assets/metamask.png'
import { useSelectedEip6963ProviderRdns, useSetEip6963Provider } from '../../api/hooks'
import { ConnectWalletOption } from '../../api/pure/ConnectWalletOption'
import { ConnectionType, type EIP1193Provider, EIP6963ProviderDetail } from '../../api/types'
import { getConnectionName } from '../../api/utils/connection'
import { useIsActiveConnection } from '../hooks/useIsActiveConnection'
import { ConnectionOptionProps, TryActivation } from '../types'

const METAMASK_DEEP_LINK = 'https://metamask.app.link/dapp/'

const metamaskCommonOption = {
color: '#E8831D',
icon: MetamaskImage,
id: 'metamask',
}

const injectedCommon = {
color: '#010101',
id: 'injected',
Expand All @@ -33,27 +24,6 @@ export const injectedOptionDark = {
icon: InjectedImageDark,
}

export const metamaskInstallOption = {
...metamaskCommonOption,
header: 'Install MetaMask',
link: 'https://metamask.io/',
}

export const metamaskInjectedOption = {
...metamaskCommonOption,
header: 'MetaMask',
}

export function InstallMetaMaskOption() {
return <ConnectWalletOption {...metamaskInstallOption} />
}

export function OpenMetaMaskMobileOption() {
return (
<ConnectWalletOption {...metamaskInjectedOption} header="MetaMask" link={METAMASK_DEEP_LINK + window.location} />
)
}

export function InjectedOption({ darkMode, tryActivation, selectedWallet }: ConnectionOptionProps) {
const options = darkMode ? injectedOptionDark : injectedOption

Expand Down
54 changes: 54 additions & 0 deletions libs/wallet/src/web3-react/connection/metaMaskSdk.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { RPC_URLS } from '@cowprotocol/common-const'
import { initializeConnector } from '@web3-react/core'

import { onError } from './onError'

import { default as MetamaskImage } from '../../api/assets/metamask.png'
import { ConnectWalletOption } from '../../api/pure/ConnectWalletOption'
import { ConnectionType } from '../../api/types'
import { getConnectionName } from '../../api/utils/connection'
import { MetaMaskSDK } from '../connectors/metaMaskSdk'
import { useIsActiveConnection } from '../hooks/useIsActiveConnection'
import { ConnectionOptionProps, Web3ReactConnection } from '../types'

const metaMaskOption = {
color: '#E8831D',
icon: MetamaskImage,
id: 'metamask',
}

const [web3MetaMask, web3MetaMaskHooks] = initializeConnector<MetaMaskSDK>(
(actions) =>
new MetaMaskSDK({
actions,
options: {
dappMetadata: {
name: 'CoW Swap',
url: 'https://swap.cow.fi',
},
readonlyRPCMap: Object.fromEntries(
Object.entries(RPC_URLS).map(([chainId, url]) => [`0x${Number(chainId).toString(16)}`, url]),
),
},
onError,
}),
)

export const metaMaskSdkConnection: Web3ReactConnection = {
connector: web3MetaMask,
hooks: web3MetaMaskHooks,
type: ConnectionType.METAMASK,
}

export function MetaMaskSdkOption({ tryActivation, selectedWallet }: ConnectionOptionProps) {
const isActive = useIsActiveConnection(selectedWallet, metaMaskSdkConnection)

return (
<ConnectWalletOption
{...metaMaskOption}
isActive={isActive}
onClick={() => tryActivation(metaMaskSdkConnection.connector)}
header={getConnectionName(ConnectionType.METAMASK)}
/>
)
}
Loading

0 comments on commit 28fcda9

Please sign in to comment.