Skip to content

Commit

Permalink
Add Contract info to signing step (#4234)
Browse files Browse the repository at this point in the history
* Add TxIntermediaryDisplay to signing step

* Move contract info below content on WC screen

* Add tests
  • Loading branch information
FrederikBolding authored Dec 16, 2021
1 parent 97a889a commit d40dd70
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 31 deletions.
32 changes: 17 additions & 15 deletions jest_config/__fixtures__/txConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ import { BigNumber } from '@ethersproject/bignumber';
import {
ITxConfig,
ITxData,
ITxFromAddress,
ITxGasLimit,
ITxGasPrice,
ITxNonce,
ITxToAddress,
ITxValue,
NetworkId,
StoreAccount,
TAddress,
TAssetType,
TTicker,
TUuid
} from '@types';
Expand Down Expand Up @@ -102,27 +105,26 @@ export const fApproveErc20TxConfig = {
decimal: 18,
isCustom: false,
name: 'REPv1',
networkId: 'Ethereum',
ticker: 'REPv1',
type: 'erc20',
uuid: 'd017a1e8-bdd3-5c32-8866-da258f75b0e9'
networkId: 'Ethereum' as NetworkId,
ticker: 'REPv1' as TTicker,
type: 'erc20' as TAssetType,
uuid: 'd017a1e8-bdd3-5c32-8866-da258f75b0e9' as TUuid
},
baseAsset: { ...fAssets[0], balance: BigNumber.from('0x1b9ced41465be000') },
rawTransaction: {
chainId: 1,
data:
'0x095ea7b3000000000000000000000000221657776846890989a759ba2973e427dff5c9bb0000000000000000000000000000000000000000000000004563918244f40000',
from: '0xfE5443FaC29fA621cFc33D41D1927fd0f5E0bB7c',
gasLimit: '0x249f0',
gasPrice: '0x12a05f200',
nonce: '0x1',
to: '0x1985365e9f78359a9B6AD760e32412f4a445E862',
value: '0x0'
data: '0x095ea7b3000000000000000000000000221657776846890989a759ba2973e427dff5c9bb0000000000000000000000000000000000000000000000004563918244f40000' as ITxData,
from: '0xfE5443FaC29fA621cFc33D41D1927fd0f5E0bB7c' as ITxFromAddress,
gasLimit: '0x249f0' as ITxGasLimit,
gasPrice: '0x12a05f200' as ITxGasPrice,
nonce: '0x1' as ITxNonce,
to: '0x1985365e9f78359a9B6AD760e32412f4a445E862' as ITxToAddress,
value: '0x0' as ITxValue
},
receiverAddress: '0xfE5443FaC29fA621cFc33D41D1927fd0f5E0bB7c',
receiverAddress: '0xfE5443FaC29fA621cFc33D41D1927fd0f5E0bB7c' as TAddress,
senderAccount: fAccounts[0],
from: '0xfE5443FaC29fA621cFc33D41D1927fd0f5E0bB7c',
networkId: 'Ethereum'
from: '0xfE5443FaC29fA621cFc33D41D1927fd0f5E0bB7c' as TAddress,
networkId: 'Ethereum' as NetworkId
};

export const fTokenMigrationTxConfig = {
Expand Down
6 changes: 4 additions & 2 deletions src/components/SignTransactionWallets/Hardware.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ComponentProps } from 'react';

import { DEFAULT_NETWORK } from '@config';
import { fAccounts } from '@fixtures';
import { fAccounts, fApproveErc20TxConfig } from '@fixtures';
import { translateRaw } from '@translations';
import { BusyBottomConfig, WalletId } from '@types';

Expand All @@ -16,7 +16,9 @@ const initialProps: ComponentProps<typeof SignTxHardwareUI> = {
}),
wallet: BusyBottomConfig.LEDGER,
senderAccount: { ...fAccounts[0], wallet: WalletId.LEDGER_NANO_S_NEW },
signingState: WalletSigningState.REJECTED
signingState: WalletSigningState.REJECTED,
rawTransaction: fApproveErc20TxConfig.rawTransaction,
contractName: '0x Proxy'
};

export const HardwareWalletUI = () => {
Expand Down
25 changes: 23 additions & 2 deletions src/components/SignTransactionWallets/Hardware.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,17 @@ import { TAddress, Wallet } from '@mycrypto/wallets';
import styled from 'styled-components';

import { Body, Box, BusyBottom, Heading, Icon, InlineMessage, TIcon } from '@components';
import { TxIntermediaryDisplay } from '@components/TransactionFlow/displays';
import { isContractInteraction } from '@components/TransactionFlow/helpers';
import { HARDWARE_CONFIG, WALLETS_CONFIG } from '@config';
import { WalletFactory } from '@services/WalletService';
import { connectWallet, getWalletConnection, useDispatch, useSelector } from '@store';
import {
connectWallet,
getContractName,
getWalletConnection,
useDispatch,
useSelector
} from '@store';
import { FONT_SIZE, SPACING } from '@theme';
import translate, { translateRaw } from '@translations';
import {
Expand Down Expand Up @@ -135,6 +143,8 @@ export default function HardwareSignTransaction({
);

const walletType = HARDWARE_CONFIG[senderAccount.wallet as HardwareWalletId].busyBottom;
const network = senderAccount.networkId;
const contractName = useSelector(getContractName(network, rawTransaction.to));

return (
<SignTxHardwareUI
Expand All @@ -143,6 +153,8 @@ export default function HardwareSignTransaction({
signingState={signingState}
wallet={walletType}
senderAccount={senderAccount}
rawTransaction={rawTransaction}
contractName={contractName}
/>
);
}
Expand All @@ -153,14 +165,18 @@ interface UIProps {
signingState: WalletSigningState;
wallet: BusyBottomConfig;
senderAccount: IAccount;
rawTransaction: ITxObject;
contractName?: string;
}

export const SignTxHardwareUI = ({
walletIconType,
signerDescription,
signingState,
wallet,
senderAccount
senderAccount,
rawTransaction,
contractName
}: UIProps) => (
<>
<Heading textAlign="center" fontWeight="bold" fontSize={FONT_SIZE.XXL}>
Expand All @@ -171,6 +187,11 @@ export const SignTxHardwareUI = ({
<Body fontSize={FONT_SIZE.MD} marginTop={SPACING.MD}>
{signerDescription}
</Body>
{isContractInteraction(rawTransaction.data) && rawTransaction.to && (
<Box mt={3}>
<TxIntermediaryDisplay address={rawTransaction.to} contractName={contractName} />
</Box>
)}
<div>
<SImgContainer>
<Icon type={walletIconType} />
Expand Down
11 changes: 11 additions & 0 deletions src/components/SignTransactionWallets/WalletConnect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import isEmpty from 'ramda/src/isEmpty';
import styled, { css } from 'styled-components';

import {
Box,
BusyBottom,
Button,
CodeBlock,
Expand All @@ -12,9 +13,12 @@ import {
Spinner,
Typography
} from '@components';
import { TxIntermediaryDisplay } from '@components/TransactionFlow/displays';
import { isContractInteraction } from '@components/TransactionFlow/helpers';
import { getNetworkByChainId } from '@services';
import { useNetworks } from '@services/Store';
import { TActionError, useWalletConnect, WcReducer } from '@services/WalletService';
import { getContractName, useSelector } from '@store';
import { BREAK_POINTS, COLORS, FONT_SIZE } from '@theme';
import translate, { translateRaw } from '@translations';
import { BusyBottomConfig, ISignComponentProps, ITxHash, TAddress } from '@types';
Expand Down Expand Up @@ -159,6 +163,8 @@ export function SignTransactionWalletConnect({
sendTx();
}, [state.isConnected, state.promptSignRetry, state.errors]);

const contractName = useSelector(getContractName(network.id, rawTransaction.to));

return (
<>
<SHeader>
Expand Down Expand Up @@ -198,6 +204,11 @@ export function SignTransactionWalletConnect({
<Typography as="div">{translateRaw('SIGN_TX_WALLETCONNECT_INSTRUCTIONS_3')}</Typography>
</SSection>
)}
{isContractInteraction(rawTransaction.data) && rawTransaction.to && (
<Box mt={3}>
<TxIntermediaryDisplay address={rawTransaction.to} contractName={contractName} />
</Box>
)}
<SSection center={true} withOverlay={true}>
<Overlay absolute={true} center={true} show={state.isConnected || !isEmpty(state.errors)}>
<SContainer>
Expand Down
6 changes: 4 additions & 2 deletions src/components/SignTransactionWallets/Web3.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { WALLETS_CONFIG } from '@config';
import { fAccounts } from '@fixtures';
import { fAccounts, fApproveErc20TxConfig } from '@fixtures';
import { WalletId } from '@types';

import { SignTransactionWeb3UI, UIProps, WalletSigningState } from './Web3';
Expand All @@ -10,7 +10,9 @@ const initialProps: UIProps = {
walletConfig: WALLETS_CONFIG[WalletId.METAMASK],
walletState: WalletSigningState.SUBMITTING,
networkName: 'Ethereum',
senderAccount: { ...fAccounts[0], wallet: WalletId.METAMASK }
senderAccount: { ...fAccounts[0], wallet: WalletId.METAMASK },
rawTransaction: fApproveErc20TxConfig.rawTransaction,
contractName: '0x Proxy'
};

export const SignTransactionWeb3 = () => {
Expand Down
20 changes: 19 additions & 1 deletion src/components/SignTransactionWallets/Web3.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ import { Web3Provider } from '@ethersproject/providers';
import styled from 'styled-components';

import { Body, Box, BusyBottom, Heading, InlineMessage } from '@components';
import { TxIntermediaryDisplay } from '@components/TransactionFlow/displays';
import { isContractInteraction } from '@components/TransactionFlow/helpers';
import { IWalletConfig, WALLETS_CONFIG } from '@config';
import { useNetworks } from '@services/Store';
import { getContractName, useSelector } from '@store';
import { BREAK_POINTS, FONT_SIZE, SPACING } from '@theme';
import translate, { translateRaw } from '@translations';
import {
BusyBottomConfig,
InlineMessageType,
ISignComponentProps,
ITxObject,
StoreAccount,
TAddress,
WalletId
Expand Down Expand Up @@ -113,12 +117,17 @@ export default function SignTransactionWeb3({
});
};

const network = senderAccount.networkId;
const contractName = useSelector(getContractName(network, rawTransaction.to));

return (
<SignTransactionWeb3UI
walletConfig={walletConfig}
walletState={walletState}
networkName={networkName}
senderAccount={senderAccount}
rawTransaction={rawTransaction}
contractName={contractName}
/>
);
}
Expand Down Expand Up @@ -158,13 +167,17 @@ export interface UIProps {
walletState: WalletSigningState;
networkName: string;
senderAccount: StoreAccount;
rawTransaction: ITxObject;
contractName?: string;
}

export const SignTransactionWeb3UI = ({
walletConfig,
walletState,
networkName,
senderAccount
senderAccount,
rawTransaction,
contractName
}: UIProps) => (
<Box>
<Heading fontSize="32px" textAlign="center" fontWeight="bold">
Expand All @@ -177,6 +190,11 @@ export const SignTransactionWeb3UI = ({
$walletName: walletConfig.name || WALLETS_CONFIG.WEB3.name
})}
</Body>
{isContractInteraction(rawTransaction.data) && rawTransaction.to && (
<Box mt={3}>
<TxIntermediaryDisplay address={rawTransaction.to} contractName={contractName} />
</Box>
)}
<Web3ImgContainer>
<Web3Img>
<img src={walletConfig.icon} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { ComponentProps } from 'react';
import { APP_STATE, mockAppState, simpleRender, waitFor } from 'test-utils';

import SignTransaction from '@features/SendAssets/components/SignTransaction';
import { fTxConfig } from '@fixtures';
import { fApproveErc20TxConfig, fTxConfig } from '@fixtures';
import { translateRaw } from '@translations';
import { WalletId } from '@types';

import { getHeader } from './helper';
Expand Down Expand Up @@ -81,4 +82,25 @@ describe('SignTransactionWallets: GridPlus', () => {
{ timeout: 60000 }
);
});

it('Shows contract info if needed', async () => {
const { getByText } = getComponent({
...defaultProps,
txConfig: {
...fApproveErc20TxConfig,
senderAccount: {
...fTxConfig.senderAccount,
wallet: WalletId.GRIDPLUS
}
}
});
expect(
getByText(
translateRaw('TRANSACTION_PERFORMED_VIA_CONTRACT', {
$contractName: translateRaw('UNKNOWN').toLowerCase()
}),
{ exact: false }
)
).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { ComponentProps } from 'react';
import { simpleRender, waitFor } from 'test-utils';

import SignTransaction from '@features/SendAssets/components/SignTransaction';
import { fTxConfig } from '@fixtures';
import { fApproveErc20TxConfig, fTxConfig } from '@fixtures';
import { translateRaw } from '@translations';
import { WalletId } from '@types';

// eslint-disable-next-line jest/no-mocks-import
Expand All @@ -15,8 +16,8 @@ const defaultProps: ComponentProps<typeof SignTransaction> = {
onComplete: jest.fn()
};

const getComponent = () => {
return simpleRender(<SignTransaction {...defaultProps} />);
const getComponent = (props = defaultProps) => {
return simpleRender(<SignTransaction {...props} />);
};

jest.mock('@ethersproject/providers', () => {
Expand All @@ -31,11 +32,11 @@ jest.mock('@ethersproject/providers', () => {
});

describe('SignTransactionWallets: Web3', () => {
afterEach(() => {
afterAll(() => {
jest.resetAllMocks();
});

test('Can handle Web3 signing', async () => {
it('Can handle Web3 signing', async () => {
const customWindow = window as CustomWindow;
// Mock window.ethereum
mockWindow(customWindow);
Expand All @@ -46,4 +47,25 @@ describe('SignTransactionWallets: Web3', () => {
await waitFor(() => expect(customWindow.ethereum.on).toHaveBeenCalled());
await waitFor(() => expect(defaultProps.onComplete).toHaveBeenCalledWith('txhash'));
});

it('Shows contract info if needed', async () => {
const customWindow = window as CustomWindow;
// Mock window.ethereum
mockWindow(customWindow);
const { getByText } = getComponent({
...defaultProps,
txConfig: {
...fApproveErc20TxConfig,
senderAccount: { ...fTxConfig.senderAccount, wallet: WalletId.WEB3 }
}
});
expect(
getByText(
translateRaw('TRANSACTION_PERFORMED_VIA_CONTRACT', {
$contractName: translateRaw('UNKNOWN').toLowerCase()
}),
{ exact: false }
)
).toBeInTheDocument();
});
});
Loading

0 comments on commit d40dd70

Please sign in to comment.