chore: re add use vega transaction and dialog
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
export * from './connectors';
|
||||
export * from './context';
|
||||
export * from './use-vega-transaction';
|
||||
export * from './use-vega-wallet';
|
||||
export * from './use-vega-transaction-manager';
|
||||
export * from './use-vega-transaction-store';
|
||||
@@ -11,5 +12,6 @@ export * from './provider';
|
||||
export * from './connect-dialog';
|
||||
export * from './utils';
|
||||
export * from './storage';
|
||||
export * from './types';
|
||||
export * from './__generated__/TransactionResult';
|
||||
export * from './__generated__/WithdrawalApproval';
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
export enum VegaTxStatus {
|
||||
Default = 'Default',
|
||||
Requested = 'Requested',
|
||||
Pending = 'Pending',
|
||||
Error = 'Error',
|
||||
Complete = 'Complete',
|
||||
}
|
||||
|
||||
export interface VegaTxState {
|
||||
status: VegaTxStatus;
|
||||
error: Error | null;
|
||||
txHash: string | null;
|
||||
signature: string | null;
|
||||
dialogOpen: boolean;
|
||||
}
|
||||
@@ -2,14 +2,12 @@ import { useVegaWallet } from './use-vega-wallet';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { WalletError } from './connectors';
|
||||
import { ClientErrors } from './connectors';
|
||||
import {
|
||||
useVegaTransactionStore,
|
||||
VegaTxStatus,
|
||||
} from './use-vega-transaction-store';
|
||||
import { useVegaTransactionStore } from './use-vega-transaction-store';
|
||||
import {
|
||||
WalletClientError,
|
||||
WalletHttpError,
|
||||
} from '@vegaprotocol/wallet-client';
|
||||
import { VegaTxStatus } from './types';
|
||||
|
||||
const orderErrorResolve = (err: Error | unknown): Error => {
|
||||
if (err instanceof WalletClientError || err instanceof WalletError) {
|
||||
|
||||
@@ -21,22 +21,8 @@ import type {
|
||||
|
||||
import type { WithdrawalApprovalQuery } from './__generated__/WithdrawalApproval';
|
||||
import { subscribeWithSelector } from 'zustand/middleware';
|
||||
|
||||
export enum VegaTxStatus {
|
||||
Default = 'Default',
|
||||
Requested = 'Requested',
|
||||
Pending = 'Pending',
|
||||
Error = 'Error',
|
||||
Complete = 'Complete',
|
||||
}
|
||||
|
||||
export interface VegaTxState {
|
||||
status: VegaTxStatus;
|
||||
error: Error | null;
|
||||
txHash: string | null;
|
||||
signature: string | null;
|
||||
dialogOpen: boolean;
|
||||
}
|
||||
import type { VegaTxState } from './types';
|
||||
import { VegaTxStatus } from './types';
|
||||
|
||||
export interface VegaStoredTxState extends VegaTxState {
|
||||
id: number;
|
||||
@@ -48,6 +34,7 @@ export interface VegaStoredTxState extends VegaTxState {
|
||||
withdrawalApproval?: WithdrawalApprovalQuery['erc20WithdrawalApproval'];
|
||||
order?: OrderTxUpdateFieldsFragment;
|
||||
}
|
||||
|
||||
export interface VegaTransactionStore {
|
||||
transactions: (VegaStoredTxState | undefined)[];
|
||||
create: (tx: Transaction, order?: OrderTxUpdateFieldsFragment) => number;
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import type { VegaWalletContextShape } from './context';
|
||||
import { VegaWalletContext } from './context';
|
||||
import type { ReactNode } from 'react';
|
||||
import { initialState, useVegaTransaction } from './use-vega-transaction';
|
||||
import type { Transaction } from './connectors';
|
||||
import { WalletError } from './connectors';
|
||||
import { VegaTxStatus } from './types';
|
||||
|
||||
const mockPubKey = '0x123';
|
||||
|
||||
const defaultWalletContext = {
|
||||
pubKey: null,
|
||||
pubKeys: [],
|
||||
isReadOnly: false,
|
||||
sendTx: jest.fn(),
|
||||
connect: jest.fn(),
|
||||
disconnect: jest.fn(),
|
||||
selectPubKey: jest.fn(),
|
||||
connector: null,
|
||||
} as unknown as VegaWalletContextShape;
|
||||
|
||||
function setup(context?: Partial<VegaWalletContextShape>) {
|
||||
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<VegaWalletContext.Provider value={{ ...defaultWalletContext, ...context }}>
|
||||
{children}
|
||||
</VegaWalletContext.Provider>
|
||||
);
|
||||
return renderHook(() => useVegaTransaction(), { wrapper });
|
||||
}
|
||||
|
||||
describe('useVegaTransaction', () => {
|
||||
it('has the correct default state', () => {
|
||||
const { result } = setup();
|
||||
expect(result.current).toEqual({
|
||||
transaction: initialState,
|
||||
send: expect.any(Function),
|
||||
reset: expect.any(Function),
|
||||
setComplete: expect.any(Function),
|
||||
setTransaction: expect.any(Function),
|
||||
Dialog: expect.any(Function),
|
||||
});
|
||||
});
|
||||
|
||||
it('resets state if sendTx returns null (user rejects)', async () => {
|
||||
const mockSendTx = jest.fn().mockReturnValue(Promise.resolve(null));
|
||||
const { result } = setup({ sendTx: mockSendTx });
|
||||
await act(async () => {
|
||||
result.current.send(mockPubKey, {} as Transaction);
|
||||
});
|
||||
expect(result.current.transaction.status).toEqual(VegaTxStatus.Default);
|
||||
});
|
||||
|
||||
it('handles a single wallet error', () => {
|
||||
const error = new WalletError('test error', 1, 'test data');
|
||||
const mockSendTx = jest.fn(() => {
|
||||
throw error;
|
||||
});
|
||||
const { result } = setup({ sendTx: mockSendTx });
|
||||
act(() => {
|
||||
result.current.send(mockPubKey, {} as Transaction);
|
||||
});
|
||||
expect(result.current.transaction.status).toEqual(VegaTxStatus.Error);
|
||||
expect(result.current.transaction.error).toHaveProperty(
|
||||
'message',
|
||||
error.message
|
||||
);
|
||||
expect(result.current.transaction.error).toHaveProperty('code', 1);
|
||||
expect(result.current.transaction.error).toHaveProperty('data', error.data);
|
||||
});
|
||||
|
||||
it('handles a single error', () => {
|
||||
const error = new Error('test error');
|
||||
const mockSendTx = jest.fn(() => {
|
||||
throw error;
|
||||
});
|
||||
const { result } = setup({ sendTx: mockSendTx });
|
||||
act(() => {
|
||||
result.current.send(mockPubKey, {} as Transaction);
|
||||
});
|
||||
expect(result.current.transaction.status).toEqual(VegaTxStatus.Error);
|
||||
expect(result.current.transaction.error).toHaveProperty(
|
||||
'message',
|
||||
error.message
|
||||
);
|
||||
});
|
||||
|
||||
it('handles an unknown error', () => {
|
||||
const unknownThrow = { foo: 'bar' };
|
||||
const mockSendTx = jest.fn(() => {
|
||||
throw unknownThrow;
|
||||
});
|
||||
const { result } = setup({ sendTx: mockSendTx });
|
||||
act(() => {
|
||||
result.current.send(mockPubKey, {} as Transaction);
|
||||
});
|
||||
expect(result.current.transaction.status).toEqual(VegaTxStatus.Error);
|
||||
expect(result.current.transaction.error).toHaveProperty(
|
||||
'title',
|
||||
'Something went wrong'
|
||||
);
|
||||
expect(result.current.transaction.error).toHaveProperty('code', 105);
|
||||
expect(result.current.transaction.error).toHaveProperty(
|
||||
'message',
|
||||
'Unknown error occurred'
|
||||
);
|
||||
expect(result.current.transaction.error).toHaveProperty(
|
||||
'data',
|
||||
'Unknown error occurred'
|
||||
);
|
||||
});
|
||||
|
||||
it('sets txHash and signature to state if successful', async () => {
|
||||
const successObj = {
|
||||
transactionHash: '0x123',
|
||||
signature: 'signature',
|
||||
};
|
||||
const mockSendTx = jest.fn().mockReturnValue(Promise.resolve(successObj));
|
||||
const { result } = setup({ sendTx: mockSendTx });
|
||||
await act(async () => {
|
||||
result.current.send(mockPubKey, {} as Transaction);
|
||||
});
|
||||
expect(result.current.transaction.status).toEqual(VegaTxStatus.Pending);
|
||||
expect(result.current.transaction.txHash).toEqual(
|
||||
successObj.transactionHash
|
||||
);
|
||||
expect(result.current.transaction.signature).toEqual(successObj.signature);
|
||||
});
|
||||
|
||||
it('setComplete sets VegaTxStatus', () => {
|
||||
const { result } = setup();
|
||||
act(() => {
|
||||
result.current.setComplete();
|
||||
});
|
||||
expect(result.current.transaction.status).toBe(VegaTxStatus.Complete);
|
||||
});
|
||||
|
||||
it('reset resets transaction status', async () => {
|
||||
const mockSendTx = jest.fn().mockReturnValue(
|
||||
Promise.resolve({
|
||||
transactionHash: '0x123',
|
||||
signature: 'signature',
|
||||
})
|
||||
);
|
||||
|
||||
const { result } = setup({ sendTx: mockSendTx });
|
||||
|
||||
await act(async () => {
|
||||
result.current.send(mockPubKey, {} as Transaction);
|
||||
});
|
||||
expect(result.current.transaction.status).toBe(VegaTxStatus.Pending);
|
||||
|
||||
act(() => {
|
||||
result.current.reset();
|
||||
});
|
||||
|
||||
expect(result.current.transaction).toEqual(initialState);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,131 @@
|
||||
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 { WalletError } from './connectors';
|
||||
import { ClientErrors } from './connectors';
|
||||
import type { VegaTxState } from './types';
|
||||
import { VegaTxStatus } from './types';
|
||||
|
||||
export interface DialogProps {
|
||||
intent?: Intent;
|
||||
title?: string;
|
||||
icon?: ReactNode;
|
||||
content?: VegaTransactionContentMap;
|
||||
}
|
||||
|
||||
export const initialState = {
|
||||
status: VegaTxStatus.Default,
|
||||
error: null,
|
||||
txHash: null,
|
||||
signature: null,
|
||||
dialogOpen: false,
|
||||
};
|
||||
|
||||
export const orderErrorResolve = (err: Error | unknown): Error => {
|
||||
if (err instanceof WalletClientError || err instanceof WalletError) {
|
||||
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, disconnect } = useVegaWallet();
|
||||
const [transaction, _setTransaction] = useState<VegaTxState>(initialState);
|
||||
|
||||
const setTransaction = useCallback((update: Partial<VegaTxState>) => {
|
||||
_setTransaction((curr) => ({
|
||||
...curr,
|
||||
...update,
|
||||
}));
|
||||
}, []);
|
||||
|
||||
const reset = useCallback(() => {
|
||||
setTransaction(initialState);
|
||||
}, [setTransaction]);
|
||||
|
||||
const setComplete = useCallback(() => {
|
||||
setTransaction({ status: VegaTxStatus.Complete });
|
||||
}, [setTransaction]);
|
||||
|
||||
const send = useCallback(
|
||||
async (pubKey: string, tx: Transaction) => {
|
||||
try {
|
||||
setTransaction({
|
||||
error: null,
|
||||
txHash: null,
|
||||
signature: null,
|
||||
status: VegaTxStatus.Requested,
|
||||
dialogOpen: true,
|
||||
});
|
||||
|
||||
const res = await sendTx(pubKey, tx);
|
||||
|
||||
if (res === null) {
|
||||
// User rejected
|
||||
reset();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (res.signature && res.transactionHash) {
|
||||
setTransaction({
|
||||
status: VegaTxStatus.Pending,
|
||||
txHash: res.transactionHash,
|
||||
signature: res.signature,
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (err) {
|
||||
const error = orderErrorResolve(err);
|
||||
if ((error as WalletError).code === ClientErrors.NO_SERVICE.code) {
|
||||
disconnect();
|
||||
}
|
||||
setTransaction({
|
||||
error,
|
||||
status: VegaTxStatus.Error,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
},
|
||||
[sendTx, setTransaction, reset, disconnect]
|
||||
);
|
||||
|
||||
const Dialog = useMemo(() => {
|
||||
return (props: DialogProps) => (
|
||||
<VegaTransactionDialog
|
||||
{...props}
|
||||
isOpen={transaction.dialogOpen}
|
||||
onChange={(isOpen) => {
|
||||
if (!isOpen) reset();
|
||||
setTransaction({ dialogOpen: isOpen });
|
||||
}}
|
||||
transaction={transaction}
|
||||
/>
|
||||
);
|
||||
}, [transaction, setTransaction, reset]);
|
||||
|
||||
return {
|
||||
send,
|
||||
transaction,
|
||||
reset,
|
||||
setComplete,
|
||||
setTransaction,
|
||||
Dialog,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './vega-transaction-dialog';
|
||||
@@ -0,0 +1,133 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { WalletError } from '../connectors';
|
||||
import { VegaTxStatus } from '../use-vega-transaction';
|
||||
import type { VegaTransactionDialogProps } from './vega-transaction-dialog';
|
||||
import { VegaTransactionDialog } from './vega-transaction-dialog';
|
||||
|
||||
jest.mock('@vegaprotocol/environment', () => ({
|
||||
useEnvironment: () => ({
|
||||
VEGA_EXPLORER_URL: 'https://test.explorer.vega.network',
|
||||
VEGA_ENV: 'TESTNET',
|
||||
}),
|
||||
Networks: {
|
||||
MAINNET: 'MAINNET',
|
||||
TESTNET: 'TESTNET',
|
||||
},
|
||||
}));
|
||||
|
||||
describe('VegaTransactionDialog', () => {
|
||||
let props: VegaTransactionDialogProps;
|
||||
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
isOpen: true,
|
||||
onChange: () => false,
|
||||
transaction: {
|
||||
dialogOpen: true,
|
||||
status: VegaTxStatus.Requested,
|
||||
error: null,
|
||||
txHash: null,
|
||||
signature: null,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
it('requested', () => {
|
||||
render(<VegaTransactionDialog {...props} />);
|
||||
expect(screen.getByTestId('dialog-title')).toHaveTextContent(/confirm/i);
|
||||
expect(screen.getByTestId(VegaTxStatus.Requested)).toHaveTextContent(
|
||||
/please open your wallet/i
|
||||
);
|
||||
expect(screen.getByTestId('testnet-transaction-info')).toHaveTextContent(
|
||||
/^\[This is TESTNET transaction only\]$/
|
||||
);
|
||||
});
|
||||
|
||||
it('pending', () => {
|
||||
render(
|
||||
<VegaTransactionDialog
|
||||
{...props}
|
||||
transaction={{
|
||||
...props.transaction,
|
||||
txHash: 'tx-hash',
|
||||
status: VegaTxStatus.Pending,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByTestId('dialog-title')).toHaveTextContent(/awaiting/i);
|
||||
expect(screen.getByTestId(VegaTxStatus.Pending)).toHaveTextContent(
|
||||
/please wait/i
|
||||
);
|
||||
testBlockExplorerLink('tx-hash');
|
||||
});
|
||||
|
||||
it('error', () => {
|
||||
render(
|
||||
<VegaTransactionDialog
|
||||
{...props}
|
||||
transaction={{
|
||||
...props.transaction,
|
||||
error: new WalletError('rejected', 1),
|
||||
status: VegaTxStatus.Error,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByTestId('dialog-title')).toHaveTextContent(/failed/i);
|
||||
expect(screen.getByTestId(VegaTxStatus.Error)).toHaveTextContent(
|
||||
/rejected/i
|
||||
);
|
||||
});
|
||||
|
||||
it('default complete', () => {
|
||||
render(
|
||||
<VegaTransactionDialog
|
||||
{...props}
|
||||
transaction={{
|
||||
...props.transaction,
|
||||
txHash: 'tx-hash',
|
||||
status: VegaTxStatus.Complete,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByTestId('dialog-title')).toHaveTextContent(/complete/i);
|
||||
expect(screen.getByTestId(VegaTxStatus.Complete)).toHaveTextContent(
|
||||
/confirmed/i
|
||||
);
|
||||
testBlockExplorerLink('tx-hash');
|
||||
});
|
||||
|
||||
it.each(Object.keys(VegaTxStatus))(
|
||||
'renders custom content for %s',
|
||||
(status) => {
|
||||
const title = `${status} title`;
|
||||
const text = `${status} content`;
|
||||
const content = {
|
||||
[status]: <div>{text}</div>,
|
||||
};
|
||||
render(
|
||||
<VegaTransactionDialog
|
||||
{...props}
|
||||
transaction={{
|
||||
...props.transaction,
|
||||
txHash: 'tx-hash',
|
||||
status: status as VegaTxStatus,
|
||||
}}
|
||||
title={title}
|
||||
content={content}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByTestId('dialog-title')).toHaveTextContent(title);
|
||||
expect(screen.getByText(text)).toBeInTheDocument();
|
||||
}
|
||||
);
|
||||
|
||||
function testBlockExplorerLink(txHash: string) {
|
||||
expect(screen.getByTestId('tx-block-explorer')).toHaveTextContent(
|
||||
'View in block explorer'
|
||||
);
|
||||
expect(screen.getByTestId('tx-block-explorer')).toHaveAttribute(
|
||||
'href',
|
||||
`https://test.explorer.vega.network/txs/0x${txHash}`
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,211 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { Dialog, Icon, Intent, Loader } from '@vegaprotocol/ui-toolkit';
|
||||
import { WalletClientError } from '@vegaprotocol/wallet-client';
|
||||
import type { VegaTxState } from '../types';
|
||||
import { VegaTxStatus } from '../types';
|
||||
import { useVegaWallet } from '../use-vega-wallet';
|
||||
|
||||
export type VegaTransactionContentMap = {
|
||||
[C in VegaTxStatus]?: JSX.Element;
|
||||
};
|
||||
export interface VegaTransactionDialogProps {
|
||||
isOpen: boolean;
|
||||
transaction: VegaTxState;
|
||||
onChange?: (isOpen: boolean) => void;
|
||||
intent?: Intent;
|
||||
title?: string;
|
||||
icon?: ReactNode;
|
||||
content?: VegaTransactionContentMap;
|
||||
}
|
||||
|
||||
export const VegaTransactionDialog = ({
|
||||
isOpen,
|
||||
transaction,
|
||||
onChange,
|
||||
intent,
|
||||
title,
|
||||
icon,
|
||||
content,
|
||||
}: VegaTransactionDialogProps) => {
|
||||
const computedIntent = intent ? intent : getIntent(transaction);
|
||||
const computedTitle = title ? title : getTitle(transaction);
|
||||
const computedIcon = icon ? icon : getIcon(transaction);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={isOpen}
|
||||
onChange={onChange}
|
||||
intent={computedIntent}
|
||||
title={computedTitle}
|
||||
icon={computedIcon}
|
||||
size="small"
|
||||
>
|
||||
<Content transaction={transaction} content={content} />
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
interface ContentProps {
|
||||
transaction: VegaTxState;
|
||||
content?: VegaTransactionContentMap;
|
||||
}
|
||||
|
||||
const Content = ({ transaction, content }: ContentProps) => {
|
||||
if (!content) {
|
||||
return <VegaDialog transaction={transaction} />;
|
||||
}
|
||||
|
||||
if (transaction.status === VegaTxStatus.Default && content.Default) {
|
||||
return content.Default;
|
||||
}
|
||||
|
||||
if (transaction.status === VegaTxStatus.Requested && content.Requested) {
|
||||
return content.Requested;
|
||||
}
|
||||
|
||||
if (transaction.status === VegaTxStatus.Pending && content.Pending) {
|
||||
return content.Pending;
|
||||
}
|
||||
|
||||
if (transaction.status === VegaTxStatus.Error && content.Error) {
|
||||
return content.Error;
|
||||
}
|
||||
|
||||
if (transaction.status === VegaTxStatus.Complete && content.Complete) {
|
||||
return content.Complete;
|
||||
}
|
||||
|
||||
return <VegaDialog transaction={transaction} />;
|
||||
};
|
||||
|
||||
interface VegaDialogProps {
|
||||
transaction: VegaTxState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default dialog content
|
||||
*/
|
||||
export const VegaDialog = ({ transaction }: VegaDialogProps) => {
|
||||
const { links, network } = useVegaWallet();
|
||||
|
||||
let content = null;
|
||||
if (transaction.status === VegaTxStatus.Requested) {
|
||||
content = (
|
||||
<>
|
||||
<p data-testid={transaction.status}>
|
||||
{t(
|
||||
'Please open your wallet application and confirm or reject the transaction'
|
||||
)}
|
||||
</p>
|
||||
{network !== 'MAINNET' && (
|
||||
<p data-testid="testnet-transaction-info">
|
||||
{t('[This is %s transaction only]').replace('%s', network)}
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (transaction.status === VegaTxStatus.Error) {
|
||||
let messageText = '';
|
||||
if (transaction.error instanceof WalletClientError) {
|
||||
messageText = `${transaction.error.title}: ${transaction.error.message}`;
|
||||
} else if (transaction.error instanceof Error) {
|
||||
messageText = transaction.error.message;
|
||||
}
|
||||
content = <div data-testid={transaction.status}>{messageText}</div>;
|
||||
}
|
||||
|
||||
if (transaction.status === VegaTxStatus.Pending) {
|
||||
content = (
|
||||
<div data-testid={transaction.status}>
|
||||
<p className="break-all">
|
||||
{t('Please wait for your transaction to be confirmed')} -
|
||||
{transaction.txHash && (
|
||||
<a
|
||||
className="underline"
|
||||
data-testid="tx-block-explorer"
|
||||
href={`${links.explorer}/txs/0x${transaction.txHash}`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{t('View in block explorer')}
|
||||
</a>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (transaction.status === VegaTxStatus.Complete) {
|
||||
content = (
|
||||
<div data-testid={transaction.status}>
|
||||
<p className="break-all">
|
||||
{t('Your transaction has been confirmed')} -
|
||||
{transaction.txHash && (
|
||||
<a
|
||||
className="underline"
|
||||
data-testid="tx-block-explorer"
|
||||
href={`${links.explorer}/txs/0x${transaction.txHash}`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{t('View in block explorer')}
|
||||
</a>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return <div className="text-sm">{content}</div>;
|
||||
};
|
||||
|
||||
const getIntent = (transaction: VegaTxState) => {
|
||||
switch (transaction.status) {
|
||||
case VegaTxStatus.Requested:
|
||||
return Intent.Warning;
|
||||
case VegaTxStatus.Pending:
|
||||
return Intent.None;
|
||||
case VegaTxStatus.Error:
|
||||
return Intent.Danger;
|
||||
case VegaTxStatus.Complete:
|
||||
return Intent.Success;
|
||||
default:
|
||||
return Intent.None;
|
||||
}
|
||||
};
|
||||
|
||||
const getTitle = (transaction: VegaTxState) => {
|
||||
switch (transaction.status) {
|
||||
case VegaTxStatus.Requested:
|
||||
return t('Confirm transaction in wallet');
|
||||
case VegaTxStatus.Pending:
|
||||
return t('Awaiting network confirmation');
|
||||
case VegaTxStatus.Error:
|
||||
return t('Transaction failed');
|
||||
case VegaTxStatus.Complete:
|
||||
return t('Transaction complete');
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
const getIcon = (transaction: VegaTxState) => {
|
||||
switch (transaction.status) {
|
||||
case VegaTxStatus.Requested:
|
||||
return <Icon name="hand-up" />;
|
||||
case VegaTxStatus.Pending:
|
||||
return (
|
||||
<span className="mt-1">
|
||||
<Loader size="small" />
|
||||
</span>
|
||||
);
|
||||
case VegaTxStatus.Error:
|
||||
return <Icon name="warning-sign" />;
|
||||
case VegaTxStatus.Complete:
|
||||
return <Icon name="tick" />;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user