fix(trading): inform the user his connection to wallet is lost (#2863)

This commit is contained in:
Maciek 2023-02-07 11:31:15 +01:00 committed by GitHub
parent 69340f4ddf
commit 1952cb0e78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 58 additions and 21 deletions

View File

@ -10,9 +10,9 @@ interface Props {
export const DealTicketButton = ({ disabled, variant }: Props) => {
const { pubKey } = useVegaWallet();
const { openVegaWalletDialog } = useVegaWalletDialogStore((store) => ({
openVegaWalletDialog: store.openVegaWalletDialog,
}));
const openVegaWalletDialog = useVegaWalletDialogStore(
(store) => store.openVegaWalletDialog
);
return pubKey ? (
<div className="mb-4">
<Button

View File

@ -31,8 +31,6 @@ import {
usePersistedOrderStoreSubscription,
} from '@vegaprotocol/orders';
export type TransactionStatus = 'default' | 'pending';
export interface DealTicketProps {
market: MarketDealTicket;
submit: (order: OrderSubmissionBody['orderSubmission']) => void;

View File

@ -13,10 +13,12 @@ const mockSendTx = jest.fn<Promise<Partial<TransactionResponse> | null>, []>();
const pubKey = 'pubKey';
const mockDisconnect = jest.fn();
jest.mock('./use-vega-wallet', () => ({
useVegaWallet: () => ({
sendTx: mockSendTx,
pubKey,
disconnect: mockDisconnect,
}),
}));
@ -104,6 +106,17 @@ describe('useVegaTransactionManager', () => {
mockSendTx.mockRejectedValue(null);
renderHook(useVegaTransactionManager);
await waitForNextTick();
expect(mockDisconnect).not.toHaveBeenCalledWith();
expect(update).toBeCalled();
expect(update.mock.calls[0][1]?.status).toEqual(VegaTxStatus.Error);
});
it('call disconnect if detect no service error', async () => {
mockTransactionStoreState.mockReturnValue(defaultState);
mockSendTx.mockRejectedValue(new TypeError('Failed to fetch'));
renderHook(useVegaTransactionManager);
await waitForNextTick();
expect(mockDisconnect).toHaveBeenCalledWith();
expect(update).toBeCalled();
expect(update.mock.calls[0][1]?.status).toEqual(VegaTxStatus.Error);
});

View File

@ -1,12 +1,12 @@
import { useVegaWallet } from './use-vega-wallet';
import { useEffect, useRef } from 'react';
import type { WalletError } from './connectors';
import { ClientErrors } from './connectors';
import { VegaTxStatus } from './use-vega-transaction';
import { VegaTxStatus, orderErrorResolve } from './use-vega-transaction';
import { useVegaTransactionStore } from './use-vega-transaction-store';
import { WalletClientError } from '@vegaprotocol/wallet-client';
export const useVegaTransactionManager = () => {
const { sendTx, pubKey } = useVegaWallet();
const { sendTx, pubKey, disconnect } = useVegaWallet();
const processed = useRef<Set<number>>(new Set());
const transaction = useVegaTransactionStore((state) =>
state.transactions.find(
@ -38,10 +38,14 @@ export const useVegaTransactionManager = () => {
}
})
.catch((err) => {
const error = orderErrorResolve(err);
if ((error as WalletError).code === ClientErrors.NO_SERVICE.code) {
disconnect();
}
update(transaction.id, {
error: err instanceof WalletClientError ? err : ClientErrors.UNKNOWN,
error,
status: VegaTxStatus.Error,
});
});
}, [transaction, pubKey, del, sendTx, update]);
}, [transaction, pubKey, del, sendTx, update, disconnect]);
};

View File

@ -6,17 +6,18 @@ import {
useTransactionEventSubscription,
} from './__generated__/TransactionResult';
import { useVegaTransactionStore } from './use-vega-transaction-store';
import { waitForWithdrawalApproval } from './wait-for-withdrawal-approval';
export const useVegaTransactionUpdater = () => {
const client = useApolloClient();
const { updateWithdrawal, updateOrder, updateTransaction } =
useVegaTransactionStore((state) => ({
updateWithdrawal: state.updateWithdrawal,
updateOrder: state.updateOrder,
updateTransaction: state.updateTransactionResult,
}));
const updateWithdrawal = useVegaTransactionStore(
(state) => state.updateWithdrawal
);
const updateOrder = useVegaTransactionStore((state) => state.updateOrder);
const updateTransaction = useVegaTransactionStore(
(state) => state.updateTransactionResult
);
const { pubKey } = useVegaWallet();
const variables = { partyId: pubKey || '' };
const skip = !pubKey;

View File

@ -87,7 +87,7 @@ describe('useVegaTransaction', () => {
);
});
it('handles an unkwown error', () => {
it('handles an unknown error', () => {
const unknownThrow = { foo: 'bar' };
const mockSendTx = jest.fn(() => {
throw unknownThrow;

View File

@ -1,10 +1,15 @@
import type { ReactNode } from 'react';
import { useCallback, useMemo, useState } from 'react';
import {
WalletClientError,
WalletHttpError,
} from '@vegaprotocol/wallet-client';
import { useVegaWallet } from './use-vega-wallet';
import type { VegaTransactionContentMap } from './vega-transaction-dialog';
import { VegaTransactionDialog } from './vega-transaction-dialog';
import type { Intent } from '@vegaprotocol/ui-toolkit';
import type { Transaction } from './connectors';
import type { WalletError } from './connectors';
import { ClientErrors } from './connectors';
export interface DialogProps {
@ -38,8 +43,21 @@ export const initialState = {
dialogOpen: false,
};
export const orderErrorResolve = (err: Error | unknown): Error => {
if (err instanceof WalletClientError) {
return err;
} else if (err instanceof WalletHttpError) {
return ClientErrors.UNKNOWN;
} else if (err instanceof TypeError) {
return ClientErrors.NO_SERVICE;
} else if (err instanceof Error) {
return err;
}
return ClientErrors.UNKNOWN;
};
export const useVegaTransaction = () => {
const { sendTx } = useVegaWallet();
const { sendTx, disconnect } = useVegaWallet();
const [transaction, _setTransaction] = useState<VegaTxState>(initialState);
const setTransaction = useCallback((update: Partial<VegaTxState>) => {
@ -88,7 +106,10 @@ export const useVegaTransaction = () => {
return null;
} catch (err) {
const error = err instanceof Error ? err : ClientErrors.UNKNOWN;
const error = orderErrorResolve(err);
if ((error as WalletError).code === ClientErrors.NO_SERVICE.code) {
disconnect();
}
setTransaction({
error,
status: VegaTxStatus.Error,
@ -96,7 +117,7 @@ export const useVegaTransaction = () => {
return null;
}
},
[sendTx, setTransaction, reset]
[sendTx, setTransaction, reset, disconnect]
);
const Dialog = useMemo(() => {