chore: move token's web3 url connector to web3 lib (#2655)

Co-authored-by: Dexter <dexter.edwards93@gmail.com>
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
This commit is contained in:
Art 2023-01-24 15:02:17 +01:00 committed by GitHub
parent 0cff5895c7
commit 165b131b27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 149 additions and 84 deletions

View File

@ -3,16 +3,17 @@ 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 { Url } from './url-connector';
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)
);
const [urlConnector, urlHooks] = initializeConnector<Url>(
(actions) => new Url(actions, ENV.localProviderUrl)
const [urlConnector, urlHooks] = initializeConnector<UrlConnector>(
(actions) =>
new UrlConnector(actions, ENV.localProviderUrl, ENV.ethWalletMnemonic)
);
export const createDefaultProvider = (providerUrl: string, chainId: number) => {

View File

@ -9,6 +9,8 @@ NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_WALLET_URL=http://localhost:1789
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
# Expose some env vars to cypress environment for market setup
CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session

View File

@ -9,6 +9,8 @@ NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_WALLET_URL=http://localhost:1789
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
# Expose some env vars to cypress environment for market setup
CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session

View File

@ -9,3 +9,6 @@ NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"

View File

@ -28,7 +28,8 @@ export function AppLoader({ children }: AppLoaderProps) {
export const Web3Provider = ({ children }: { children: ReactNode }) => {
const { config, loading, error } = useEthereumConfig();
const { ETHEREUM_PROVIDER_URL } = useEnvironment();
const { ETHEREUM_PROVIDER_URL, ETH_LOCAL_PROVIDER_URL, ETH_WALLET_MNEMONIC } =
useEnvironment();
const [connectors, initializeConnectors] = useWeb3ConnectStore((store) => [
store.connectors,
store.initialize,
@ -37,11 +38,22 @@ export const Web3Provider = ({ children }: { children: ReactNode }) => {
useEffect(() => {
if (config?.chain_id) {
return initializeConnectors(
createConnectors(ETHEREUM_PROVIDER_URL, Number(config?.chain_id)),
createConnectors(
ETHEREUM_PROVIDER_URL,
Number(config?.chain_id),
ETH_LOCAL_PROVIDER_URL,
ETH_WALLET_MNEMONIC
),
Number(config.chain_id)
);
}
}, [config?.chain_id, ETHEREUM_PROVIDER_URL, initializeConnectors]);
}, [
config?.chain_id,
ETHEREUM_PROVIDER_URL,
initializeConnectors,
ETH_LOCAL_PROVIDER_URL,
ETH_WALLET_MNEMONIC,
]);
return (
<AsyncRenderer

View File

@ -78,6 +78,10 @@ const getBundledEnvironmentValue = (key: EnvKey) => {
return process.env['NX_VEGA_DOCS_URL'];
case 'HOSTED_WALLET_URL':
return process.env['NX_HOSTED_WALLET_URL'];
case 'ETH_LOCAL_PROVIDER_URL':
return process.env['NX_ETH_LOCAL_PROVIDER_URL'];
case 'ETH_WALLET_MNEMONIC':
return process.env['NX_ETH_WALLET_MNEMONIC'];
case 'MAINTENANCE_PAGE':
return (
process.env['MAINTENANCE_PAGE'] || process.env['NX_MAINTENANCE_PAGE']

View File

@ -50,6 +50,8 @@ const schemaObject = {
}),
HOSTED_WALLET_URL: z.optional(z.string()),
MAINTENANCE_PAGE: z.optional(z.boolean()),
ETH_LOCAL_PROVIDER_URL: z.optional(z.string()),
ETH_WALLET_MNEMONIC: z.optional(z.string()),
};
export const ENV_KEYS = Object.keys(schemaObject) as Array<

View File

@ -20,3 +20,5 @@ export * from './lib/web3-connectors';
export * from './lib/web3-connect-dialog';
export * from './lib/web3-connect-store';
export * from './lib/web3-container';
export * from './lib/url-connector';
export * from './lib/eip-1193-custom-bridge';

View File

@ -1,12 +1,7 @@
import { ethers, Wallet } from 'ethers';
import { Connector } from '@web3-react/types';
import { Eip1193Bridge } from '@ethersproject/experimental';
import type { ConnectionInfo } from '@ethersproject/web';
import type { Actions } from '@web3-react/types';
import { ENV } from '../config/env';
import { ethers } from 'ethers';
export class CustomizedBridge extends Eip1193Bridge {
export class Eip1193CustomBridge extends Eip1193Bridge {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async sendAsync(...args: any) {
console.debug('sendAsync called', ...args);
@ -89,63 +84,3 @@ export class CustomizedBridge extends Eip1193Bridge {
}
}
}
type url = string | ConnectionInfo;
export class Url extends Connector {
/** {@inheritdoc Connector.provider} */
public override provider: Eip1193Bridge | undefined;
private eagerConnection?: Promise<void>;
private url: url;
/**
* @param url - An RPC url.
* @param connectEagerly - A flag indicating whether connection should be initiated when the class is constructed.
*/
constructor(actions: Actions, url: url, connectEagerly = false) {
super(actions);
if (connectEagerly && typeof window === 'undefined') {
throw new Error(
'connectEagerly = true is invalid for SSR, instead use the activate method in a useEffect'
);
}
this.url = url;
if (connectEagerly) void this.activate();
}
private async isomorphicInitialize() {
if (this.eagerConnection) return this.eagerConnection;
await (this.eagerConnection = import('@ethersproject/providers')
.then(({ JsonRpcProvider }) => JsonRpcProvider)
.then((JsonRpcProvider) => {
const provider = new JsonRpcProvider(this.url);
const privateKey = Wallet.fromMnemonic(
ENV.ethWalletMnemonic,
`m/44'/60'/0'/0/0`
).privateKey;
const signer = new Wallet(privateKey, provider);
this.provider = new CustomizedBridge(signer, provider);
this.actions.update({ accounts: [signer.address], chainId: 1440 });
}));
}
/** {@inheritdoc Connector.activate} */
public async activate(): Promise<void> {
this.actions.startActivation();
await this.isomorphicInitialize();
try {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const chainId = await this.provider!.request({ method: 'eth_chainId' });
this.actions.update({ chainId: Number(chainId) });
} catch (error) {
this.actions.reportError(error as Error);
}
}
}

View File

@ -0,0 +1,88 @@
import { Wallet } from 'ethers';
import { Connector } from '@web3-react/types';
import type { ConnectionInfo } from '@ethersproject/web';
import type { Actions } from '@web3-react/types';
import { initializeConnector } from '@web3-react/core';
import type { Eip1193Bridge } from '@ethersproject/experimental';
import { Eip1193CustomBridge } from './eip-1193-custom-bridge';
type url = string | ConnectionInfo;
export class UrlConnector extends Connector {
/** {@inheritdoc Connector.provider} */
public override provider: Eip1193Bridge | undefined;
private eagerConnection?: Promise<void>;
private url: url;
private ethWalletMnemonic: string;
/**
* @param url - An RPC url.
* @param connectEagerly - A flag indicating whether connection should be initiated when the class is constructed.
*/
constructor(
actions: Actions,
url: url,
ethWalletMnemonic: string,
connectEagerly = false
) {
super(actions);
if (connectEagerly && typeof window === 'undefined') {
throw new Error(
'connectEagerly = true is invalid for SSR, instead use the activate method in a useEffect'
);
}
this.url = url;
this.ethWalletMnemonic = ethWalletMnemonic;
if (connectEagerly) void this.activate();
}
private async isomorphicInitialize() {
if (this.eagerConnection) return this.eagerConnection;
await (this.eagerConnection = import('@ethersproject/providers')
.then(({ JsonRpcProvider }) => JsonRpcProvider)
.then((JsonRpcProvider) => {
const provider = new JsonRpcProvider(this.url);
const privateKey = Wallet.fromMnemonic(
this.ethWalletMnemonic,
`m/44'/60'/0'/0/0`
).privateKey;
const signer = new Wallet(privateKey, provider);
this.provider = new Eip1193CustomBridge(signer, provider);
this.actions.update({ accounts: [signer.address], chainId: 1440 });
}));
}
/** {@inheritdoc Connector.activate} */
public async activate(): Promise<void> {
this.actions.startActivation();
await this.isomorphicInitialize();
try {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const chainId = await this.provider!.request({ method: 'eth_chainId' });
this.actions.update({ chainId: Number(chainId) });
} catch (error) {
this.actions.reportError(error as Error);
}
}
}
export const initializeUrlConnector = (
localProviderUrl?: string,
walletMnemonic?: string
) =>
localProviderUrl &&
walletMnemonic &&
localProviderUrl.length > 0 &&
walletMnemonic.length > 0
? initializeConnector<UrlConnector>(
(actions) => new UrlConnector(actions, localProviderUrl, walletMnemonic)
)
: null;

View File

@ -1,6 +1,4 @@
import create from 'zustand';
import type { MetaMask } from '@web3-react/metamask';
import type { WalletConnect } from '@web3-react/walletconnect';
import type { Web3ReactHooks } from '@web3-react/core';
import type { Connector } from '@web3-react/types';
@ -10,10 +8,7 @@ interface State {
desiredChainId?: number;
}
interface Actions {
initialize: (
connectors: [MetaMask | WalletConnect, Web3ReactHooks][],
desiredChainId: number
) => void;
initialize: (connectors: State['connectors'], desiredChainId: number) => void;
open: () => void;
close: () => void;
}

View File

@ -1,9 +1,16 @@
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 { initializeUrlConnector } from './url-connector';
export const createConnectors = (providerUrl: string, chainId: number) => {
export const createConnectors = (
providerUrl: string,
chainId: number,
localProviderUrl?: string,
walletMnemonic?: string
) => {
if (isNaN(chainId)) {
throw new Error('Invalid Ethereum chain ID for environment');
}
@ -23,7 +30,8 @@ export const createConnectors = (providerUrl: string, chainId: number) => {
[chainId]
);
return [
initializeUrlConnector(localProviderUrl, walletMnemonic),
[metamask, metamaskHooks],
[walletconnect, walletconnectHooks],
] as [MetaMask | WalletConnect, Web3ReactHooks][];
].filter(Boolean) as [Connector, Web3ReactHooks][];
};

View File

@ -22,13 +22,24 @@ export const Web3Container = ({
connectEagerly,
}: Web3ContainerProps) => {
const { config, loading, error } = useEthereumConfig();
const { ETHEREUM_PROVIDER_URL } = useEnvironment();
const { ETHEREUM_PROVIDER_URL, ETH_LOCAL_PROVIDER_URL, ETH_WALLET_MNEMONIC } =
useEnvironment();
const connectors = useMemo(() => {
if (config?.chain_id) {
return createConnectors(ETHEREUM_PROVIDER_URL, Number(config?.chain_id));
return createConnectors(
ETHEREUM_PROVIDER_URL,
Number(config?.chain_id),
ETH_LOCAL_PROVIDER_URL,
ETH_WALLET_MNEMONIC
);
}
return null;
}, [config?.chain_id, ETHEREUM_PROVIDER_URL]);
}, [
config?.chain_id,
ETHEREUM_PROVIDER_URL,
ETH_LOCAL_PROVIDER_URL,
ETH_WALLET_MNEMONIC,
]);
return (
<AsyncRenderer data={config} loading={loading} error={error}>
{connectors && config && (