chore(2351): improve handling wallet errors (#2729)

This commit is contained in:
macqbat 2023-01-27 15:45:29 +01:00 committed by GitHub
parent b68c090ee5
commit 853ec8f69c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 126 additions and 108 deletions

View File

@ -9,6 +9,7 @@ import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing';
import { VegaWalletProvider } from '../provider'; import { VegaWalletProvider } from '../provider';
import { VegaConnectDialog, CLOSE_DELAY } from './connect-dialog'; import { VegaConnectDialog, CLOSE_DELAY } from './connect-dialog';
import type { VegaWalletDialogStore } from './connect-dialog';
import type { VegaConnectDialogProps } from '..'; import type { VegaConnectDialogProps } from '..';
import { import {
ClientErrors, ClientErrors,
@ -23,13 +24,15 @@ import { ChainIdDocument } from '@vegaprotocol/react-helpers';
const mockUpdateDialogOpen = jest.fn(); const mockUpdateDialogOpen = jest.fn();
const mockCloseVegaDialog = jest.fn(); const mockCloseVegaDialog = jest.fn();
const mockStoreObj: Partial<VegaWalletDialogStore> = {
updateVegaWalletDialog: mockUpdateDialogOpen,
closeVegaWalletDialog: mockCloseVegaDialog,
vegaWalletDialogOpen: true,
};
jest.mock('zustand', () => ({ jest.mock('zustand', () => ({
create: () => () => ({ create: () => (storeGetter: (store: VegaWalletDialogStore) => unknown) =>
updateVegaWalletDialog: mockUpdateDialogOpen, storeGetter(mockStoreObj as VegaWalletDialogStore),
closeVegaWalletDialog: mockCloseVegaDialog,
vegaWalletDialogOpen: true,
}),
})); }));
let defaultProps: VegaConnectDialogProps; let defaultProps: VegaConnectDialogProps;
@ -301,7 +304,9 @@ describe('VegaConnectDialog', () => {
spyOnConnectWallet spyOnConnectWallet
.mockClear() .mockClear()
.mockImplementation(() => .mockImplementation(() =>
delayedReject(new WalletError('message', 3001, 'data')) delayedReject(
new WalletError('User error', 3001, 'The user rejected the request')
)
); );
render(generateJSX()); render(generateJSX());
@ -322,9 +327,9 @@ describe('VegaConnectDialog', () => {
await act(async () => { await act(async () => {
jest.advanceTimersByTime(delay); jest.advanceTimersByTime(delay);
}); });
expect(screen.getByText('Connection declined')).toBeInTheDocument(); expect(screen.getByText('User error')).toBeInTheDocument();
expect( expect(
screen.getByText('Your wallet connection was rejected') screen.getByText('The user rejected the request')
).toBeInTheDocument(); ).toBeInTheDocument();
}); });

View File

@ -9,8 +9,9 @@ import {
Loader, Loader,
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
import type { WalletClientError } from '@vegaprotocol/wallet-client';
import { ExternalLinks, t, useChainIdQuery } from '@vegaprotocol/react-helpers'; import { ExternalLinks, t, useChainIdQuery } from '@vegaprotocol/react-helpers';
import type { VegaConnector, WalletError } from '../connectors'; import type { VegaConnector } from '../connectors';
import { ViewConnector } from '../connectors'; import { ViewConnector } from '../connectors';
import { JsonRpcConnector, RestConnector } from '../connectors'; import { JsonRpcConnector, RestConnector } from '../connectors';
import { RestConnectorForm } from './rest-connector-form'; import { RestConnectorForm } from './rest-connector-form';
@ -44,7 +45,7 @@ export const useVegaWalletDialogStore = create<VegaWalletDialogStore>(
}) })
); );
interface VegaWalletDialogStore { export interface VegaWalletDialogStore {
vegaWalletDialogOpen: boolean; vegaWalletDialogOpen: boolean;
updateVegaWalletDialog: (open: boolean) => void; updateVegaWalletDialog: (open: boolean) => void;
openVegaWalletDialog: () => void; openVegaWalletDialog: () => void;
@ -55,25 +56,25 @@ export const VegaConnectDialog = ({
connectors, connectors,
onChangeOpen, onChangeOpen,
}: VegaConnectDialogProps) => { }: VegaConnectDialogProps) => {
const { const vegaWalletDialogOpen = useVegaWalletDialogStore(
vegaWalletDialogOpen, (store) => store.vegaWalletDialogOpen
closeVegaWalletDialog, );
updateVegaWalletDialog, const updateVegaWalletDialog = useVegaWalletDialogStore((store) =>
} = useVegaWalletDialogStore((store) => ({ onChangeOpen
vegaWalletDialogOpen: store.vegaWalletDialogOpen,
updateVegaWalletDialog: onChangeOpen
? (open: boolean) => { ? (open: boolean) => {
store.updateVegaWalletDialog(open); store.updateVegaWalletDialog(open);
onChangeOpen(open); onChangeOpen(open);
} }
: store.updateVegaWalletDialog, : store.updateVegaWalletDialog
closeVegaWalletDialog: onChangeOpen );
const closeVegaWalletDialog = useVegaWalletDialogStore((store) =>
onChangeOpen
? () => { ? () => {
store.closeVegaWalletDialog(); store.closeVegaWalletDialog();
onChangeOpen(false); onChangeOpen(false);
} }
: store.closeVegaWalletDialog, : store.closeVegaWalletDialog
})); );
const { data, error, loading } = useChainIdQuery(); const { data, error, loading } = useChainIdQuery();
@ -254,7 +255,7 @@ const SelectedForm = ({
appChainId: string; appChainId: string;
jsonRpcState: { jsonRpcState: {
status: Status; status: Status;
error: WalletError | null; error: WalletClientError | null;
}; };
reset: () => void; reset: () => void;
onConnect: () => void; onConnect: () => void;

View File

@ -8,16 +8,15 @@ import {
Tick, Tick,
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import type { WalletClientError } from '@vegaprotocol/wallet-client';
import type { JsonRpcConnector } from '../connectors'; import type { JsonRpcConnector } from '../connectors';
import { ClientErrors } from '../connectors'; import { ClientErrors } from '../connectors';
import type { WalletError } from '../connectors';
import { ConnectDialogTitle } from './connect-dialog-elements'; import { ConnectDialogTitle } from './connect-dialog-elements';
import { Status } from '../use-json-rpc-connect'; import { Status } from '../use-json-rpc-connect';
import { useEnvironment } from '@vegaprotocol/environment'; import { useEnvironment } from '@vegaprotocol/environment';
export const ServiceErrors = { export const ServiceErrors = {
NO_HEALTHY_NODE: 1000, NO_HEALTHY_NODE: 1000,
CONNECTION_DECLINED: 3001,
REQUEST_PROCESSING: -32000, REQUEST_PROCESSING: -32000,
}; };
@ -31,7 +30,7 @@ export const JsonRpcConnectorForm = ({
connector: JsonRpcConnector; connector: JsonRpcConnector;
appChainId: string; appChainId: string;
status: Status; status: Status;
error: WalletError | null; error: WalletClientError | null;
onConnect: () => void; onConnect: () => void;
reset: () => void; reset: () => void;
}) => { }) => {
@ -58,7 +57,7 @@ const Connecting = ({
reset, reset,
}: { }: {
status: Status; status: Status;
error: WalletError | null; error: WalletClientError | null;
connector: JsonRpcConnector; connector: JsonRpcConnector;
appChainId: string; appChainId: string;
reset: () => void; reset: () => void;
@ -141,7 +140,7 @@ const Error = ({
appChainId, appChainId,
onTryAgain, onTryAgain,
}: { }: {
error: WalletError | null; error: WalletClientError | null;
connectorUrl: string | null; connectorUrl: string | null;
appChainId: string; appChainId: string;
onTryAgain: () => void; onTryAgain: () => void;
@ -158,18 +157,20 @@ const Error = ({
if (error) { if (error) {
if (error.code === ClientErrors.NO_SERVICE.code) { if (error.code === ClientErrors.NO_SERVICE.code) {
title = t('No wallet detected'); title = t('No wallet detected');
text = t(`No wallet application running at ${connectorUrl}`); text = connectorUrl
? t('No wallet application running at %s', connectorUrl)
: t('No Vega Wallet application running');
} else if (error.code === ClientErrors.WRONG_NETWORK.code) { } else if (error.code === ClientErrors.WRONG_NETWORK.code) {
title = t('Wrong network'); title = t('Wrong network');
text = `To complete your wallet connection, set your wallet network in your app to "${appChainId}".`; text = t(
} else if (error.code === ServiceErrors.CONNECTION_DECLINED) { 'To complete your wallet connection, set your wallet network in your app to "%s".',
title = t('Connection declined'); appChainId
text = t('Your wallet connection was rejected'); );
} else if (error.code === ServiceErrors.NO_HEALTHY_NODE) { } else if (error.code === ServiceErrors.NO_HEALTHY_NODE) {
title = error.message; title = error.title;
text = ( text = (
<> <>
{capitalize(error.data)} {capitalize(error.message)}
{'. '} {'. '}
{VEGA_DOCS_URL && ( {VEGA_DOCS_URL && (
<Link <Link
@ -188,20 +189,33 @@ const Error = ({
title = t('Wrong network'); title = t('Wrong network');
text = ( text = (
<> <>
{t(`To complete your wallet connection, set your wallet network in your {t(
app to ${appChainId}.`)} `To complete your wallet connection, set your wallet network in your
app to %s.`,
appChainId
)}
</> </>
); );
} else if (error.code === ClientErrors.INVALID_WALLET.code) {
title = error.title;
const errorData = error.message?.split('\n ') || [];
text = (
<span className="flex flex-col">
{errorData.map((str, i) => (
<span key={i}>{str}</span>
))}
</span>
);
} else { } else {
title = error.message; title = t(error.title);
text = `${error.data} (${error.code})`; text = t(error.message);
} }
} }
return ( return (
<> <>
<ConnectDialogTitle>{title}</ConnectDialogTitle> <ConnectDialogTitle>{title}</ConnectDialogTitle>
<p className="text-center mb-2">{text}</p> <p className="text-center mb-2 first-letter:uppercase">{text}</p>
{tryAgain} {tryAgain}
</> </>
); );

View File

@ -8,8 +8,6 @@ const VERSION = 'v2';
export const ClientErrors = { export const ClientErrors = {
NO_SERVICE: new WalletError(t('No service'), 100), NO_SERVICE: new WalletError(t('No service'), 100),
NO_TOKEN: new WalletError(t('No token'), 101),
INVALID_RESPONSE: new WalletError(t('Something went wrong'), 102),
INVALID_WALLET: new WalletError(t('Wallet version invalid'), 103), INVALID_WALLET: new WalletError(t('Wallet version invalid'), 103),
WRONG_NETWORK: new WalletError( WRONG_NETWORK: new WalletError(
t('Wrong network'), t('Wrong network'),
@ -22,11 +20,6 @@ export const ClientErrors = {
t('Unknown error occurred') t('Unknown error occurred')
), ),
NO_CLIENT: new WalletError(t('No client found.'), 106), NO_CLIENT: new WalletError(t('No client found.'), 106),
REQUEST_REJECTED: new WalletError(
t('Request rejected'),
107,
t('The request has been rejected by the user')
),
} as const; } as const;
export class JsonRpcConnector implements VegaConnector { export class JsonRpcConnector implements VegaConnector {
@ -70,7 +63,9 @@ export class JsonRpcConnector implements VegaConnector {
}), }),
}); });
} }
get url() {
return this._url || '';
}
async getChainId() { async getChainId() {
if (!this.client) { if (!this.client) {
throw ClientErrors.NO_CLIENT; throw ClientErrors.NO_CLIENT;
@ -79,7 +74,12 @@ export class JsonRpcConnector implements VegaConnector {
const { result } = await this.client.GetChainId(); const { result } = await this.client.GetChainId();
return result; return result;
} catch (err) { } catch (err) {
throw ClientErrors.INVALID_RESPONSE; const {
code = ClientErrors.UNKNOWN.code,
message = ClientErrors.UNKNOWN.message,
title,
} = err as WalletClientError;
throw new WalletError(title, code, message);
} }
} }
@ -92,11 +92,12 @@ export class JsonRpcConnector implements VegaConnector {
await this.client.ConnectWallet(); await this.client.ConnectWallet();
return null; return null;
} catch (err) { } catch (err) {
const clientErr = const {
err instanceof WalletClientError && err.code === 3001 code = ClientErrors.UNKNOWN.code,
? ClientErrors.REQUEST_REJECTED message = ClientErrors.UNKNOWN.message,
: ClientErrors.INVALID_RESPONSE; title,
throw clientErr; } = err as WalletClientError;
throw new WalletError(title, code, message);
} }
} }
@ -111,7 +112,12 @@ export class JsonRpcConnector implements VegaConnector {
const { result } = await this.client.ListKeys(); const { result } = await this.client.ListKeys();
return result.keys; return result.keys;
} catch (err) { } catch (err) {
throw ClientErrors.INVALID_RESPONSE; const {
code = ClientErrors.UNKNOWN.code,
message = ClientErrors.UNKNOWN.message,
title,
} = err as WalletClientError;
throw new WalletError(title, code, message);
} }
} }
@ -147,15 +153,21 @@ export class JsonRpcConnector implements VegaConnector {
try { try {
const result = await fetch(`${this._url}/api/${this.version}/methods`); const result = await fetch(`${this._url}/api/${this.version}/methods`);
if (!result.ok) { if (!result.ok) {
const err = ClientErrors.INVALID_WALLET; const sent1 = t(
err.data = t( 'The version of the wallet service running at %s is not supported.',
`The wallet running at ${this._url} is not supported. Required version is ${this.version}` this._url as string
); );
throw err; const sent2 = t(
'Update the wallet software to a version that expose the API %s.',
this.version
);
const data = `${sent1}\n ${sent2}`;
const title = t('Wallet version invalid');
throw new WalletError(title, ClientErrors.INVALID_WALLET.code, data);
} }
return true; return true;
} catch (err) { } catch (err) {
if (err instanceof WalletError) { if (err instanceof WalletClientError) {
throw err; throw err;
} }

View File

@ -1,3 +1,4 @@
import { WalletClientError } from '@vegaprotocol/wallet-client';
import type * as Schema from '@vegaprotocol/types'; import type * as Schema from '@vegaprotocol/types';
export interface DelegateSubmissionBody { export interface DelegateSubmissionBody {
@ -329,14 +330,11 @@ export interface TransactionResponse {
receivedAt: string; receivedAt: string;
sentAt: string; sentAt: string;
} }
export class WalletError { export class WalletError extends WalletClientError {
message: string; data: string;
code: number;
data?: string;
constructor(message: string, code: number, data?: string) { constructor(message: string, code: number, data = 'Wallet error') {
this.message = message; super({ code, message, data });
this.code = code;
this.data = data; this.data = data;
} }
} }

View File

@ -1,6 +1,7 @@
import { LocalStorage } from '@vegaprotocol/react-helpers'; import { LocalStorage } from '@vegaprotocol/react-helpers';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import { useCallback, useMemo, useRef, useState } from 'react'; import { useCallback, useMemo, useRef, useState } from 'react';
import { WalletClientError } from '@vegaprotocol/wallet-client';
import type { VegaWalletContextShape } from '.'; import type { VegaWalletContextShape } from '.';
import type { import type {
PubKey, PubKey,
@ -9,7 +10,6 @@ import type {
} from './connectors/vega-connector'; } from './connectors/vega-connector';
import { VegaWalletContext } from './context'; import { VegaWalletContext } from './context';
import { WALLET_KEY } from './storage'; import { WALLET_KEY } from './storage';
import { WalletError } from './connectors/vega-connector';
import { ViewConnector } from './connectors'; import { ViewConnector } from './connectors';
interface VegaWalletProviderProps { interface VegaWalletProviderProps {
@ -53,7 +53,7 @@ export const VegaWalletProvider = ({ children }: VegaWalletProviderProps) => {
return null; return null;
} }
} catch (err) { } catch (err) {
if (err instanceof WalletError) { if (err instanceof WalletClientError) {
throw err; throw err;
} }
return null; return null;

View File

@ -1,7 +1,7 @@
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
import { WalletClientError } from '@vegaprotocol/wallet-client';
import type { JsonRpcConnector } from './connectors'; import type { JsonRpcConnector } from './connectors';
import { ClientErrors } from './connectors'; import { ClientErrors } from './connectors';
import { WalletError } from './connectors';
import { useVegaWallet } from './use-vega-wallet'; import { useVegaWallet } from './use-vega-wallet';
export enum Status { export enum Status {
@ -18,7 +18,7 @@ export enum Status {
export const useJsonRpcConnect = (onConnect: () => void) => { export const useJsonRpcConnect = (onConnect: () => void) => {
const { connect } = useVegaWallet(); const { connect } = useVegaWallet();
const [status, setStatus] = useState(Status.Idle); const [status, setStatus] = useState(Status.Idle);
const [error, setError] = useState<WalletError | null>(null); const [error, setError] = useState<WalletClientError | null>(null);
const attemptConnect = useCallback( const attemptConnect = useCallback(
async (connector: JsonRpcConnector, appChainId: string) => { async (connector: JsonRpcConnector, appChainId: string) => {
@ -56,7 +56,7 @@ export const useJsonRpcConnect = (onConnect: () => void) => {
setStatus(Status.Connected); setStatus(Status.Connected);
onConnect(); onConnect();
} catch (err) { } catch (err) {
if (err instanceof WalletError) { if (err instanceof WalletClientError) {
setError(err); setError(err);
} }
setStatus(Status.Error); setStatus(Status.Error);

View File

@ -1,7 +1,6 @@
import { useVegaWallet } from './use-vega-wallet'; import { useVegaWallet } from './use-vega-wallet';
import { useEffect, useRef } from 'react'; import { useEffect, useRef } from 'react';
import { ClientErrors } from './connectors'; import { ClientErrors } from './connectors';
import { WalletError } from './connectors';
import { VegaTxStatus } from './use-vega-transaction'; import { VegaTxStatus } from './use-vega-transaction';
import { useVegaTransactionStore } from './use-vega-transaction-store'; import { useVegaTransactionStore } from './use-vega-transaction-store';
import { WalletClientError } from '@vegaprotocol/wallet-client'; import { WalletClientError } from '@vegaprotocol/wallet-client';
@ -40,10 +39,7 @@ export const useVegaTransactionManager = () => {
}) })
.catch((err) => { .catch((err) => {
update(transaction.id, { update(transaction.id, {
error: error: err instanceof WalletClientError ? err : ClientErrors.UNKNOWN,
err instanceof WalletError || err instanceof WalletClientError
? err
: ClientErrors.UNKNOWN,
status: VegaTxStatus.Error, status: VegaTxStatus.Error,
}); });
}); });

View File

@ -98,10 +98,14 @@ describe('useVegaTransaction', () => {
}); });
expect(result.current.transaction.status).toEqual(VegaTxStatus.Error); expect(result.current.transaction.status).toEqual(VegaTxStatus.Error);
expect(result.current.transaction.error).toHaveProperty( expect(result.current.transaction.error).toHaveProperty(
'message', 'title',
'Something went wrong' 'Something went wrong'
); );
expect(result.current.transaction.error).toHaveProperty('code', 105); expect(result.current.transaction.error).toHaveProperty('code', 105);
expect(result.current.transaction.error).toHaveProperty(
'message',
'Unknown error occurred'
);
expect(result.current.transaction.error).toHaveProperty( expect(result.current.transaction.error).toHaveProperty(
'data', 'data',
'Unknown error occurred' 'Unknown error occurred'

View File

@ -6,8 +6,6 @@ import { VegaTransactionDialog } from './vega-transaction-dialog';
import type { Intent } from '@vegaprotocol/ui-toolkit'; import type { Intent } from '@vegaprotocol/ui-toolkit';
import type { Transaction } from './connectors'; import type { Transaction } from './connectors';
import { ClientErrors } from './connectors'; import { ClientErrors } from './connectors';
import { WalletError } from './connectors';
import type { WalletClientError } from '@vegaprotocol/wallet-client';
export interface DialogProps { export interface DialogProps {
intent?: Intent; intent?: Intent;
@ -26,7 +24,7 @@ export enum VegaTxStatus {
export interface VegaTxState { export interface VegaTxState {
status: VegaTxStatus; status: VegaTxStatus;
error: WalletError | WalletClientError | Error | null; error: Error | null;
txHash: string | null; txHash: string | null;
signature: string | null; signature: string | null;
dialogOpen: boolean; dialogOpen: boolean;
@ -90,14 +88,9 @@ export const useVegaTransaction = () => {
return null; return null;
} catch (err) { } catch (err) {
const error = const error = err instanceof Error ? err : ClientErrors.UNKNOWN;
err instanceof WalletError
? err
: err instanceof Error
? err
: ClientErrors.UNKNOWN;
setTransaction({ setTransaction({
error: error, error,
status: VegaTxStatus.Error, status: VegaTxStatus.Error,
}); });
return null; return null;

View File

@ -10,9 +10,9 @@ export function useVegaWallet() {
} }
export function useReconnectVegaWallet() { export function useReconnectVegaWallet() {
const { openVegaWalletDialog } = useVegaWalletDialogStore((store) => ({ const openVegaWalletDialog = useVegaWalletDialogStore(
openVegaWalletDialog: store.openVegaWalletDialog, (store) => store.openVegaWalletDialog
})); );
const { disconnect } = useVegaWallet(); const { disconnect } = useVegaWallet();
const reconnect = useCallback(async () => { const reconnect = useCallback(async () => {
await disconnect(); await disconnect();

View File

@ -2,7 +2,7 @@ import { Networks, useEnvironment } from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/react-helpers';
import { Dialog, Icon, Intent, Loader } from '@vegaprotocol/ui-toolkit'; import { Dialog, Icon, Intent, Loader } from '@vegaprotocol/ui-toolkit';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import { WalletError } from '../connectors'; import { WalletClientError } from '@vegaprotocol/wallet-client';
import type { VegaTxState } from '../use-vega-transaction'; import type { VegaTxState } from '../use-vega-transaction';
import { VegaTxStatus } from '../use-vega-transaction'; import { VegaTxStatus } from '../use-vega-transaction';
@ -107,18 +107,13 @@ export const VegaDialog = ({ transaction }: VegaDialogProps) => {
} }
if (transaction.status === VegaTxStatus.Error) { if (transaction.status === VegaTxStatus.Error) {
content = ( let messageText = '';
<div data-testid={transaction.status}> if (transaction.error instanceof WalletClientError) {
{transaction.error instanceof WalletError && ( messageText = `${transaction.error.title}: ${transaction.error.message}`;
<p> } else if (transaction.error instanceof Error) {
{transaction.error.message}: {transaction.error.data} messageText = transaction.error.message;
</p> }
)} content = <div data-testid={transaction.status}>{messageText}</div>;
{transaction.error instanceof Error && (
<p>{transaction.error.message}</p>
)}
</div>
);
} }
if (transaction.status === VegaTxStatus.Pending) { if (transaction.status === VegaTxStatus.Pending) {

View File

@ -36,7 +36,7 @@
"@sentry/nextjs": "^6.19.3", "@sentry/nextjs": "^6.19.3",
"@sentry/react": "^6.19.2", "@sentry/react": "^6.19.2",
"@sentry/tracing": "^6.19.2", "@sentry/tracing": "^6.19.2",
"@vegaprotocol/wallet-client": "0.1.8", "@vegaprotocol/wallet-client": "0.1.9",
"@walletconnect/ethereum-provider": "^1.7.5", "@walletconnect/ethereum-provider": "^1.7.5",
"@web3-react/core": "8.0.20-beta.0", "@web3-react/core": "8.0.20-beta.0",
"@web3-react/metamask": "8.0.16-beta.0", "@web3-react/metamask": "8.0.16-beta.0",

View File

@ -7321,10 +7321,10 @@
"@typescript-eslint/types" "5.40.0" "@typescript-eslint/types" "5.40.0"
eslint-visitor-keys "^3.3.0" eslint-visitor-keys "^3.3.0"
"@vegaprotocol/wallet-client@0.1.8": "@vegaprotocol/wallet-client@0.1.9":
version "0.1.8" version "0.1.9"
resolved "https://registry.yarnpkg.com/@vegaprotocol/wallet-client/-/wallet-client-0.1.8.tgz#38ca8566d78b9f6694b12ad9364bb34d6482935d" resolved "https://registry.yarnpkg.com/@vegaprotocol/wallet-client/-/wallet-client-0.1.9.tgz#8c6a71c8b2222b3de5d73cade8fc6db57e332de9"
integrity sha512-FVvDvvlccKyXn0ujhivPUCVnkZYQJxtI1q8OgipNnbmAjU1mLyeuRTBw0Isu330yPI1KppNbW6Qicd8OTHBmxw== integrity sha512-oacfJGT0zHM+1If4I/pgIWi7zzU/3uHy4+sjuFEh8pWI8bWBzCF+mHbOGA6iTM+5/5mhayMFc+YZ9GexH1sBnQ==
dependencies: dependencies:
express "4.18.2" express "4.18.2"
nanoid "3.3.4" nanoid "3.3.4"