vega-frontend-monorepo/libs/react-helpers/src/hooks/use-ethereum-transaction.test.tsx

123 lines
3.1 KiB
TypeScript
Raw Normal View History

Feat/103 deposits (#143) * add web3 provider using web3-react package * add env setup, add guard for incorrect chain id * add lib for web3-provider * make wallet and ethereum connect dialogs look more consistent * add setup tests file for jest-dom * remove chain id config and just use appChainId prop, add disconnect button to invalid chainId state * switch handling of connect dialog state to the consuming app * rename web3-provider package to just web3 * envs for each environment so we can specify chainId * make web3container enforce connection before rendering childen * add web3 provider using web3-react package * make web3container enforce connection before rendering childen * add container for getting network params * Move ethereum config query to web3 container * add basic deposit form elements * add queries required for deposits, add asset default * add bridge contract and deposit transaction * break txhash * restrict etherscan link props, use etherscan link in transaction dialogs * use smart-contracts-sdk * split hooks and components into different files, fix find deposit logic, add styles and progress for tx dialogs * fix text colors for dark mode * improve tx dialogs, rename deposit query * position use buttons, fix select validation * fix type errors after not being in strict mode, add allowance checking * add deposit-limits component, fix types now that strict mode is enabled * make contract hooks have a single instance * split out dialogs into separate files, fix icon alignment * improve error types for use transaction hook, add number save min and max for the amount input * add validation for ethereum and vega addresses * add unit test for deposit form component * add icons and shared dialog styles so it better matches order transaction dialog * fix underline class, reset finalized deposit * fix type imports, use i18n function, regen types * only pass contract address to token contract hook * add vega env, refactor so retrieving asset contract address logic isn't duplicated * add faucet functionality, combine dialogs into single transaction-dialog * combine rendering logic into single func of transaction dialog, rever contract hooks to just useMemo * use to field rather than connected key * fix props and imports in deposit form test * share faucetable condition, pass it to token contract * pass contracts in as params to hooks to avoid multiple contract instances * refetch balance in wallet after deposit, add comments * use hook state for tracking deposit via partyid, add test for use ethereum transaction hook * add deposits lib * add last smart contract sdk package * fix asset import in test * tidy up ts-ignores * pass arg for faucetable token contract * add provider url to env vars and use in place of infura id, also update web3-connector to only allow the chain permitted by the app * add type guard for erc20 assets * fix intent shadow helper function, use arrow function for isEthereumError * update etherscan link to use env vars for url base * rename deposit related hooks to indicate read vs write calls * move ethereum error class and helpers to react-helpers * add use-ethereum-read-contract hook to contain fetch logic * remove unused import * move validation to lib, add hex check for vega public key * use map for transaction modal states, pass confirmed prop to transaction dialog for deposits * remove unused import for classnames
2022-04-06 17:34:51 +00:00
import { MockedProvider } from '@apollo/client/testing';
import { waitFor } from '@testing-library/react';
import { act, renderHook } from '@testing-library/react-hooks';
import { TxState } from './use-ethereum-transaction';
import type { ReactNode } from 'react';
import { useEthereumTransaction } from './use-ethereum-transaction';
import type { ethers } from 'ethers';
import { EthereumError } from '../lib/ethereum-error';
beforeAll(() => {
jest.useFakeTimers();
});
afterAll(() => {
jest.useRealTimers();
});
class MockContract {
static txHash = 'tx-hash';
confirmations = 0;
depositAsset(args: {
assetSource: string;
amount: string;
vegaPublicKey: string;
}): Promise<ethers.ContractTransaction> {
return Promise.resolve({
hash: MockContract.txHash,
wait: () => {
this.confirmations++;
return new Promise((resolve) => {
setTimeout(
() =>
resolve({
confirmations: this.confirmations,
} as ethers.ContractReceipt),
100
);
});
},
} as ethers.ContractTransaction);
}
}
const mockContract = new MockContract();
const requiredConfirmations = 3;
function setup(perform: () => void) {
const wrapper = ({ children }: { children: ReactNode }) => (
<MockedProvider>{children}</MockedProvider>
);
return renderHook(
// @ts-ignore force MockContract
() => useEthereumTransaction(perform, requiredConfirmations),
{ wrapper }
);
}
test('Ethereum transaction flow', async () => {
const { result } = setup(() => {
return mockContract.depositAsset({
assetSource: 'asset-source',
amount: '100',
vegaPublicKey: 'vega-key',
});
});
expect(result.current).toEqual({
status: TxState.Default,
txHash: null,
error: null,
confirmations: 0,
perform: expect.any(Function),
});
act(() => {
result.current.perform();
});
expect(result.current.status).toEqual(TxState.Requested);
expect(result.current.confirmations).toBe(0);
await waitFor(() => {
expect(result.current.status).toEqual(TxState.Pending);
expect(result.current.txHash).toEqual(MockContract.txHash);
});
await act(async () => {
jest.advanceTimersByTime(100);
});
expect(result.current.confirmations).toBe(1);
expect(result.current.status).toEqual(TxState.Pending);
await act(async () => {
jest.advanceTimersByTime(100);
});
expect(result.current.confirmations).toBe(2);
expect(result.current.status).toEqual(TxState.Pending);
await act(async () => {
jest.advanceTimersByTime(100);
});
expect(result.current.confirmations).toBe(3);
// Now complete as required confirmations have been surpassed
expect(result.current.status).toEqual(TxState.Complete);
});
test('Error handling', async () => {
const { result } = setup(() => {
throw new EthereumError(errorMsg, 500);
});
const errorMsg = 'test-error';
act(() => {
result.current.perform();
});
expect(result.current.status).toEqual(TxState.Error);
expect(result.current.error instanceof EthereumError).toBe(true);
expect(result.current.error?.message).toBe(errorMsg);
});