Commit 1929d165 authored by tom's avatar tom

add support for coinbase provider

parent fbe02374
import type { MetaMaskInpageProvider } from '@metamask/providers';
import type { ExternalProvider } from 'types/client/wallets';
type CPreferences = {
zone: string;
......@@ -7,8 +7,10 @@ type CPreferences = {
}
declare global {
interface Window {
ethereum: MetaMaskInpageProvider;
export interface Window {
ethereum?: {
providers?: Array<ExternalProvider>;
};
coinzilla_display: Array<CPreferences>;
}
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2500 2500">
<rect fill="none"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#0052FF" d="M520.7 0h1458.5C2266.9 0 2500 250.8 2500 560.2v1379.6c0 309.4-233.1 560.2-520.7 560.2H520.7C233.1 2500 0 2249.2 0 1939.8V560.2C0 250.8 233.1 0 520.7 0z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFF" d="M1250 362.1c490.4 0 887.9 397.5 887.9 887.9s-397.5 887.9-887.9 887.9-887.9-397.5-887.9-887.9S759.6 362.1 1250 362.1z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#0052FF" d="M1031.3 966.2h437.3c36 0 65.1 31.4 65.1 70v427.5c0 38.7-29.2 70-65.1 70h-437.3c-36 0-65.1-31.4-65.1-70v-427.5c0-38.6 29.2-70 65.1-70z"/>
</svg>
import React from 'react';
import type { ExternalProvider } from 'types/client/wallets';
import appConfig from 'configs/app/config';
export default function useProvider() {
const [ provider, setProvider ] = React.useState<ExternalProvider>();
React.useEffect(() => {
if (!('ethereum' in window)) {
return;
}
window.ethereum?.providers?.forEach(async(provider) => {
if (appConfig.web3.defaultWallet === 'coinbase' && provider.isCoinbaseWallet) {
return setProvider(provider);
}
if (appConfig.web3.defaultWallet === 'metamask' && provider.isMetaMask) {
return setProvider(provider);
}
});
}, []);
return provider;
}
......@@ -2,3 +2,17 @@ export const SUPPORTED_WALLETS = [
'metamask' as const,
'coinbase' as const,
];
import coinbaseIcon from 'icons/wallets/coinbase.svg';
import metamaskIcon from 'icons/wallets/metamask.svg';
export const WALLETS_INFO = {
metamask: {
add_token_text: 'Add token to MetaMask',
icon: metamaskIcon,
},
coinbase: {
add_token_text: 'Add token to Coinbase Wallet',
icon: coinbaseIcon,
},
};
import type { providers } from 'ethers';
import type { ArrayElement } from 'types/utils';
import type { SUPPORTED_WALLETS } from 'lib/web3/wallets';
export type WalletType = ArrayElement<typeof SUPPORTED_WALLETS>;
export interface ExternalProvider extends providers.ExternalProvider {
isCoinbaseWallet?: boolean;
// have to patch ethers here, since params could be not only an array
// eslint-disable-next-line @typescript-eslint/no-explicit-any
request?: (request: { method: string; params?: any }) => Promise<any>;
}
import type { MetaMaskInpageProvider } from '@metamask/providers';
import { test, expect } from '@playwright/experimental-ct-react';
import type { UseQueryResult } from '@tanstack/react-query';
import React from 'react';
......@@ -73,7 +72,9 @@ test('token', async({ mount, page }) => {
}), { times: 1 });
await page.evaluate(() => {
window.ethereum = { } as MetaMaskInpageProvider;
window.ethereum = {
providers: [ { isMetaMask: true } ],
};
});
const component = await mount(
......
......@@ -3,8 +3,10 @@ import React from 'react';
import type { TokenInfo } from 'types/api/token';
import metamaskIcon from 'icons/metamask.svg';
import appConfig from 'configs/app/config';
import useToast from 'lib/hooks/useToast';
import useProvider from 'lib/web3/useProvider';
import { WALLETS_INFO } from 'lib/web3/wallets';
interface Props {
className?: string;
......@@ -14,9 +16,11 @@ interface Props {
const AddressAddToWallet = ({ className, token }: Props) => {
const toast = useToast();
const provider = useProvider();
const handleClick = React.useCallback(async() => {
try {
const wasAdded = await window.ethereum.request?.({
const wasAdded = await provider?.request?.({
method: 'wallet_watchAsset',
params: {
type: 'ERC20', // Initially only supports ERC20, but eventually more!
......@@ -24,6 +28,8 @@ const AddressAddToWallet = ({ className, token }: Props) => {
address: token.address,
symbol: token.symbol,
decimals: Number(token.decimals) || 18,
// TODO: add token image when we have it in API
// image: ''
},
},
});
......@@ -32,7 +38,7 @@ const AddressAddToWallet = ({ className, token }: Props) => {
toast({
position: 'top-right',
title: 'Success',
description: 'Successfully added token to MetaMask',
description: 'Successfully added token to your wallet',
status: 'success',
variant: 'subtle',
isClosable: true,
......@@ -48,16 +54,18 @@ const AddressAddToWallet = ({ className, token }: Props) => {
isClosable: true,
});
}
}, [ toast, token ]);
}, [ toast, token, provider ]);
if (!('ethereum' in window)) {
if (!provider) {
return null;
}
const defaultWallet = appConfig.web3.defaultWallet;
return (
<Tooltip label="Add token to MetaMask">
<Tooltip label={ WALLETS_INFO[defaultWallet].add_token_text }>
<Box className={ className } display="inline-flex" cursor="pointer" onClick={ handleClick }>
<Icon as={ metamaskIcon } boxSize={ 6 }/>
<Icon as={ WALLETS_INFO[defaultWallet].icon } boxSize={ 6 }/>
</Box>
</Tooltip>
);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment