Skip to content

Commit

Permalink
Implement token send components
Browse files Browse the repository at this point in the history
  • Loading branch information
pedronfigueiredo committed Oct 9, 2024
1 parent 98a1064 commit 8f29230
Show file tree
Hide file tree
Showing 10 changed files with 237 additions and 27 deletions.
3 changes: 3 additions & 0 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */
import { TransactionEnvelopeType } from '@metamask/transaction-controller';
import { DAPP_URL } from '../../../constants';
import { unlockWallet } from '../../../helpers';
import { unlockWallet, WINDOW_TITLES } from '../../../helpers';
import { Mockttp } from '../../../mock-e2e';
import SetApprovalForAllTransactionConfirmation from '../../../page-objects/pages/set-approval-for-all-transaction-confirmation';
import TestDapp from '../../../page-objects/pages/test-dapp';
import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry';
import { Driver } from '../../../webdriver/driver';
import { withRedesignConfirmationFixtures } from '../helpers';
import { mocked4BytesSetApprovalForAll } from './erc721-revoke-set-approval-for-all-redesign';
import { TestSuiteArguments } from './shared';

const { SMART_CONTRACTS } = require('../../../seeder/smart-contracts');

const SMART_CONTRACT = SMART_CONTRACTS.HST;

describe('Confirmation Redesign ERC20 Token Send', function () {
describe('Confirmation Redesign ERC20 Token Send @no-mmi', function () {
it('Sends a type 0 transaction (Legacy)', async function () {
await withRedesignConfirmationFixtures(
this.test?.fullTitle(),
Expand All @@ -20,7 +22,7 @@ describe('Confirmation Redesign ERC20 Token Send', function () {
await createTransactionAndAssertDetails(driver, contractRegistry);
},
mocks,
SMART_CONTRACT,
SMART_CONTRACTS.HST,
);
});

Expand All @@ -32,13 +34,13 @@ describe('Confirmation Redesign ERC20 Token Send', function () {
await createTransactionAndAssertDetails(driver, contractRegistry);
},
mocks,
SMART_CONTRACT,
SMART_CONTRACTS.HST,
);
});
});

async function mocks() {
return [];
async function mocks(server: Mockttp) {
return [await mocked4BytesSetApprovalForAll(server)];
}

async function createTransactionAndAssertDetails(
Expand All @@ -49,13 +51,15 @@ async function createTransactionAndAssertDetails(

const contractAddress = await (
contractRegistry as GanacheContractAddressRegistry
).getContractAddress(SMART_CONTRACT);
).getContractAddress(SMART_CONTRACTS.HST);

const testDapp = new TestDapp(driver);

await testDapp.open({ contractAddress, url: DAPP_URL });

await driver.delay(1024 ** 2);
// 0x581c3C1A2A4EBDE2A0Df29B5cf4c116E42945947
// 0x8e212420caE9c3D6ba75B247f63998cf1B178B63

// await testDapp.clickERC1155RevokeSetApprovalForAllButton();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const render = (
};

describe('<WalletInitiatedHeader />', () => {
it.only('should match snapshot', () => {
it('should match snapshot', () => {
const { container } = render();

expect(container).toMatchSnapshot();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,20 @@
import { Meta } from '@storybook/react';
import React from 'react';
import { Provider } from 'react-redux';
import mockState from '../../../../../../../../test/data/mock-state.json';
import { getMockTokenTransferConfirmState } from '../../../../../../../../test/data/confirmations/helper';
import configureStore from '../../../../../../../store/store';
import { SendHeading } from './send-heading';
import { ConfirmContextProvider } from '../../../../../context/confirm';
import SendHeading from './send-heading';

function getStore() {
return configureStore(mockState);
}
const store = configureStore(getMockTokenTransferConfirmState({}));

const Story = {
title: 'Components/App/Confirm/info/SendHeading',
component: SendHeading,
decorators: [
(story: () => Meta<typeof SendHeading>) => (
<Provider store={getStore()}>
<div
style={{
backgroundColor: 'var(--color-background-alternative)',
padding: 30,
}}
>
{story()}
</div>
<Provider store={store}>
<ConfirmContextProvider>{story()}</ConfirmContextProvider>
</Provider>
),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import mockState from '../../../../../../../../test/data/mock-state.json';
import { renderWithProvider } from '../../../../../../../../test/lib/render-helpers';
import { SendHeading } from './send-heading';
import SendHeading from './send-heading';

describe('<SendHeading />', () => {
const middleware = [thunk];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const SendHeading = () => {
flexDirection={FlexDirection.Column}
justifyContent={JustifyContent.center}
alignItems={AlignItems.center}
paddingTop={4}
padding={4}
>
<AvatarToken
src={tokenImage}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { NameType } from '@metamask/name-controller';
import React, { useState } from 'react';
import { useSelector } from 'react-redux';
import { useFallbackDisplayName } from '../../../../../../components/app/confirm/info/row/hook';
import NicknamePopovers from '../../../../../../components/app/modals/nickname-popovers';
import Name from '../../../../../../components/app/name';
import {
AvatarAccount,
AvatarAccountSize,
Box,
Text,
} from '../../../../../../components/component-library';
import {
AlignItems,
BorderColor,
Display,
FlexDirection,
TextColor,
} from '../../../../../../helpers/constants/design-system';
import { getPetnamesEnabled } from '../../../../../../selectors';

export const NameOrAddressDisplay = ({ address }: { address: string }) => {
const isPetNamesEnabled = useSelector(getPetnamesEnabled);
const { displayName, hexAddress } = useFallbackDisplayName(address);
const [isNicknamePopoverShown, setIsNicknamePopoverShown] = useState(false);
const handleDisplayNameClick = () => setIsNicknamePopoverShown(true);
const onCloseHandler = () => setIsNicknamePopoverShown(false);

if (isPetNamesEnabled) {
return <Name value={hexAddress} type={NameType.ETHEREUM_ADDRESS} />;
}

return (
<>
<Box
display={Display.Flex}
flexDirection={FlexDirection.Row}
alignItems={AlignItems.center}
onClick={handleDisplayNameClick}
>
<AvatarAccount
address={address}
size={AvatarAccountSize.Xs}
borderColor={BorderColor.transparent}
/>
<Text
marginLeft={2}
color={TextColor.inherit}
data-testid="confirm-info-row-display-name"
>
{displayName}
</Text>
</Box>
{isNicknamePopoverShown ? (
<NicknamePopovers onClose={onCloseHandler} address={hexAddress} />
) : null}
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { TransactionMeta } from '@metamask/transaction-controller';
import React from 'react';
import { useSelector } from 'react-redux';
import { CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP } from '../../../../../../../shared/constants/network';
import {
ConfirmInfoRow,
ConfirmInfoRowAddress,
} from '../../../../../../components/app/confirm/info/row';
import { ConfirmInfoSection } from '../../../../../../components/app/confirm/info/row/section';
import {
AvatarNetwork,
AvatarNetworkSize,
Box,
Text,
} from '../../../../../../components/component-library';
import {
AlignItems,
BlockSize,
BorderColor,
Display,
FlexWrap,
TextColor,
TextVariant,
} from '../../../../../../helpers/constants/design-system';
import { useI18nContext } from '../../../../../../hooks/useI18nContext';
import {
getCurrentChainId,
getNetworkConfigurationsByChainId,
} from '../../../../../../selectors';
import { useConfirmContext } from '../../../../context/confirm';

export const TokenDetailsSection = () => {
const t = useI18nContext();
const { currentConfirmation: transactionMeta } =
useConfirmContext<TransactionMeta>();

const chainId = useSelector(getCurrentChainId);
const networkConfigurations = useSelector(getNetworkConfigurationsByChainId);
const networkName = networkConfigurations[chainId].name;

const networkRow = (
<ConfirmInfoRow label={t('transactionFlowNetwork')}>
<Box
display={Display.Flex}
alignItems={AlignItems.center}
flexWrap={FlexWrap.Wrap}
gap={2}
minWidth={BlockSize.Zero}
>
<AvatarNetwork
borderColor={BorderColor.backgroundDefault}
size={AvatarNetworkSize.Sm}
src={
CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[
chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP
]
}
name={networkName}
/>
<Text variant={TextVariant.bodyMd} color={TextColor.textDefault}>
{networkName}
</Text>
</Box>
</ConfirmInfoRow>
);

const tokenRow = (
<ConfirmInfoRow label={t('interactingWith')}>
<ConfirmInfoRowAddress address={transactionMeta.txParams.to as string} />
</ConfirmInfoRow>
);

return (
<ConfirmInfoSection data-testid="confirmation__transaction-flow">
{networkRow}
{tokenRow}
</ConfirmInfoSection>
);
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { selectConfirmationAdvancedDetailsOpen } from '../../../../selectors/preferences';
import { AdvancedDetails } from '../shared/advanced-details/advanced-details';
import { GasFeesSection } from '../shared/gas-fees-section/gas-fees-section';
import SendHeading from '../shared/send-heading/send-heading';
import { TokenDetailsSection } from './token-details-section';
import { TransactionFlowSection } from './transaction-flow-section';

const TokenTransferInfo = () => {
return <SendHeading />;
const showAdvancedDetails = useSelector(
selectConfirmationAdvancedDetailsOpen,
);

return (
<>
<SendHeading />
<TransactionFlowSection />
<TokenDetailsSection />
<GasFeesSection />
{showAdvancedDetails && <AdvancedDetails />}
</>
);
};

export default TokenTransferInfo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { TransactionMeta } from '@metamask/transaction-controller';
import React from 'react';
import { ConfirmInfoSection } from '../../../../../../components/app/confirm/info/row/section';
import {
Box,
Icon,
IconName,
IconSize,
} from '../../../../../../components/component-library';
import {
AlignItems,
Display,
FlexDirection,
IconColor,
JustifyContent,
} from '../../../../../../helpers/constants/design-system';
import { useConfirmContext } from '../../../../context/confirm';
import { useDecodedTransactionData } from '../hooks/useDecodedTransactionData';
import { NameOrAddressDisplay } from './name';

export const TransactionFlowSection = () => {
const { currentConfirmation: transactionMeta } =
useConfirmContext<TransactionMeta>();

const { value, pending } = useDecodedTransactionData();

const recipientAddress =
value?.data[0].params.find((param) => param.type === 'address')?.value ||
'0x0000000000000000000000000000000000000000';

if (pending) {
// TODO: ConfirmPendingLoader when papercuts PR is merged
return null;
}

return (
<ConfirmInfoSection data-testid="confirmation__transaction-flow">
<Box
display={Display.Flex}
flexDirection={FlexDirection.Row}
justifyContent={JustifyContent.spaceBetween}
alignItems={AlignItems.center}
padding={3}
>
<NameOrAddressDisplay address={transactionMeta.txParams.from} />
<Icon
name={IconName.ArrowRight}
size={IconSize.Md}
color={IconColor.iconMuted}
/>
<NameOrAddressDisplay address={recipientAddress} />
</Box>
</ConfirmInfoSection>
);
};

0 comments on commit 8f29230

Please sign in to comment.