mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
Extracting out title component from confirm-transaction-base (#17991)
This commit is contained in:
parent
2fc0d93789
commit
5dee7904d6
@ -313,11 +313,10 @@ describe('MetaMask', function () {
|
|||||||
text: 'Transfer',
|
text: 'Transfer',
|
||||||
});
|
});
|
||||||
|
|
||||||
const tokenAmount = await driver.findElement(
|
await driver.findElement({
|
||||||
'.confirm-page-container-summary__title-text',
|
tag: 'h1',
|
||||||
);
|
text: '1 TST',
|
||||||
const tokenAmountText = await tokenAmount.getText();
|
});
|
||||||
assert.equal(tokenAmountText, '1 TST');
|
|
||||||
|
|
||||||
await driver.waitForSelector({
|
await driver.waitForSelector({
|
||||||
tag: 'p',
|
tag: 'p',
|
||||||
@ -419,11 +418,10 @@ describe('MetaMask', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('submits the transaction', async function () {
|
it('submits the transaction', async function () {
|
||||||
const tokenAmount = await driver.findElement(
|
await driver.findElement({
|
||||||
'.confirm-page-container-summary__title-text',
|
tag: 'h1',
|
||||||
);
|
text: '1.5 TST',
|
||||||
const tokenAmountText = await tokenAmount.getText();
|
});
|
||||||
assert.equal(tokenAmountText, '1.5 TST');
|
|
||||||
|
|
||||||
await driver.clickElement({ text: 'Confirm', tag: 'button' });
|
await driver.clickElement({ text: 'Confirm', tag: 'button' });
|
||||||
await driver.delay(regularDelayMs);
|
await driver.delay(regularDelayMs);
|
||||||
|
@ -29,11 +29,9 @@ export default class ConfirmPageContainerContent extends Component {
|
|||||||
///: END:ONLY_INCLUDE_IN
|
///: END:ONLY_INCLUDE_IN
|
||||||
errorKey: PropTypes.string,
|
errorKey: PropTypes.string,
|
||||||
errorMessage: PropTypes.string,
|
errorMessage: PropTypes.string,
|
||||||
hideSubtitle: PropTypes.bool,
|
|
||||||
tokenAddress: PropTypes.string,
|
tokenAddress: PropTypes.string,
|
||||||
nonce: PropTypes.string,
|
nonce: PropTypes.string,
|
||||||
subtitleComponent: PropTypes.node,
|
subtitleComponent: PropTypes.node,
|
||||||
title: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
||||||
image: PropTypes.string,
|
image: PropTypes.string,
|
||||||
titleComponent: PropTypes.node,
|
titleComponent: PropTypes.node,
|
||||||
warning: PropTypes.string,
|
warning: PropTypes.string,
|
||||||
@ -48,7 +46,6 @@ export default class ConfirmPageContainerContent extends Component {
|
|||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
unapprovedTxCount: PropTypes.number,
|
unapprovedTxCount: PropTypes.number,
|
||||||
rejectNText: PropTypes.string,
|
rejectNText: PropTypes.string,
|
||||||
hideTitle: PropTypes.bool,
|
|
||||||
supportsEIP1559: PropTypes.bool,
|
supportsEIP1559: PropTypes.bool,
|
||||||
hasTopBorder: PropTypes.bool,
|
hasTopBorder: PropTypes.bool,
|
||||||
nativeCurrency: PropTypes.string,
|
nativeCurrency: PropTypes.string,
|
||||||
@ -136,11 +133,9 @@ export default class ConfirmPageContainerContent extends Component {
|
|||||||
action,
|
action,
|
||||||
errorKey,
|
errorKey,
|
||||||
errorMessage,
|
errorMessage,
|
||||||
title,
|
|
||||||
image,
|
image,
|
||||||
titleComponent,
|
titleComponent,
|
||||||
subtitleComponent,
|
subtitleComponent,
|
||||||
hideSubtitle,
|
|
||||||
tokenAddress,
|
tokenAddress,
|
||||||
nonce,
|
nonce,
|
||||||
detailsComponent,
|
detailsComponent,
|
||||||
@ -156,7 +151,6 @@ export default class ConfirmPageContainerContent extends Component {
|
|||||||
rejectNText,
|
rejectNText,
|
||||||
origin,
|
origin,
|
||||||
ethGasPriceWarning,
|
ethGasPriceWarning,
|
||||||
hideTitle,
|
|
||||||
supportsEIP1559,
|
supportsEIP1559,
|
||||||
hasTopBorder,
|
hasTopBorder,
|
||||||
nativeCurrency,
|
nativeCurrency,
|
||||||
@ -199,15 +193,12 @@ export default class ConfirmPageContainerContent extends Component {
|
|||||||
!detailsComponent || !dataComponent,
|
!detailsComponent || !dataComponent,
|
||||||
})}
|
})}
|
||||||
action={action}
|
action={action}
|
||||||
title={title}
|
|
||||||
image={image}
|
image={image}
|
||||||
titleComponent={titleComponent}
|
titleComponent={titleComponent}
|
||||||
subtitleComponent={subtitleComponent}
|
subtitleComponent={subtitleComponent}
|
||||||
hideSubtitle={hideSubtitle}
|
|
||||||
tokenAddress={tokenAddress}
|
tokenAddress={tokenAddress}
|
||||||
nonce={nonce}
|
nonce={nonce}
|
||||||
origin={origin}
|
origin={origin}
|
||||||
hideTitle={hideTitle}
|
|
||||||
toAddress={toAddress}
|
toAddress={toAddress}
|
||||||
transactionType={transactionType}
|
transactionType={transactionType}
|
||||||
/>
|
/>
|
||||||
|
@ -14,8 +14,6 @@ import { getIpfsGateway } from '../../../../../selectors';
|
|||||||
import Identicon from '../../../../ui/identicon';
|
import Identicon from '../../../../ui/identicon';
|
||||||
import InfoTooltip from '../../../../ui/info-tooltip';
|
import InfoTooltip from '../../../../ui/info-tooltip';
|
||||||
import NicknamePopovers from '../../../modals/nickname-popovers';
|
import NicknamePopovers from '../../../modals/nickname-popovers';
|
||||||
import { Text } from '../../../../component-library';
|
|
||||||
import { TextVariant } from '../../../../../helpers/constants/design-system';
|
|
||||||
import { ORIGIN_METAMASK } from '../../../../../../shared/constants/app';
|
import { ORIGIN_METAMASK } from '../../../../../../shared/constants/app';
|
||||||
import SiteOrigin from '../../../../ui/site-origin';
|
import SiteOrigin from '../../../../ui/site-origin';
|
||||||
import { getAssetImageURL } from '../../../../../helpers/utils/util';
|
import { getAssetImageURL } from '../../../../../helpers/utils/util';
|
||||||
@ -23,16 +21,13 @@ import { getAssetImageURL } from '../../../../../helpers/utils/util';
|
|||||||
const ConfirmPageContainerSummary = (props) => {
|
const ConfirmPageContainerSummary = (props) => {
|
||||||
const {
|
const {
|
||||||
action,
|
action,
|
||||||
title,
|
|
||||||
titleComponent,
|
titleComponent,
|
||||||
subtitleComponent,
|
subtitleComponent,
|
||||||
hideSubtitle,
|
|
||||||
className,
|
className,
|
||||||
tokenAddress,
|
tokenAddress,
|
||||||
toAddress,
|
toAddress,
|
||||||
nonce,
|
nonce,
|
||||||
origin,
|
origin,
|
||||||
hideTitle,
|
|
||||||
image,
|
image,
|
||||||
transactionType,
|
transactionType,
|
||||||
} = props;
|
} = props;
|
||||||
@ -130,26 +125,9 @@ const ConfirmPageContainerSummary = (props) => {
|
|||||||
<>
|
<>
|
||||||
<div className="confirm-page-container-summary__title">
|
<div className="confirm-page-container-summary__title">
|
||||||
{renderImage()}
|
{renderImage()}
|
||||||
{!hideTitle ? (
|
{titleComponent}
|
||||||
<Text
|
|
||||||
className="confirm-page-container-summary__title-text"
|
|
||||||
variant={
|
|
||||||
title && title.length < 10
|
|
||||||
? TextVariant.displayMd
|
|
||||||
: TextVariant.headingMd
|
|
||||||
}
|
|
||||||
as={title && title.length < 10 ? 'h1' : 'h3'}
|
|
||||||
title={title}
|
|
||||||
>
|
|
||||||
{titleComponent || title}
|
|
||||||
</Text>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
{hideSubtitle ? null : (
|
{subtitleComponent}
|
||||||
<div className="confirm-page-container-summary__subtitle">
|
|
||||||
{subtitleComponent}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
{showNicknamePopovers && (
|
{showNicknamePopovers && (
|
||||||
<NicknamePopovers
|
<NicknamePopovers
|
||||||
@ -163,17 +141,14 @@ const ConfirmPageContainerSummary = (props) => {
|
|||||||
|
|
||||||
ConfirmPageContainerSummary.propTypes = {
|
ConfirmPageContainerSummary.propTypes = {
|
||||||
action: PropTypes.string,
|
action: PropTypes.string,
|
||||||
title: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
||||||
image: PropTypes.string,
|
image: PropTypes.string,
|
||||||
titleComponent: PropTypes.node,
|
titleComponent: PropTypes.node,
|
||||||
subtitleComponent: PropTypes.node,
|
subtitleComponent: PropTypes.node,
|
||||||
hideSubtitle: PropTypes.bool,
|
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
tokenAddress: PropTypes.string,
|
tokenAddress: PropTypes.string,
|
||||||
toAddress: PropTypes.string,
|
toAddress: PropTypes.string,
|
||||||
nonce: PropTypes.string,
|
nonce: PropTypes.string,
|
||||||
origin: PropTypes.string.isRequired,
|
origin: PropTypes.string.isRequired,
|
||||||
hideTitle: PropTypes.bool,
|
|
||||||
transactionType: PropTypes.string,
|
transactionType: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -69,31 +69,6 @@
|
|||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__title-text {
|
|
||||||
@include H1;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__title-text-long {
|
|
||||||
@include H3;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__subtitle {
|
|
||||||
@include H5;
|
|
||||||
|
|
||||||
color: var(--color-text-alternative);
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--border {
|
&--border {
|
||||||
border-bottom: 1px solid var(--color-border-muted);
|
border-bottom: 1px solid var(--color-border-muted);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,6 @@ const ConfirmPageContainer = (props) => {
|
|||||||
image,
|
image,
|
||||||
titleComponent,
|
titleComponent,
|
||||||
subtitleComponent,
|
subtitleComponent,
|
||||||
hideSubtitle,
|
|
||||||
detailsComponent,
|
detailsComponent,
|
||||||
dataComponent,
|
dataComponent,
|
||||||
dataHexComponent,
|
dataHexComponent,
|
||||||
@ -123,11 +122,6 @@ const ConfirmPageContainer = (props) => {
|
|||||||
const shouldDisplayWarning =
|
const shouldDisplayWarning =
|
||||||
contentComponent && disabled && (errorKey || errorMessage);
|
contentComponent && disabled && (errorKey || errorMessage);
|
||||||
|
|
||||||
const hideTitle =
|
|
||||||
(currentTransaction.type === TransactionType.contractInteraction ||
|
|
||||||
currentTransaction.type === TransactionType.deployContract) &&
|
|
||||||
currentTransaction.txParams?.value === '0x0';
|
|
||||||
|
|
||||||
const networkName =
|
const networkName =
|
||||||
NETWORK_TO_NAME_MAP[currentTransaction.chainId] || networkIdentifier;
|
NETWORK_TO_NAME_MAP[currentTransaction.chainId] || networkIdentifier;
|
||||||
|
|
||||||
@ -203,7 +197,6 @@ const ConfirmPageContainer = (props) => {
|
|||||||
image={image}
|
image={image}
|
||||||
titleComponent={titleComponent}
|
titleComponent={titleComponent}
|
||||||
subtitleComponent={subtitleComponent}
|
subtitleComponent={subtitleComponent}
|
||||||
hideSubtitle={hideSubtitle}
|
|
||||||
detailsComponent={detailsComponent}
|
detailsComponent={detailsComponent}
|
||||||
dataComponent={dataComponent}
|
dataComponent={dataComponent}
|
||||||
dataHexComponent={dataHexComponent}
|
dataHexComponent={dataHexComponent}
|
||||||
@ -225,7 +218,6 @@ const ConfirmPageContainer = (props) => {
|
|||||||
rejectNText={t('rejectTxsN', [unapprovedTxCount])}
|
rejectNText={t('rejectTxsN', [unapprovedTxCount])}
|
||||||
origin={origin}
|
origin={origin}
|
||||||
ethGasPriceWarning={ethGasPriceWarning}
|
ethGasPriceWarning={ethGasPriceWarning}
|
||||||
hideTitle={hideTitle}
|
|
||||||
supportsEIP1559={supportsEIP1559}
|
supportsEIP1559={supportsEIP1559}
|
||||||
currentTransaction={currentTransaction}
|
currentTransaction={currentTransaction}
|
||||||
nativeCurrency={nativeCurrency}
|
nativeCurrency={nativeCurrency}
|
||||||
@ -341,7 +333,6 @@ const ConfirmPageContainer = (props) => {
|
|||||||
ConfirmPageContainer.propTypes = {
|
ConfirmPageContainer.propTypes = {
|
||||||
// Header
|
// Header
|
||||||
action: PropTypes.string,
|
action: PropTypes.string,
|
||||||
hideSubtitle: PropTypes.bool,
|
|
||||||
onEdit: PropTypes.func,
|
onEdit: PropTypes.func,
|
||||||
showEdit: PropTypes.bool,
|
showEdit: PropTypes.bool,
|
||||||
subtitleComponent: PropTypes.node,
|
subtitleComponent: PropTypes.node,
|
||||||
|
10
ui/components/app/confirm-subtitle/README.mdx
Normal file
10
ui/components/app/confirm-subtitle/README.mdx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { Story, Canvas, ArgsTable } from '@storybook/addon-docs';
|
||||||
|
import { ConfirmSubTitle } from '.';
|
||||||
|
|
||||||
|
# Confirm Sub Title
|
||||||
|
|
||||||
|
Confirm Sub Title is used on confirmation screen to display transaction amoutn in header.
|
||||||
|
|
||||||
|
<Canvas>
|
||||||
|
<Story id="components-app-ConfirmSubTitle--default-story" />
|
||||||
|
</Canvas>
|
56
ui/components/app/confirm-subtitle/confirm-subtitle.js
Normal file
56
ui/components/app/confirm-subtitle/confirm-subtitle.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
|
import { SECONDARY } from '../../../helpers/constants/common';
|
||||||
|
import { Text } from '../../component-library';
|
||||||
|
import {
|
||||||
|
Color,
|
||||||
|
FONT_WEIGHT,
|
||||||
|
TextVariant,
|
||||||
|
} from '../../../helpers/constants/design-system';
|
||||||
|
import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display';
|
||||||
|
import { getShouldShowFiat } from '../../../selectors';
|
||||||
|
import { useTransactionInfo } from '../../../hooks/useTransactionInfo';
|
||||||
|
|
||||||
|
const ConfirmSubTitle = ({
|
||||||
|
txData,
|
||||||
|
hexTransactionAmount,
|
||||||
|
subtitleComponent,
|
||||||
|
}) => {
|
||||||
|
const shouldShowFiat = useSelector(getShouldShowFiat);
|
||||||
|
const { isNftTransfer } = useTransactionInfo(txData);
|
||||||
|
|
||||||
|
if (!shouldShowFiat && !isNftTransfer) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subtitleComponent) {
|
||||||
|
return subtitleComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Text
|
||||||
|
as="h5"
|
||||||
|
ellipsis
|
||||||
|
fontWeight={FONT_WEIGHT.NORMAL}
|
||||||
|
variant={TextVariant.bodyMd}
|
||||||
|
color={Color.textAlternative}
|
||||||
|
>
|
||||||
|
<UserPreferencedCurrencyDisplay
|
||||||
|
value={hexTransactionAmount}
|
||||||
|
type={SECONDARY}
|
||||||
|
showEthLogo
|
||||||
|
hideLabel
|
||||||
|
/>
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ConfirmSubTitle.propTypes = {
|
||||||
|
hexTransactionAmount: PropTypes.string,
|
||||||
|
subtitleComponent: PropTypes.element,
|
||||||
|
txData: PropTypes.object.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ConfirmSubTitle;
|
@ -0,0 +1,51 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
|
||||||
|
import mockState from '../../../../test/data/mock-state.json';
|
||||||
|
import configureStore from '../../../store/store';
|
||||||
|
|
||||||
|
import README from './README.mdx';
|
||||||
|
import ConfirmSubTitle from './confirm-subtitle';
|
||||||
|
|
||||||
|
mockState.metamask.preferences.showFiatInTestnets = true;
|
||||||
|
const store = configureStore(mockState);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Components/App/ConfirmSubTitle',
|
||||||
|
|
||||||
|
component: ConfirmSubTitle,
|
||||||
|
decorators: [(story) => <Provider store={store}>{story()}</Provider>],
|
||||||
|
parameters: {
|
||||||
|
docs: {
|
||||||
|
page: README,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
txData: 'object',
|
||||||
|
hexTransactionAmount: 'number',
|
||||||
|
title: 'string',
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
txData: {
|
||||||
|
txParams: {},
|
||||||
|
type: 'transfer',
|
||||||
|
},
|
||||||
|
hexTransactionAmount: '0x9184e72a000',
|
||||||
|
subtitleComponent: undefined,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DefaultStory = (args) => {
|
||||||
|
return <ConfirmSubTitle {...args} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
DefaultStory.storyName = 'Default';
|
||||||
|
|
||||||
|
export const CustomSubTitleStory = (args) => {
|
||||||
|
return <ConfirmSubTitle {...args} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomSubTitleStory.storyName = 'CustomSubTitle';
|
||||||
|
CustomSubTitleStory.args = {
|
||||||
|
subtitleComponent: 'Any custom sub title passed',
|
||||||
|
};
|
80
ui/components/app/confirm-subtitle/confirm-subtitle.test.js
Normal file
80
ui/components/app/confirm-subtitle/confirm-subtitle.test.js
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import mockState from '../../../../test/data/mock-state.json';
|
||||||
|
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||||
|
import configureStore from '../../../store/store';
|
||||||
|
import ConfirmSubTitle from './confirm-subtitle';
|
||||||
|
|
||||||
|
describe('ConfirmSubTitle', () => {
|
||||||
|
let store;
|
||||||
|
beforeEach(() => {
|
||||||
|
mockState.metamask.preferences.showFiatInTestnets = true;
|
||||||
|
store = configureStore(mockState);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render subtitle correctly', async () => {
|
||||||
|
const { findByText } = renderWithProvider(
|
||||||
|
<ConfirmSubTitle
|
||||||
|
txData={{
|
||||||
|
txParams: {},
|
||||||
|
}}
|
||||||
|
hexTransactionAmount="0x9184e72a000"
|
||||||
|
/>,
|
||||||
|
store,
|
||||||
|
);
|
||||||
|
expect(await findByText('$0.01')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return null if showFiatInTestnets preference if false', () => {
|
||||||
|
mockState.metamask.preferences.showFiatInTestnets = false;
|
||||||
|
store = configureStore(mockState);
|
||||||
|
|
||||||
|
const { container } = renderWithProvider(
|
||||||
|
<ConfirmSubTitle
|
||||||
|
txData={{
|
||||||
|
txParams: {},
|
||||||
|
}}
|
||||||
|
hexTransactionAmount="0x9184e72a000"
|
||||||
|
/>,
|
||||||
|
store,
|
||||||
|
);
|
||||||
|
expect(container.firstChild).toStrictEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not null if showFiatInTestnets preference if false but it is NFT Transfer', async () => {
|
||||||
|
mockState.metamask.preferences.showFiatInTestnets = false;
|
||||||
|
mockState.metamask.allNftContracts = {
|
||||||
|
[mockState.metamask.selectedAddress]: {
|
||||||
|
[mockState.metamask.provider.chainId]: [{ address: '0x9' }],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
store = configureStore(mockState);
|
||||||
|
|
||||||
|
const { findByText } = renderWithProvider(
|
||||||
|
<ConfirmSubTitle
|
||||||
|
txData={{
|
||||||
|
txParams: {
|
||||||
|
to: '0x9',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
hexTransactionAmount="0x9184e72a000"
|
||||||
|
/>,
|
||||||
|
store,
|
||||||
|
);
|
||||||
|
expect(await findByText('0.00001')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render subtitleComponent if passed', () => {
|
||||||
|
const { getByText } = renderWithProvider(
|
||||||
|
<ConfirmSubTitle
|
||||||
|
txData={{
|
||||||
|
txParams: {},
|
||||||
|
}}
|
||||||
|
hexTransactionAmount="0x9184e72a000"
|
||||||
|
subtitleComponent={<div>dummy_sub_title_passed</div>}
|
||||||
|
/>,
|
||||||
|
store,
|
||||||
|
);
|
||||||
|
expect(getByText('dummy_sub_title_passed')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
1
ui/components/app/confirm-subtitle/index.js
Normal file
1
ui/components/app/confirm-subtitle/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as ConfirmSubTitle } from './confirm-subtitle';
|
10
ui/components/app/confirm-title/README.mdx
Normal file
10
ui/components/app/confirm-title/README.mdx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { Story, Canvas, ArgsTable } from '@storybook/addon-docs';
|
||||||
|
import { ConfirmTitle } from '.';
|
||||||
|
|
||||||
|
# Confirm Title
|
||||||
|
|
||||||
|
Confirm Title is used on the confirmation screen to display the transaction amount in the header.
|
||||||
|
|
||||||
|
<Canvas>
|
||||||
|
<Story id="components-app-ConfirmTitle--default-story" />
|
||||||
|
</Canvas>
|
68
ui/components/app/confirm-title/confirm-title.js
Normal file
68
ui/components/app/confirm-title/confirm-title.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import { TransactionType } from '../../../../shared/constants/transaction';
|
||||||
|
import { PRIMARY } from '../../../helpers/constants/common';
|
||||||
|
import { Text } from '../../component-library';
|
||||||
|
import {
|
||||||
|
FONT_WEIGHT,
|
||||||
|
TextVariant,
|
||||||
|
} from '../../../helpers/constants/design-system';
|
||||||
|
import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display';
|
||||||
|
|
||||||
|
const ConfirmTitle = ({ title, hexTransactionAmount, txData }) => {
|
||||||
|
const isContractInteraction =
|
||||||
|
txData.type === TransactionType.contractInteraction;
|
||||||
|
|
||||||
|
const hideTitle =
|
||||||
|
(isContractInteraction || txData.type === TransactionType.deployContract) &&
|
||||||
|
txData.txParams?.value === '0x0';
|
||||||
|
|
||||||
|
if (hideTitle) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (title) {
|
||||||
|
return (
|
||||||
|
<Text
|
||||||
|
as={title && title.length < 10 ? 'h1' : 'h3'}
|
||||||
|
ellipsis
|
||||||
|
title={title}
|
||||||
|
variant={
|
||||||
|
title && title.length < 10
|
||||||
|
? TextVariant.displayMd
|
||||||
|
: TextVariant.headingMd
|
||||||
|
}
|
||||||
|
fontWeight={FONT_WEIGHT.NORMAL}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Text
|
||||||
|
as="h3"
|
||||||
|
ellipsis
|
||||||
|
fontWeight={FONT_WEIGHT.NORMAL}
|
||||||
|
variant={TextVariant.headingMd}
|
||||||
|
>
|
||||||
|
<UserPreferencedCurrencyDisplay
|
||||||
|
ethLogoHeight={24}
|
||||||
|
hideLabel={!isContractInteraction}
|
||||||
|
showCurrencySuffix={isContractInteraction}
|
||||||
|
showEthLogo
|
||||||
|
type={PRIMARY}
|
||||||
|
value={hexTransactionAmount}
|
||||||
|
/>
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ConfirmTitle.propTypes = {
|
||||||
|
txData: PropTypes.object.isRequired,
|
||||||
|
title: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
hexTransactionAmount: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ConfirmTitle;
|
54
ui/components/app/confirm-title/confirm-title.stories.js
Normal file
54
ui/components/app/confirm-title/confirm-title.stories.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import README from './README.mdx';
|
||||||
|
import ConfirmTitle from './confirm-title';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Components/App/ConfirmTitle',
|
||||||
|
|
||||||
|
component: ConfirmTitle,
|
||||||
|
parameters: {
|
||||||
|
docs: {
|
||||||
|
page: README,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
txData: 'object',
|
||||||
|
hexTransactionAmount: 'string',
|
||||||
|
title: 'string',
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
txData: {
|
||||||
|
txParams: {},
|
||||||
|
type: 'transfer',
|
||||||
|
},
|
||||||
|
hexTransactionAmount: '0x9184e72a000',
|
||||||
|
title: undefined,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DefaultStory = (args) => {
|
||||||
|
return <ConfirmTitle {...args} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
DefaultStory.storyName = 'Default';
|
||||||
|
|
||||||
|
export const ContractInteractionStory = (args) => {
|
||||||
|
return <ConfirmTitle {...args} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
ContractInteractionStory.storyName = 'ContractInteraction';
|
||||||
|
ContractInteractionStory.args = {
|
||||||
|
txData: {
|
||||||
|
txParams: {},
|
||||||
|
type: 'contractInteraction',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CustomTitleStory = (args) => {
|
||||||
|
return <ConfirmTitle {...args} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomTitleStory.storyName = 'CustomTitle';
|
||||||
|
CustomTitleStory.args = {
|
||||||
|
title: 'Any custom title passed',
|
||||||
|
};
|
54
ui/components/app/confirm-title/confirm-title.test.js
Normal file
54
ui/components/app/confirm-title/confirm-title.test.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { TransactionType } from '../../../../shared/constants/transaction';
|
||||||
|
|
||||||
|
import mockState from '../../../../test/data/mock-state.json';
|
||||||
|
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||||
|
|
||||||
|
import configureStore from '../../../store/store';
|
||||||
|
import ConfirmTitle from './confirm-title';
|
||||||
|
|
||||||
|
describe('ConfirmTitle', () => {
|
||||||
|
const store = configureStore(mockState);
|
||||||
|
|
||||||
|
it('should render title correctly', async () => {
|
||||||
|
const { findByText } = renderWithProvider(
|
||||||
|
<ConfirmTitle
|
||||||
|
txData={{
|
||||||
|
txParams: {},
|
||||||
|
}}
|
||||||
|
hexTransactionAmount="0x9184e72a000"
|
||||||
|
/>,
|
||||||
|
store,
|
||||||
|
);
|
||||||
|
expect(await findByText('0.00001')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return null if transaction is contract interation with 0 value', () => {
|
||||||
|
const { container } = renderWithProvider(
|
||||||
|
<ConfirmTitle
|
||||||
|
txData={{
|
||||||
|
txParams: {
|
||||||
|
value: '0x0',
|
||||||
|
},
|
||||||
|
type: TransactionType.contractInteraction,
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
store,
|
||||||
|
);
|
||||||
|
expect(container.firstChild).toStrictEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render title if passed', () => {
|
||||||
|
const { getByText } = renderWithProvider(
|
||||||
|
<ConfirmTitle
|
||||||
|
txData={{
|
||||||
|
txParams: {},
|
||||||
|
}}
|
||||||
|
hexTransactionAmount="0x5"
|
||||||
|
title="dummy_title_passed"
|
||||||
|
/>,
|
||||||
|
store,
|
||||||
|
);
|
||||||
|
expect(getByText('dummy_title_passed')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
1
ui/components/app/confirm-title/index.js
Normal file
1
ui/components/app/confirm-title/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as ConfirmTitle } from './confirm-title';
|
19
ui/hooks/useTransactionInfo.js
Normal file
19
ui/hooks/useTransactionInfo.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
|
import { isEqualCaseInsensitive } from '../../shared/modules/string-utils';
|
||||||
|
|
||||||
|
export const useTransactionInfo = (txData = {}) => {
|
||||||
|
const {
|
||||||
|
allNftContracts,
|
||||||
|
selectedAddress,
|
||||||
|
provider: { chainId },
|
||||||
|
} = useSelector((state) => state.metamask);
|
||||||
|
|
||||||
|
const isNftTransfer = Boolean(
|
||||||
|
allNftContracts?.[selectedAddress]?.[chainId]?.find((contract) => {
|
||||||
|
return isEqualCaseInsensitive(contract.address, txData.txParams.to);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return { isNftTransfer };
|
||||||
|
};
|
36
ui/hooks/useTransactionInfo.test.js
Normal file
36
ui/hooks/useTransactionInfo.test.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { renderHookWithProvider } from '../../test/lib/render-helpers';
|
||||||
|
import mockState from '../../test/data/mock-state.json';
|
||||||
|
import { useTransactionInfo } from './useTransactionInfo';
|
||||||
|
|
||||||
|
describe('useTransactionInfo', () => {
|
||||||
|
describe('isNftTransfer', () => {
|
||||||
|
it('should return false if transaction is not NFT transfer', () => {
|
||||||
|
const { result } = renderHookWithProvider(
|
||||||
|
() =>
|
||||||
|
useTransactionInfo({
|
||||||
|
txParams: {},
|
||||||
|
}),
|
||||||
|
mockState,
|
||||||
|
);
|
||||||
|
expect(result.current.isNftTransfer).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
it('should return true if transaction is NFT transfer', () => {
|
||||||
|
mockState.metamask.allNftContracts = {
|
||||||
|
[mockState.metamask.selectedAddress]: {
|
||||||
|
[mockState.metamask.provider.chainId]: [{ address: '0x9' }],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const { result } = renderHookWithProvider(
|
||||||
|
() =>
|
||||||
|
useTransactionInfo({
|
||||||
|
txParams: {
|
||||||
|
to: '0x9',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
mockState,
|
||||||
|
);
|
||||||
|
expect(result.current.isNftTransfer).toStrictEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -254,7 +254,7 @@ exports[`Confirm Transaction Base should match snapshot 1`] = `
|
|||||||
class="confirm-page-container-summary__title"
|
class="confirm-page-container-summary__title"
|
||||||
>
|
>
|
||||||
<h3
|
<h3
|
||||||
class="box mm-text confirm-page-container-summary__title-text mm-text--heading-md mm-text--color-text-default box--flex-direction-row"
|
class="box mm-text mm-text--heading-md mm-text--font-weight-normal mm-text--ellipsis mm-text--color-text-default box--flex-direction-row"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="currency-display-component"
|
class="currency-display-component"
|
||||||
|
@ -58,6 +58,8 @@ import {
|
|||||||
import TransactionAlerts from '../../components/app/transaction-alerts';
|
import TransactionAlerts from '../../components/app/transaction-alerts';
|
||||||
import { ConfirmHexData } from '../../components/app/confirm-hexdata';
|
import { ConfirmHexData } from '../../components/app/confirm-hexdata';
|
||||||
import { ConfirmData } from '../../components/app/confirm-data';
|
import { ConfirmData } from '../../components/app/confirm-data';
|
||||||
|
import { ConfirmTitle } from '../../components/app/confirm-title';
|
||||||
|
import { ConfirmSubTitle } from '../../components/app/confirm-subtitle';
|
||||||
|
|
||||||
const renderHeartBeatIfNotInTest = () =>
|
const renderHeartBeatIfNotInTest = () =>
|
||||||
process.env.IN_TEST ? null : <LoadingHeartBeat />;
|
process.env.IN_TEST ? null : <LoadingHeartBeat />;
|
||||||
@ -108,7 +110,6 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
contentComponent: PropTypes.node,
|
contentComponent: PropTypes.node,
|
||||||
dataComponent: PropTypes.node,
|
dataComponent: PropTypes.node,
|
||||||
dataHexComponent: PropTypes.node,
|
dataHexComponent: PropTypes.node,
|
||||||
hideSubtitle: PropTypes.bool,
|
|
||||||
tokenAddress: PropTypes.string,
|
tokenAddress: PropTypes.string,
|
||||||
customTokenAmount: PropTypes.string,
|
customTokenAmount: PropTypes.string,
|
||||||
dappProposedTokenAmount: PropTypes.string,
|
dappProposedTokenAmount: PropTypes.string,
|
||||||
@ -837,38 +838,24 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
renderTitleComponent() {
|
renderTitleComponent() {
|
||||||
const { title, hexTransactionAmount, txData } = this.props;
|
const { title, hexTransactionAmount, txData } = this.props;
|
||||||
|
|
||||||
// Title string passed in by props takes priority
|
|
||||||
if (title) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isContractInteraction =
|
|
||||||
txData.type === TransactionType.contractInteraction;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UserPreferencedCurrencyDisplay
|
<ConfirmTitle
|
||||||
value={hexTransactionAmount}
|
title={title}
|
||||||
type={PRIMARY}
|
hexTransactionAmount={hexTransactionAmount}
|
||||||
showEthLogo
|
txData={txData}
|
||||||
ethLogoHeight={24}
|
|
||||||
hideLabel={!isContractInteraction}
|
|
||||||
showCurrencySuffix={isContractInteraction}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSubtitleComponent() {
|
renderSubtitleComponent() {
|
||||||
const { subtitleComponent, hexTransactionAmount } = this.props;
|
const { subtitleComponent, hexTransactionAmount, txData } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
subtitleComponent || (
|
<ConfirmSubTitle
|
||||||
<UserPreferencedCurrencyDisplay
|
hexTransactionAmount={hexTransactionAmount}
|
||||||
value={hexTransactionAmount}
|
subtitleComponent={subtitleComponent}
|
||||||
type={SECONDARY}
|
txData={txData}
|
||||||
showEthLogo
|
/>
|
||||||
hideLabel
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -946,8 +933,6 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
toEns,
|
toEns,
|
||||||
toNickname,
|
toNickname,
|
||||||
methodData,
|
methodData,
|
||||||
title,
|
|
||||||
hideSubtitle,
|
|
||||||
tokenAddress,
|
tokenAddress,
|
||||||
contentComponent,
|
contentComponent,
|
||||||
onEdit,
|
onEdit,
|
||||||
@ -1024,11 +1009,9 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
toNickname={toNickname}
|
toNickname={toNickname}
|
||||||
showEdit={!isContractInteractionFromDapp && Boolean(onEdit)}
|
showEdit={!isContractInteractionFromDapp && Boolean(onEdit)}
|
||||||
action={functionType}
|
action={functionType}
|
||||||
title={title}
|
|
||||||
image={image}
|
image={image}
|
||||||
titleComponent={this.renderTitleComponent()}
|
titleComponent={this.renderTitleComponent()}
|
||||||
subtitleComponent={this.renderSubtitleComponent()}
|
subtitleComponent={this.renderSubtitleComponent()}
|
||||||
hideSubtitle={hideSubtitle}
|
|
||||||
detailsComponent={this.renderDetails()}
|
detailsComponent={this.renderDetails()}
|
||||||
dataComponent={this.renderData(functionType)}
|
dataComponent={this.renderData(functionType)}
|
||||||
dataHexComponent={this.renderDataHex(functionType)}
|
dataHexComponent={this.renderDataHex(functionType)}
|
||||||
|
@ -63,7 +63,6 @@ import {
|
|||||||
TransactionStatus,
|
TransactionStatus,
|
||||||
TransactionType,
|
TransactionType,
|
||||||
} from '../../../shared/constants/transaction';
|
} from '../../../shared/constants/transaction';
|
||||||
import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
|
|
||||||
import { getTokenAddressParam } from '../../helpers/utils/token-util';
|
import { getTokenAddressParam } from '../../helpers/utils/token-util';
|
||||||
import { calcGasTotal } from '../../../shared/lib/transactions-controller-utils';
|
import { calcGasTotal } from '../../../shared/lib/transactions-controller-utils';
|
||||||
import ConfirmTransactionBase from './confirm-transaction-base.component';
|
import ConfirmTransactionBase from './confirm-transaction-base.component';
|
||||||
@ -105,8 +104,6 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
network,
|
network,
|
||||||
unapprovedTxs,
|
unapprovedTxs,
|
||||||
nextNonce,
|
nextNonce,
|
||||||
allNftContracts,
|
|
||||||
selectedAddress,
|
|
||||||
provider: { chainId },
|
provider: { chainId },
|
||||||
} = metamask;
|
} = metamask;
|
||||||
const { tokenData, txData, tokenProps, nonce } = confirmTransaction;
|
const { tokenData, txData, tokenProps, nonce } = confirmTransaction;
|
||||||
@ -184,12 +181,6 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
customTxParamsData,
|
customTxParamsData,
|
||||||
);
|
);
|
||||||
|
|
||||||
const isNftTransfer = Boolean(
|
|
||||||
allNftContracts?.[selectedAddress]?.[chainId]?.find((contract) => {
|
|
||||||
return isEqualCaseInsensitive(contract.address, fullTxData.txParams.to);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
customNonceValue = getCustomNonceValue(state);
|
customNonceValue = getCustomNonceValue(state);
|
||||||
const isEthGasPrice = getIsEthGasPriceFetched(state);
|
const isEthGasPrice = getIsEthGasPriceFetched(state);
|
||||||
const noGasPrice = !supportsEIP1559 && getNoGasPriceFetched(state);
|
const noGasPrice = !supportsEIP1559 && getNoGasPriceFetched(state);
|
||||||
@ -235,7 +226,6 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
useNonceField: getUseNonceField(state),
|
useNonceField: getUseNonceField(state),
|
||||||
customNonceValue,
|
customNonceValue,
|
||||||
insufficientBalance,
|
insufficientBalance,
|
||||||
hideSubtitle: !getShouldShowFiat(state) && !isNftTransfer,
|
|
||||||
hideFiatConversion: !getShouldShowFiat(state),
|
hideFiatConversion: !getShouldShowFiat(state),
|
||||||
type,
|
type,
|
||||||
nextNonce,
|
nextNonce,
|
||||||
|
Loading…
Reference in New Issue
Block a user