chore(web3): wallet connect v2

This commit is contained in:
asiaznik
2023-04-20 14:32:50 +02:00
parent 9e054c7c85
commit 88d074c67e
18 changed files with 1095 additions and 477 deletions
@@ -239,7 +239,12 @@ export const EthWallet = () => {
<div className="flex justify-end">
<button
className="underline"
onClick={() => connector.deactivate()}
onClick={() => {
if (connector.deactivate) {
connector.deactivate();
}
connector.resetState();
}}
data-testid="disconnect-from-eth-wallet-button"
>
{t('disconnect')}
@@ -1,5 +1,9 @@
import { Button, Splash } from '@vegaprotocol/ui-toolkit';
import { getChainName, Web3ConnectDialog } from '@vegaprotocol/web3';
import {
getChainName,
useWeb3ConnectStore,
Web3ConnectDialog,
} from '@vegaprotocol/web3';
import { useWeb3React } from '@web3-react/core';
import type { ReactElement } from 'react';
import { useCallback, useEffect } from 'react';
@@ -51,7 +55,11 @@ interface Web3ContentProps {
}
export const Web3Content = ({ children, appChainId }: Web3ContentProps) => {
const { error, connector, chainId } = useWeb3React();
const { connector, chainId } = useWeb3React();
const [error, clearError] = useWeb3ConnectStore((store) => [
store.error,
store.clearError,
]);
useEffect(() => {
if (connector?.connectEagerly) {
@@ -62,12 +70,20 @@ export const Web3Content = ({ children, appChainId }: Web3ContentProps) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const deactivateConnector = () => {
if (connector.deactivate) {
connector.deactivate();
}
connector.resetState();
clearError();
};
if (error) {
return (
<Splash>
<div className="flex flex-col items-center gap-12">
<p className="text-white">Something went wrong: {error.message}</p>
<Button onClick={() => connector.deactivate()}>Disconnect</Button>
<Button onClick={() => deactivateConnector()}>Disconnect</Button>
</div>
</Splash>
);
@@ -80,7 +96,7 @@ export const Web3Content = ({ children, appChainId }: Web3ContentProps) => {
<p className="text-white">
This app only works on {getChainName(appChainId)}
</p>
<Button onClick={() => connector.deactivate()}>Disconnect</Button>
<Button onClick={() => deactivateConnector()}>Disconnect</Button>
</div>
</Splash>
);
+12 -17
View File
@@ -1,15 +1,13 @@
import { ethers } from 'ethers';
import type { Web3ReactHooks } from '@web3-react/core';
import { initializeConnector } from '@web3-react/core';
import { MetaMask } from '@web3-react/metamask';
import { WalletConnect } from '@web3-react/walletconnect';
import type { Connector } from '@web3-react/types';
import { ENV } from '../config/env';
import { UrlConnector } from '@vegaprotocol/web3';
const [metamask, metamaskHooks] = initializeConnector<MetaMask>(
(actions) => new MetaMask(actions)
);
import {
initializeMetaMaskConnector,
initializeWalletConnector,
UrlConnector,
} from '@vegaprotocol/web3';
const [urlConnector, urlHooks] = initializeConnector<UrlConnector>(
(actions) =>
@@ -20,20 +18,17 @@ export const createDefaultProvider = (providerUrl: string, chainId: number) => {
return new ethers.providers.JsonRpcProvider(providerUrl, chainId);
};
const [metamask, metamaskHooks] = initializeMetaMaskConnector();
export const createConnectors = (providerUrl: string, chainId: number) => {
if (isNaN(chainId)) {
throw new Error('Invalid Ethereum chain ID for environment');
}
const [walletconnect, walletconnectHooks] =
initializeConnector<WalletConnect>(
(actions) =>
new WalletConnect(actions, {
rpc: {
[chainId]: providerUrl,
},
}),
[chainId]
);
const [walletconnect, walletconnectHooks] = initializeWalletConnector(
chainId,
providerUrl
);
return [
ENV.urlConnect ? [urlConnector, urlHooks] : null,
[metamask, metamaskHooks],
@@ -1,5 +1,9 @@
import { useEnvironment } from '@vegaprotocol/environment';
import { getChainName, useEthereumConfig } from '@vegaprotocol/web3';
import {
getChainName,
useEthereumConfig,
useWeb3ConnectStore,
} from '@vegaprotocol/web3';
import { Button, Splash, AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { Web3ConnectDialog } from '@vegaprotocol/web3';
import { useWeb3React } from '@web3-react/core';
@@ -55,7 +59,11 @@ export const Web3Content = ({
appChainId,
setDialogOpen,
}: Web3ContentProps) => {
const { error, connector, chainId } = useWeb3React();
const { connector, chainId } = useWeb3React();
const [error, clearError] = useWeb3ConnectStore((store) => [
store.error,
store.clearError,
]);
useEffect(() => {
if (connector?.connectEagerly) {
@@ -66,12 +74,20 @@ export const Web3Content = ({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [connector]);
const deactivateConnector = () => {
if (connector.deactivate) {
connector.deactivate();
}
connector.resetState();
clearError();
};
if (error) {
return (
<Splash>
<div className="flex flex-col items-center gap-12">
<p className="text-white">Something went wrong: {error.message}</p>
<Button onClick={() => connector.deactivate()}>Disconnect</Button>
<Button onClick={() => deactivateConnector()}>Disconnect</Button>
</div>
</Splash>
);
@@ -84,7 +100,7 @@ export const Web3Content = ({
<p className="text-white">
This app only works on {getChainName(appChainId)}
</p>
<Button onClick={() => connector.deactivate()}>Disconnect</Button>
<Button onClick={() => deactivateConnector()}>Disconnect</Button>
</div>
</Splash>
);
@@ -1,32 +1,25 @@
import { ethers } from 'ethers';
import type { Web3ReactHooks } from '@web3-react/core';
import { initializeConnector } from '@web3-react/core';
import { MetaMask } from '@web3-react/metamask';
import { WalletConnect } from '@web3-react/walletconnect';
import type { Connector } from '@web3-react/types';
const [metamask, metamaskHooks] = initializeConnector<MetaMask>(
(actions) => new MetaMask(actions)
);
import {
initializeMetaMaskConnector,
initializeWalletConnector,
} from '@vegaprotocol/web3';
export const createDefaultProvider = (providerUrl: string, chainId: number) => {
return new ethers.providers.JsonRpcProvider(providerUrl, chainId);
};
const [metamask, metamaskHooks] = initializeMetaMaskConnector();
export const createConnectors = (providerUrl: string, chainId: number) => {
if (isNaN(chainId)) {
throw new Error('Invalid Ethereum chain ID for environment');
}
const [walletconnect, walletconnectHooks] =
initializeConnector<WalletConnect>(
(actions) =>
new WalletConnect(actions, {
rpc: {
[chainId]: providerUrl,
},
}),
[chainId]
);
const [walletconnect, walletconnectHooks] = initializeWalletConnector(
chainId,
providerUrl
);
return [
[metamask, metamaskHooks],
[walletconnect, walletconnectHooks],
@@ -14,10 +14,9 @@ export const Web3Provider = ({ children }: { children: ReactNode }) => {
const { config, loading, error } = useEthereumConfig();
const { ETHEREUM_PROVIDER_URL, ETH_LOCAL_PROVIDER_URL, ETH_WALLET_MNEMONIC } =
useEnvironment();
const [connectors, initializeConnectors] = useWeb3ConnectStore((store) => [
store.connectors,
store.initialize,
]);
const connectors = useWeb3ConnectStore((store) => store.connectors);
const initializeConnectors = useWeb3ConnectStore((store) => store.initialize);
useEffect(() => {
if (config?.chain_id) {
+8 -1
View File
@@ -449,10 +449,17 @@ const DisconnectEthereumButton = ({
const { connector } = useWeb3React();
const [, , removeEagerConnector] = useLocalStorage(ETHEREUM_EAGER_CONNECT);
const deactivateConnector = () => {
if (connector.deactivate) {
connector.deactivate();
}
connector.resetState();
};
return (
<ButtonLink
onClick={() => {
connector.deactivate();
deactivateConnector();
removeEagerConnector();
onDisconnect();
}}
+1
View File
@@ -0,0 +1 @@
export const PROJECT_ID = 'fe8091dc35738863e509fc4947525c72';
+1
View File
@@ -21,3 +21,4 @@ export * from './lib/web3-connect-dialog';
export * from './lib/web3-connect-store';
export * from './lib/url-connector';
export * from './lib/eip-1193-custom-bridge';
export * from './constansts';
+1 -1
View File
@@ -69,7 +69,7 @@ export class UrlConnector extends Connector {
const chainId = await this.provider!.request({ method: 'eth_chainId' });
this.actions.update({ chainId: Number(chainId) });
} catch (error) {
this.actions.reportError(error as Error);
this.onError?.(error as Error);
}
}
}
+13 -5
View File
@@ -2,7 +2,7 @@ import { useLocalStorage } from '@vegaprotocol/react-helpers';
import type { Web3ReactHooks } from '@web3-react/core';
import { MetaMask } from '@web3-react/metamask';
import type { Connector } from '@web3-react/types';
import { WalletConnect } from '@web3-react/walletconnect';
import { WalletConnect } from '@web3-react/walletconnect-v2';
import { useEffect, useRef } from 'react';
import { useWeb3ConnectStore } from './web3-connect-store';
@@ -18,10 +18,18 @@ export const useEagerConnect = () => {
const stored = getConnector(connectors, eagerConnector);
// found a valid connection option
if (stored && stored[0].connectEagerly) {
stored[0].connectEagerly();
}
const tryConnectEagerly = async () => {
// found a valid connection option
if (stored && stored[0].connectEagerly) {
try {
await stored[0].connectEagerly();
} catch (err) {
// NOOP - no active session
console.log('ERR_WEB3_EAGER_CONNECT', (err as Error).message);
}
}
};
tryConnectEagerly();
attemptedRef.current = true;
}, [eagerConnector, connectors]);
+8 -4
View File
@@ -2,7 +2,7 @@ import { t } from '@vegaprotocol/i18n';
import { useLocalStorage } from '@vegaprotocol/react-helpers';
import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
import { MetaMask } from '@web3-react/metamask';
import { WalletConnect } from '@web3-react/walletconnect';
import { WalletConnect } from '@web3-react/walletconnect-v2';
import type { Connector } from '@web3-react/types';
import { ETHEREUM_EAGER_CONNECT } from './use-eager-connect';
import type { Web3ReactHooks } from '@web3-react/core';
@@ -39,9 +39,13 @@ export const Web3ConnectDialog = ({
className="hover:text-vega-pink dark:hover:text-vega-yellow underline"
data-testid={`web3-connector-${info.name}`}
onClick={async () => {
await connector.activate(desiredChainId);
setEagerConnector(info.name);
setDialogOpen(false);
try {
await connector.activate(desiredChainId);
setEagerConnector(info.name);
setDialogOpen(false);
} catch (err) {
// NOOP - cancelled wallet connector
}
}}
>
{info.text}
+3
View File
@@ -6,11 +6,13 @@ interface State {
isOpen: boolean;
connectors: [Connector, Web3ReactHooks][];
desiredChainId?: number;
error?: Error;
}
interface Actions {
initialize: (connectors: State['connectors'], desiredChainId: number) => void;
open: () => void;
close: () => void;
clearError: () => void;
}
export const useWeb3ConnectStore = create<State & Actions>()((set) => ({
@@ -21,4 +23,5 @@ export const useWeb3ConnectStore = create<State & Actions>()((set) => ({
},
open: () => set(() => ({ isOpen: true })),
close: () => set(() => ({ isOpen: false })),
clearError: () => set(() => ({ error: undefined })),
}));
+43 -13
View File
@@ -2,8 +2,47 @@ import type { Web3ReactHooks } from '@web3-react/core';
import { initializeConnector } from '@web3-react/core';
import type { Connector } from '@web3-react/types';
import { MetaMask } from '@web3-react/metamask';
import { WalletConnect } from '@web3-react/walletconnect';
import { WalletConnect } from '@web3-react/walletconnect-v2';
import { initializeUrlConnector } from './url-connector';
import { PROJECT_ID } from '../constansts';
import { useWeb3ConnectStore } from './web3-connect-store';
export const initializeWalletConnector = (
chainId: number,
providerUrl: string
) =>
initializeConnector<WalletConnect>(
(actions) =>
new WalletConnect({
actions,
options: {
projectId: PROJECT_ID,
chains: [chainId],
showQrModal: true,
rpcMap: {
[chainId]: providerUrl,
},
},
onError: (error) => {
console.log('ERR_WALLET_CONNECT', error.message);
useWeb3ConnectStore.setState({ error });
},
})
);
export const initializeMetaMaskConnector = () =>
initializeConnector<MetaMask>(
(actions) =>
new MetaMask({
actions,
onError: (error) => {
console.log('ERR_META_MASK', error.message);
useWeb3ConnectStore.setState({ error });
},
})
);
const [metamask, metamaskHooks] = initializeMetaMaskConnector();
export const createConnectors = (
providerUrl: string,
@@ -15,20 +54,11 @@ export const createConnectors = (
throw new Error('Invalid Ethereum chain ID for environment');
}
const [metamask, metamaskHooks] = initializeConnector<MetaMask>(
(actions) => new MetaMask(actions)
const [walletconnect, walletconnectHooks] = initializeWalletConnector(
chainId,
providerUrl
);
const [walletconnect, walletconnectHooks] =
initializeConnector<WalletConnect>(
(actions) =>
new WalletConnect(actions, {
rpc: {
[chainId]: providerUrl,
},
}),
[chainId]
);
return [
initializeUrlConnector(localProviderUrl, walletMnemonic),
[metamask, metamaskHooks],
+9 -1
View File
@@ -1,6 +1,7 @@
import type { Web3ReactHooks } from '@web3-react/core';
import { Web3ReactProvider } from '@web3-react/core';
import type { Connector } from '@web3-react/types';
import { useMemo } from 'react';
interface Web3ProviderProps {
children: JSX.Element | JSX.Element[];
@@ -8,7 +9,14 @@ interface Web3ProviderProps {
}
export const Web3Provider = ({ children, connectors }: Web3ProviderProps) => {
const key = useMemo(
() => `WEB3_PROVIDER_${Date.now().toString()}`,
[connectors]
);
return (
<Web3ReactProvider connectors={connectors}>{children}</Web3ReactProvider>
<Web3ReactProvider key={key} connectors={connectors}>
{children}
</Web3ReactProvider>
);
};
+4 -1
View File
@@ -310,7 +310,10 @@ const EthereumButton = ({ clearAddress }: { clearAddress: () => void }) => {
return (
<UseButton
onClick={() => {
connector.deactivate();
if (connector.deactivate) {
connector.deactivate();
}
connector.resetState();
clearAddress();
removeEagerConnector();
}}
+4 -4
View File
@@ -37,10 +37,10 @@
"@sentry/react": "^6.19.2",
"@sentry/tracing": "^6.19.2",
"@vegaprotocol/wallet-client": "0.1.9",
"@walletconnect/ethereum-provider": "^1.7.5",
"@web3-react/core": "8.0.20-beta.0",
"@web3-react/metamask": "8.0.16-beta.0",
"@web3-react/walletconnect": "^8.0.23-beta.0",
"@walletconnect/ethereum-provider": "^2.5.2",
"@web3-react/core": "^8.1.2-beta.0",
"@web3-react/metamask": "^8.1.2-beta.0",
"@web3-react/walletconnect-v2": "^8.1.3-beta.0",
"ag-grid-community": "^27.0.1",
"ag-grid-react": "^27.0.1",
"allotment": "1.18.1",
+929 -400
View File
File diff suppressed because it is too large Load Diff