chore(web3): wallet connect v2
This commit is contained in:
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export const PROJECT_ID = 'fe8091dc35738863e509fc4947525c72';
|
||||
@@ -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';
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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 })),
|
||||
}));
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user