Review spending cap screen (#15919)
parent
d97b9c7eef
commit
a993509afc
@ -0,0 +1,241 @@ |
|||||||
|
import React, { useContext } from 'react'; |
||||||
|
import PropTypes from 'prop-types'; |
||||||
|
import classnames from 'classnames'; |
||||||
|
import Box from '../../ui/box/box'; |
||||||
|
import Button from '../../ui/button'; |
||||||
|
import EditGasFeeButton from '../edit-gas-fee-button/edit-gas-fee-button'; |
||||||
|
import Typography from '../../ui/typography/typography'; |
||||||
|
import { |
||||||
|
ALIGN_ITEMS, |
||||||
|
BLOCK_SIZES, |
||||||
|
COLORS, |
||||||
|
DISPLAY, |
||||||
|
FLEX_DIRECTION, |
||||||
|
FONT_WEIGHT, |
||||||
|
JUSTIFY_CONTENT, |
||||||
|
TEXT_ALIGN, |
||||||
|
TYPOGRAPHY, |
||||||
|
} from '../../../helpers/constants/design-system'; |
||||||
|
import { I18nContext } from '../../../../.storybook/i18n'; |
||||||
|
import GasDetailsItem from '../gas-details-item/gas-details-item'; |
||||||
|
import MultiLayerFeeMessage from '../multilayer-fee-message/multi-layer-fee-message'; |
||||||
|
import { formatCurrency } from '../../../helpers/utils/confirm-tx.util'; |
||||||
|
|
||||||
|
export default function ApproveContentCard({ |
||||||
|
showHeader = true, |
||||||
|
symbol, |
||||||
|
title, |
||||||
|
showEdit, |
||||||
|
showAdvanceGasFeeOptions = false, |
||||||
|
onEditClick, |
||||||
|
footer, |
||||||
|
noBorder, |
||||||
|
supportsEIP1559V2, |
||||||
|
renderTransactionDetailsContent, |
||||||
|
renderDataContent, |
||||||
|
isMultiLayerFeeNetwork, |
||||||
|
ethTransactionTotal, |
||||||
|
nativeCurrency, |
||||||
|
fullTxData, |
||||||
|
hexTransactionTotal, |
||||||
|
fiatTransactionTotal, |
||||||
|
currentCurrency, |
||||||
|
isSetApproveForAll, |
||||||
|
isApprovalOrRejection, |
||||||
|
data, |
||||||
|
}) { |
||||||
|
const t = useContext(I18nContext); |
||||||
|
|
||||||
|
return ( |
||||||
|
<Box |
||||||
|
className={classnames({ |
||||||
|
'approve-content-card-container__card': !noBorder, |
||||||
|
'approve-content-card-container__card--no-border': noBorder, |
||||||
|
})} |
||||||
|
> |
||||||
|
{showHeader && ( |
||||||
|
<Box |
||||||
|
display={DISPLAY.FLEX} |
||||||
|
flexDirection={FLEX_DIRECTION.ROW} |
||||||
|
alignItems={ALIGN_ITEMS.CENTER} |
||||||
|
justifyContent={JUSTIFY_CONTENT.FLEX_END} |
||||||
|
className="approve-content-card-container__card-header" |
||||||
|
> |
||||||
|
{supportsEIP1559V2 && title === t('transactionFee') ? null : ( |
||||||
|
<> |
||||||
|
<Box className="approve-content-card-container__card-header__symbol"> |
||||||
|
{symbol} |
||||||
|
</Box> |
||||||
|
<Box |
||||||
|
marginLeft={4} |
||||||
|
className="approve-content-card-container__card-header__title" |
||||||
|
> |
||||||
|
<Typography |
||||||
|
variant={TYPOGRAPHY.H6} |
||||||
|
fontWeight={FONT_WEIGHT.BOLD} |
||||||
|
> |
||||||
|
{title} |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
|
</> |
||||||
|
)} |
||||||
|
{showEdit && (!showAdvanceGasFeeOptions || !supportsEIP1559V2) && ( |
||||||
|
<Box width={BLOCK_SIZES.ONE_SIXTH}> |
||||||
|
<Button type="link" onClick={() => onEditClick()}> |
||||||
|
<Typography |
||||||
|
variant={TYPOGRAPHY.H7} |
||||||
|
color={COLORS.PRIMARY_DEFAULT} |
||||||
|
> |
||||||
|
{t('edit')} |
||||||
|
</Typography> |
||||||
|
</Button> |
||||||
|
</Box> |
||||||
|
)} |
||||||
|
{showEdit && showAdvanceGasFeeOptions && supportsEIP1559V2 && ( |
||||||
|
<EditGasFeeButton /> |
||||||
|
)} |
||||||
|
</Box> |
||||||
|
)} |
||||||
|
<Box |
||||||
|
marginTop={1} |
||||||
|
marginBottom={3} |
||||||
|
className="approve-content-card-container__card-content" |
||||||
|
> |
||||||
|
{renderTransactionDetailsContent && |
||||||
|
(!isMultiLayerFeeNetwork && supportsEIP1559V2 ? ( |
||||||
|
<GasDetailsItem /> |
||||||
|
) : ( |
||||||
|
<Box |
||||||
|
display={DISPLAY.FLEX} |
||||||
|
flexDirection={FLEX_DIRECTION.ROW} |
||||||
|
justifyContent={JUSTIFY_CONTENT.SPACE_BETWEEN} |
||||||
|
> |
||||||
|
{isMultiLayerFeeNetwork ? ( |
||||||
|
<Box |
||||||
|
display={DISPLAY.FLEX} |
||||||
|
flexDirection={FLEX_DIRECTION.COLUMN} |
||||||
|
className="approve-content-card-container__transaction-details-extra-content" |
||||||
|
> |
||||||
|
<Box |
||||||
|
display={DISPLAY.FLEX} |
||||||
|
justifyContent={JUSTIFY_CONTENT.SPACE_BETWEEN} |
||||||
|
> |
||||||
|
<Typography |
||||||
|
variant={TYPOGRAPHY.H6} |
||||||
|
fontWeight={FONT_WEIGHT.NORMAL} |
||||||
|
color={COLORS.TEXT_MUTED} |
||||||
|
> |
||||||
|
<span>{t('transactionDetailLayer2GasHeading')}</span> |
||||||
|
{`${ethTransactionTotal} ${nativeCurrency}`} |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
|
<MultiLayerFeeMessage |
||||||
|
transaction={fullTxData} |
||||||
|
layer2fee={hexTransactionTotal} |
||||||
|
nativeCurrency={nativeCurrency} |
||||||
|
plainStyle |
||||||
|
/> |
||||||
|
</Box> |
||||||
|
) : ( |
||||||
|
<> |
||||||
|
<Box> |
||||||
|
<Typography |
||||||
|
variant={TYPOGRAPHY.H7} |
||||||
|
color={COLORS.TEXT_ALTERNATIVE} |
||||||
|
> |
||||||
|
{t('feeAssociatedRequest')} |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
|
<Box |
||||||
|
display={DISPLAY.FLEX} |
||||||
|
flexDirection={FLEX_DIRECTION.COLUMN} |
||||||
|
alignItems={ALIGN_ITEMS.FLEX_END} |
||||||
|
textAlign={TEXT_ALIGN.RIGHT} |
||||||
|
> |
||||||
|
<Box> |
||||||
|
<Typography |
||||||
|
variant={TYPOGRAPHY.H4} |
||||||
|
fontWeight={FONT_WEIGHT.BOLD} |
||||||
|
color={COLORS.TEXT_DEFAULT} |
||||||
|
> |
||||||
|
{formatCurrency(fiatTransactionTotal, currentCurrency)} |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
|
<Box> |
||||||
|
<Typography |
||||||
|
variant={TYPOGRAPHY.H6} |
||||||
|
fontWeight={FONT_WEIGHT.NORMAL} |
||||||
|
color={COLORS.TEXT_MUTED} |
||||||
|
> |
||||||
|
{`${ethTransactionTotal} ${nativeCurrency}`} |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
|
</Box> |
||||||
|
</> |
||||||
|
)} |
||||||
|
</Box> |
||||||
|
))} |
||||||
|
{renderDataContent && ( |
||||||
|
<Box display={DISPLAY.FLEX} flexDirection={FLEX_DIRECTION.COLUMN}> |
||||||
|
<Box> |
||||||
|
<Typography |
||||||
|
variant={TYPOGRAPHY.H7} |
||||||
|
color={COLORS.TEXT_ALTERNATIVE} |
||||||
|
> |
||||||
|
{isSetApproveForAll |
||||||
|
? t('functionSetApprovalForAll') |
||||||
|
: t('functionApprove')} |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
|
{isSetApproveForAll && isApprovalOrRejection !== undefined ? ( |
||||||
|
<Box> |
||||||
|
<Typography |
||||||
|
variant={TYPOGRAPHY.H7} |
||||||
|
color={COLORS.TEXT_ALTERNATIVE} |
||||||
|
> |
||||||
|
{`${t('parameters')}: ${isApprovalOrRejection}`} |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
|
) : null} |
||||||
|
<Box |
||||||
|
marginRight={4} |
||||||
|
className="approve-content-card-container__data__data-block" |
||||||
|
> |
||||||
|
<Typography |
||||||
|
variant={TYPOGRAPHY.H7} |
||||||
|
color={COLORS.TEXT_ALTERNATIVE} |
||||||
|
> |
||||||
|
{data} |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
|
</Box> |
||||||
|
)} |
||||||
|
</Box> |
||||||
|
{footer} |
||||||
|
</Box> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
ApproveContentCard.propTypes = { |
||||||
|
showHeader: PropTypes.bool, |
||||||
|
symbol: PropTypes.node, |
||||||
|
title: PropTypes.string, |
||||||
|
showEdit: PropTypes.bool, |
||||||
|
showAdvanceGasFeeOptions: PropTypes.bool, |
||||||
|
onEditClick: PropTypes.func, |
||||||
|
footer: PropTypes.node, |
||||||
|
noBorder: PropTypes.bool, |
||||||
|
supportsEIP1559V2: PropTypes.bool, |
||||||
|
renderTransactionDetailsContent: PropTypes.bool, |
||||||
|
renderDataContent: PropTypes.bool, |
||||||
|
isMultiLayerFeeNetwork: PropTypes.bool, |
||||||
|
ethTransactionTotal: PropTypes.string, |
||||||
|
nativeCurrency: PropTypes.string, |
||||||
|
fullTxData: PropTypes.object, |
||||||
|
hexTransactionTotal: PropTypes.string, |
||||||
|
fiatTransactionTotal: PropTypes.string, |
||||||
|
currentCurrency: PropTypes.string, |
||||||
|
isSetApproveForAll: PropTypes.bool, |
||||||
|
isApprovalOrRejection: PropTypes.bool, |
||||||
|
data: PropTypes.string, |
||||||
|
}; |
@ -0,0 +1 @@ |
|||||||
|
export { default } from './approve-content-card'; |
@ -0,0 +1,51 @@ |
|||||||
|
.approve-content-card-container { |
||||||
|
&__card, |
||||||
|
&__card--no-border { |
||||||
|
border-bottom: 1px solid var(--color-border-default); |
||||||
|
position: relative; |
||||||
|
padding-inline-start: 24px; |
||||||
|
padding-inline-end: 24px; |
||||||
|
} |
||||||
|
|
||||||
|
&__card--no-border { |
||||||
|
border-bottom: none; |
||||||
|
} |
||||||
|
|
||||||
|
&__card-header { |
||||||
|
position: relative; |
||||||
|
|
||||||
|
&__symbol { |
||||||
|
width: auto; |
||||||
|
} |
||||||
|
|
||||||
|
&__symbol--aligned { |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
&__title { |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
&__title--aligned { |
||||||
|
margin-inline-start: 27px; |
||||||
|
position: absolute; |
||||||
|
width: auto; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&__card-content--aligned { |
||||||
|
margin-inline-start: 42px; |
||||||
|
} |
||||||
|
|
||||||
|
&__transaction-details-extra-content { |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
&__data { |
||||||
|
width: 100%; |
||||||
|
|
||||||
|
&__data-block { |
||||||
|
overflow-wrap: break-word; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
export { default } from './token-allowance'; |
@ -0,0 +1,41 @@ |
|||||||
|
.token-allowance-container { |
||||||
|
&__icon-display-content { |
||||||
|
width: fit-content; |
||||||
|
height: 40px; |
||||||
|
box-sizing: border-box; |
||||||
|
border-radius: 100px; |
||||||
|
position: relative; |
||||||
|
|
||||||
|
&__siteimage-identicon { |
||||||
|
width: 24px; |
||||||
|
height: 24px; |
||||||
|
box-shadow: none; |
||||||
|
background: none; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
a.token-allowance-container__verify-link { |
||||||
|
width: fit-content; |
||||||
|
margin-inline-start: 96px; |
||||||
|
margin-inline-end: 96px; |
||||||
|
padding: 0; |
||||||
|
} |
||||||
|
|
||||||
|
a.token-allowance-container__view-details { |
||||||
|
width: fit-content; |
||||||
|
margin-inline-start: 108px; |
||||||
|
margin-inline-end: 108px; |
||||||
|
} |
||||||
|
|
||||||
|
&__card-wrapper { |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
&__data { |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
&__full-tx-content { |
||||||
|
max-width: 100%; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,437 @@ |
|||||||
|
import React, { useState, useContext } from 'react'; |
||||||
|
import { useDispatch, useSelector } from 'react-redux'; |
||||||
|
import { useHistory } from 'react-router-dom'; |
||||||
|
import PropTypes from 'prop-types'; |
||||||
|
import Box from '../../components/ui/box/box'; |
||||||
|
import NetworkAccountBalanceHeader from '../../components/app/network-account-balance-header/network-account-balance-header'; |
||||||
|
import UrlIcon from '../../components/ui/url-icon/url-icon'; |
||||||
|
import Typography from '../../components/ui/typography/typography'; |
||||||
|
import { |
||||||
|
ALIGN_ITEMS, |
||||||
|
BORDER_STYLE, |
||||||
|
COLORS, |
||||||
|
DISPLAY, |
||||||
|
FLEX_DIRECTION, |
||||||
|
FONT_WEIGHT, |
||||||
|
JUSTIFY_CONTENT, |
||||||
|
TEXT_ALIGN, |
||||||
|
TYPOGRAPHY, |
||||||
|
} from '../../helpers/constants/design-system'; |
||||||
|
import { I18nContext } from '../../contexts/i18n'; |
||||||
|
import ContractTokenValues from '../../components/ui/contract-token-values/contract-token-values'; |
||||||
|
import Button from '../../components/ui/button'; |
||||||
|
import ReviewSpendingCap from '../../components/ui/review-spending-cap/review-spending-cap'; |
||||||
|
import { PageContainerFooter } from '../../components/ui/page-container'; |
||||||
|
import ContractDetailsModal from '../../components/app/modals/contract-details-modal/contract-details-modal'; |
||||||
|
import { |
||||||
|
getCurrentAccountWithSendEtherInfo, |
||||||
|
getNetworkIdentifier, |
||||||
|
transactionFeeSelector, |
||||||
|
getKnownMethodData, |
||||||
|
getRpcPrefsForCurrentProvider, |
||||||
|
} from '../../selectors'; |
||||||
|
import { NETWORK_TO_NAME_MAP } from '../../../shared/constants/network'; |
||||||
|
import { |
||||||
|
cancelTx, |
||||||
|
updateAndApproveTx, |
||||||
|
updateCustomNonce, |
||||||
|
} from '../../store/actions'; |
||||||
|
import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck'; |
||||||
|
import { getMostRecentOverviewPage } from '../../ducks/history/history'; |
||||||
|
import ApproveContentCard from '../../components/app/approve-content-card/approve-content-card'; |
||||||
|
|
||||||
|
export default function TokenAllowance({ |
||||||
|
origin, |
||||||
|
siteImage, |
||||||
|
showCustomizeGasModal, |
||||||
|
useNonceField, |
||||||
|
currentCurrency, |
||||||
|
nativeCurrency, |
||||||
|
ethTransactionTotal, |
||||||
|
fiatTransactionTotal, |
||||||
|
hexTransactionTotal, |
||||||
|
txData, |
||||||
|
isMultiLayerFeeNetwork, |
||||||
|
supportsEIP1559V2, |
||||||
|
userAddress, |
||||||
|
tokenAddress, |
||||||
|
data, |
||||||
|
isSetApproveForAll, |
||||||
|
isApprovalOrRejection, |
||||||
|
customTxParamsData, |
||||||
|
dappProposedTokenAmount, |
||||||
|
currentTokenBalance, |
||||||
|
toAddress, |
||||||
|
tokenSymbol, |
||||||
|
}) { |
||||||
|
const t = useContext(I18nContext); |
||||||
|
const dispatch = useDispatch(); |
||||||
|
const history = useHistory(); |
||||||
|
const mostRecentOverviewPage = useSelector(getMostRecentOverviewPage); |
||||||
|
|
||||||
|
const [showContractDetails, setShowContractDetails] = useState(false); |
||||||
|
const [showFullTxDetails, setShowFullTxDetails] = useState(false); |
||||||
|
const [isFirstPage, setIsFirstPage] = useState(false); |
||||||
|
|
||||||
|
const currentAccount = useSelector(getCurrentAccountWithSendEtherInfo); |
||||||
|
const networkIdentifier = useSelector(getNetworkIdentifier); |
||||||
|
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); |
||||||
|
|
||||||
|
let fullTxData = { ...txData }; |
||||||
|
|
||||||
|
if (customTxParamsData) { |
||||||
|
fullTxData = { |
||||||
|
...fullTxData, |
||||||
|
txParams: { |
||||||
|
...fullTxData.txParams, |
||||||
|
data: customTxParamsData, |
||||||
|
}, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
const fee = useSelector((state) => transactionFeeSelector(state, fullTxData)); |
||||||
|
const methodData = useSelector((state) => getKnownMethodData(state, data)); |
||||||
|
|
||||||
|
const networkName = |
||||||
|
NETWORK_TO_NAME_MAP[fullTxData.chainId] || networkIdentifier; |
||||||
|
|
||||||
|
const customNonceValue = ''; |
||||||
|
const customNonceMerge = (transactionData) => |
||||||
|
customNonceValue |
||||||
|
? { |
||||||
|
...transactionData, |
||||||
|
customNonceValue, |
||||||
|
} |
||||||
|
: transactionData; |
||||||
|
|
||||||
|
const handleReject = () => { |
||||||
|
dispatch(cancelTx(fullTxData)).then(() => { |
||||||
|
dispatch(clearConfirmTransaction()); |
||||||
|
dispatch(updateCustomNonce('')); |
||||||
|
history.push(mostRecentOverviewPage); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
const handleApprove = () => { |
||||||
|
const { name } = methodData; |
||||||
|
|
||||||
|
if (fee.gasEstimationObject.baseFeePerGas) { |
||||||
|
fullTxData.estimatedBaseFee = fee.gasEstimationObject.baseFeePerGas; |
||||||
|
} |
||||||
|
|
||||||
|
if (name) { |
||||||
|
fullTxData.contractMethodName = name; |
||||||
|
} |
||||||
|
|
||||||
|
if (dappProposedTokenAmount) { |
||||||
|
fullTxData.dappProposedTokenAmount = dappProposedTokenAmount; |
||||||
|
fullTxData.originalApprovalAmount = dappProposedTokenAmount; |
||||||
|
} |
||||||
|
|
||||||
|
if (currentTokenBalance) { |
||||||
|
fullTxData.currentTokenBalance = currentTokenBalance; |
||||||
|
} |
||||||
|
|
||||||
|
dispatch(updateAndApproveTx(customNonceMerge(fullTxData))).then(() => { |
||||||
|
dispatch(clearConfirmTransaction()); |
||||||
|
dispatch(updateCustomNonce('')); |
||||||
|
history.push(mostRecentOverviewPage); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
return ( |
||||||
|
<Box className="token-allowance-container page-container"> |
||||||
|
<Box |
||||||
|
paddingLeft={4} |
||||||
|
paddingRight={4} |
||||||
|
alignItems={ALIGN_ITEMS.CENTER} |
||||||
|
display={DISPLAY.FLEX} |
||||||
|
flexDirection={FLEX_DIRECTION.ROW} |
||||||
|
justifyContent={JUSTIFY_CONTENT.SPACE_BETWEEN} |
||||||
|
> |
||||||
|
<Box> |
||||||
|
{!isFirstPage && ( |
||||||
|
<Button type="inline" onClick={() => setIsFirstPage(true)}> |
||||||
|
<Typography |
||||||
|
variant={TYPOGRAPHY.H6} |
||||||
|
color={COLORS.TEXT_MUTED} |
||||||
|
fontWeight={FONT_WEIGHT.BOLD} |
||||||
|
> |
||||||
|
{'<'} {t('back')} |
||||||
|
</Typography> |
||||||
|
</Button> |
||||||
|
)} |
||||||
|
</Box> |
||||||
|
<Box textAlign={TEXT_ALIGN.END}> |
||||||
|
<Typography |
||||||
|
variant={TYPOGRAPHY.H7} |
||||||
|
color={COLORS.TEXT_MUTED} |
||||||
|
fontWeight={FONT_WEIGHT.BOLD} |
||||||
|
> |
||||||
|
{isFirstPage ? 1 : 2} {t('ofTextNofM')} 2 |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
|
</Box> |
||||||
|
<NetworkAccountBalanceHeader |
||||||
|
networkName={networkName} |
||||||
|
accountName={currentAccount.name} |
||||||
|
accountBalance={currentTokenBalance} |
||||||
|
tokenName={tokenSymbol} |
||||||
|
accountAddress={userAddress} |
||||||
|
/> |
||||||
|
<Box |
||||||
|
display={DISPLAY.FLEX} |
||||||
|
flexDirection={FLEX_DIRECTION.ROW} |
||||||
|
justifyContent={JUSTIFY_CONTENT.CENTER} |
||||||
|
> |
||||||
|
<Box |
||||||
|
display={DISPLAY.FLEX} |
||||||
|
alignItems={ALIGN_ITEMS.CENTER} |
||||||
|
marginTop={6} |
||||||
|
marginRight={12} |
||||||
|
marginBottom={8} |
||||||
|
marginLeft={12} |
||||||
|
paddingTop={2} |
||||||
|
paddingRight={4} |
||||||
|
paddingBottom={2} |
||||||
|
paddingLeft={2} |
||||||
|
borderColor={COLORS.BORDER_MUTED} |
||||||
|
borderStyle={BORDER_STYLE.SOLID} |
||||||
|
borderWidth={1} |
||||||
|
className="token-allowance-container__icon-display-content" |
||||||
|
> |
||||||
|
<UrlIcon |
||||||
|
className="token-allowance-container__icon-display-content__siteimage-identicon" |
||||||
|
fallbackClassName="token-allowance-container__icon-display-content__siteimage-identicon" |
||||||
|
name={origin} |
||||||
|
url={siteImage} |
||||||
|
/> |
||||||
|
<Typography |
||||||
|
variant={TYPOGRAPHY.H6} |
||||||
|
fontWeight={FONT_WEIGHT.NORMAL} |
||||||
|
color={COLORS.TEXT_ALTERNATIVE} |
||||||
|
boxProps={{ marginLeft: 1, marginTop: 2 }} |
||||||
|
> |
||||||
|
{origin} |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
|
</Box> |
||||||
|
<Box marginBottom={5}> |
||||||
|
<Typography |
||||||
|
variant={TYPOGRAPHY.H3} |
||||||
|
fontWeight={FONT_WEIGHT.BOLD} |
||||||
|
align={TEXT_ALIGN.CENTER} |
||||||
|
> |
||||||
|
{isFirstPage ? t('setSpendingCap') : t('reviewSpendingCap')} |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
|
<Box> |
||||||
|
<ContractTokenValues |
||||||
|
tokenName={tokenSymbol} |
||||||
|
address={tokenAddress} |
||||||
|
chainId={fullTxData.chainId} |
||||||
|
rpcPrefs={rpcPrefs} |
||||||
|
/> |
||||||
|
</Box> |
||||||
|
<Box |
||||||
|
marginTop={1} |
||||||
|
display={DISPLAY.FLEX} |
||||||
|
flexDirection={FLEX_DIRECTION.ROW} |
||||||
|
justifyContent={JUSTIFY_CONTENT.CENTER} |
||||||
|
> |
||||||
|
<Button |
||||||
|
type="link" |
||||||
|
onClick={() => setShowContractDetails(true)} |
||||||
|
className="token-allowance-container__verify-link" |
||||||
|
> |
||||||
|
<Typography variant={TYPOGRAPHY.H6} color={COLORS.PRIMARY_DEFAULT}> |
||||||
|
{t('verifyContractDetails')} |
||||||
|
</Typography> |
||||||
|
</Button> |
||||||
|
</Box> |
||||||
|
<Box margin={[4, 4, 3, 4]}> |
||||||
|
<ReviewSpendingCap |
||||||
|
tokenName={tokenSymbol} |
||||||
|
currentTokenBalance={parseFloat(currentTokenBalance)} |
||||||
|
tokenValue={10} |
||||||
|
onEdit={() => setIsFirstPage(true)} |
||||||
|
/> |
||||||
|
</Box> |
||||||
|
{!isFirstPage && ( |
||||||
|
<Box className="token-allowance-container__card-wrapper"> |
||||||
|
<ApproveContentCard |
||||||
|
symbol={<i className="fa fa-tag" />} |
||||||
|
title={t('transactionFee')} |
||||||
|
showEdit |
||||||
|
showAdvanceGasFeeOptions |
||||||
|
onEditClick={showCustomizeGasModal} |
||||||
|
renderTransactionDetailsContent |
||||||
|
noBorder={useNonceField || !showFullTxDetails} |
||||||
|
supportsEIP1559V2={supportsEIP1559V2} |
||||||
|
isMultiLayerFeeNetwork={isMultiLayerFeeNetwork} |
||||||
|
ethTransactionTotal={ethTransactionTotal} |
||||||
|
nativeCurrency={nativeCurrency} |
||||||
|
fullTxData={fullTxData} |
||||||
|
hexTransactionTotal={hexTransactionTotal} |
||||||
|
fiatTransactionTotal={fiatTransactionTotal} |
||||||
|
currentCurrency={currentCurrency} |
||||||
|
/> |
||||||
|
</Box> |
||||||
|
)} |
||||||
|
<Box |
||||||
|
display={DISPLAY.FLEX} |
||||||
|
flexDirection={FLEX_DIRECTION.ROW} |
||||||
|
justifyContent={JUSTIFY_CONTENT.CENTER} |
||||||
|
> |
||||||
|
<Button |
||||||
|
type="link" |
||||||
|
onClick={() => setShowFullTxDetails(!showFullTxDetails)} |
||||||
|
className="token-allowance-container__view-details" |
||||||
|
> |
||||||
|
<Typography |
||||||
|
variant={TYPOGRAPHY.H6} |
||||||
|
color={COLORS.PRIMARY_DEFAULT} |
||||||
|
marginRight={1} |
||||||
|
> |
||||||
|
{t('viewDetails')} |
||||||
|
</Typography> |
||||||
|
{showFullTxDetails ? ( |
||||||
|
<i className="fa fa-sm fa-angle-up" /> |
||||||
|
) : ( |
||||||
|
<i className="fa fa-sm fa-angle-down" /> |
||||||
|
)} |
||||||
|
</Button> |
||||||
|
</Box> |
||||||
|
{showFullTxDetails ? ( |
||||||
|
<Box |
||||||
|
display={DISPLAY.FLEX} |
||||||
|
flexDirection={FLEX_DIRECTION.COLUMN} |
||||||
|
alignItems={ALIGN_ITEMS.CENTER} |
||||||
|
className="token-allowance-container__full-tx-content" |
||||||
|
> |
||||||
|
<Box className="token-allowance-container__data"> |
||||||
|
<ApproveContentCard |
||||||
|
symbol={<i className="fa fa-file" />} |
||||||
|
title={t('data')} |
||||||
|
renderDataContent |
||||||
|
noBorder |
||||||
|
supportsEIP1559V2={supportsEIP1559V2} |
||||||
|
isSetApproveForAll={isSetApproveForAll} |
||||||
|
isApprovalOrRejection={isApprovalOrRejection} |
||||||
|
data={data} |
||||||
|
/> |
||||||
|
</Box> |
||||||
|
</Box> |
||||||
|
) : null} |
||||||
|
<PageContainerFooter |
||||||
|
cancelText={t('reject')} |
||||||
|
submitText={isFirstPage ? t('next') : t('approveButtonText')} |
||||||
|
onCancel={() => handleReject()} |
||||||
|
onSubmit={() => (isFirstPage ? setIsFirstPage(false) : handleApprove())} |
||||||
|
/> |
||||||
|
{showContractDetails && ( |
||||||
|
<ContractDetailsModal |
||||||
|
tokenName={tokenSymbol} |
||||||
|
onClose={() => setShowContractDetails(false)} |
||||||
|
tokenAddress={tokenAddress} |
||||||
|
toAddress={toAddress} |
||||||
|
chainId={fullTxData.chainId} |
||||||
|
rpcPrefs={rpcPrefs} |
||||||
|
origin={origin} |
||||||
|
siteImage={siteImage} |
||||||
|
/> |
||||||
|
)} |
||||||
|
</Box> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
TokenAllowance.propTypes = { |
||||||
|
/** |
||||||
|
* Dapp URL |
||||||
|
*/ |
||||||
|
origin: PropTypes.string, |
||||||
|
/** |
||||||
|
* Dapp image |
||||||
|
*/ |
||||||
|
siteImage: PropTypes.string, |
||||||
|
/** |
||||||
|
* Function that is supposed to open the customized gas modal |
||||||
|
*/ |
||||||
|
showCustomizeGasModal: PropTypes.func, |
||||||
|
/** |
||||||
|
* Whether nonce field should be used or not |
||||||
|
*/ |
||||||
|
useNonceField: PropTypes.bool, |
||||||
|
/** |
||||||
|
* Current fiat currency (e.g. USD) |
||||||
|
*/ |
||||||
|
currentCurrency: PropTypes.string, |
||||||
|
/** |
||||||
|
* Current native currency (e.g. RopstenETH) |
||||||
|
*/ |
||||||
|
nativeCurrency: PropTypes.string, |
||||||
|
/** |
||||||
|
* Total sum of the transaction in native currency |
||||||
|
*/ |
||||||
|
ethTransactionTotal: PropTypes.string, |
||||||
|
/** |
||||||
|
* Total sum of the transaction in fiat currency |
||||||
|
*/ |
||||||
|
fiatTransactionTotal: PropTypes.string, |
||||||
|
/** |
||||||
|
* Total sum of the transaction converted to hex value |
||||||
|
*/ |
||||||
|
hexTransactionTotal: PropTypes.string, |
||||||
|
/** |
||||||
|
* Current transaction |
||||||
|
*/ |
||||||
|
txData: PropTypes.object, |
||||||
|
/** |
||||||
|
* Is multi-layer fee network or not |
||||||
|
*/ |
||||||
|
isMultiLayerFeeNetwork: PropTypes.bool, |
||||||
|
/** |
||||||
|
* Is the enhanced gas fee enabled or not |
||||||
|
*/ |
||||||
|
supportsEIP1559V2: PropTypes.bool, |
||||||
|
/** |
||||||
|
* User's address |
||||||
|
*/ |
||||||
|
userAddress: PropTypes.string, |
||||||
|
/** |
||||||
|
* Address of the token that is waiting to be allowed |
||||||
|
*/ |
||||||
|
tokenAddress: PropTypes.string, |
||||||
|
/** |
||||||
|
* Current transaction data |
||||||
|
*/ |
||||||
|
data: PropTypes.string, |
||||||
|
/** |
||||||
|
* Is set approve for all or not |
||||||
|
*/ |
||||||
|
isSetApproveForAll: PropTypes.bool, |
||||||
|
/** |
||||||
|
* Whether a current set approval for all transaction will approve or revoke access |
||||||
|
*/ |
||||||
|
isApprovalOrRejection: PropTypes.bool, |
||||||
|
/** |
||||||
|
* Custom transaction parameters data made by the user (fees) |
||||||
|
*/ |
||||||
|
customTxParamsData: PropTypes.object, |
||||||
|
/** |
||||||
|
* Token amount proposed by the Dapp |
||||||
|
*/ |
||||||
|
dappProposedTokenAmount: PropTypes.string, |
||||||
|
/** |
||||||
|
* Token balance of the current account |
||||||
|
*/ |
||||||
|
currentTokenBalance: PropTypes.string, |
||||||
|
/** |
||||||
|
* Contract address requesting spending cap |
||||||
|
*/ |
||||||
|
toAddress: PropTypes.string, |
||||||
|
/** |
||||||
|
* Symbol of the token that is waiting to be allowed |
||||||
|
*/ |
||||||
|
tokenSymbol: PropTypes.string, |
||||||
|
}; |
@ -0,0 +1,201 @@ |
|||||||
|
import React from 'react'; |
||||||
|
import TokenAllowance from './token-allowance'; |
||||||
|
|
||||||
|
export default { |
||||||
|
title: 'Pages/TokenAllowance', |
||||||
|
id: __filename, |
||||||
|
argTypes: { |
||||||
|
origin: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
siteImage: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
showCustomizeGasModal: { |
||||||
|
action: 'showCustomizeGasModal', |
||||||
|
}, |
||||||
|
useNonceField: { |
||||||
|
control: 'boolean', |
||||||
|
}, |
||||||
|
currentCurrency: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
nativeCurrency: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
ethTransactionTotal: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
fiatTransactionTotal: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
hexTransactionTotal: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
isMultiLayerFeeNetwork: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
supportsEIP1559V2: { |
||||||
|
control: 'boolean', |
||||||
|
}, |
||||||
|
userAddress: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
tokenAddress: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
data: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
isSetApproveForAll: { |
||||||
|
control: 'boolean', |
||||||
|
}, |
||||||
|
setApproveForAllArg: { |
||||||
|
control: 'boolean', |
||||||
|
}, |
||||||
|
customTxParamsData: { |
||||||
|
control: 'object', |
||||||
|
}, |
||||||
|
dappProposedTokenAmount: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
currentTokenBalance: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
toAddress: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
tokenSymbol: { |
||||||
|
control: 'text', |
||||||
|
}, |
||||||
|
txData: { |
||||||
|
control: 'object', |
||||||
|
}, |
||||||
|
}, |
||||||
|
args: { |
||||||
|
origin: 'https://metamask.github.io', |
||||||
|
siteImage: 'https://metamask.github.io/test-dapp/metamask-fox.svg', |
||||||
|
useNonceField: false, |
||||||
|
currentCurrency: 'usd', |
||||||
|
nativeCurrency: 'RopstenETH', |
||||||
|
ethTransactionTotal: '0.0012', |
||||||
|
fiatTransactionTotal: '1.6', |
||||||
|
hexTransactionTotal: '0x44364c5bb0000', |
||||||
|
isMultiLayerFeeNetwork: false, |
||||||
|
supportsEIP1559V2: false, |
||||||
|
userAddress: '0xdd34b35ca1de17dfcdc07f79ff1f8f94868c40a1', |
||||||
|
tokenAddress: '0x55797717b9947b31306f4aac7ad1365c6e3923bd', |
||||||
|
data: '0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef40000000000000000000000000000000000000000000000000000000000011170', |
||||||
|
isSetApproveForAll: false, |
||||||
|
setApproveForAllArg: false, |
||||||
|
customTxParamsData: {}, |
||||||
|
dappProposedTokenAmount: '7', |
||||||
|
currentTokenBalance: '10', |
||||||
|
toAddress: '0x9bc5baf874d2da8d216ae9f137804184ee5afef4', |
||||||
|
tokenSymbol: 'TST', |
||||||
|
txData: { |
||||||
|
id: 3049568294499567, |
||||||
|
time: 1664449552289, |
||||||
|
status: 'unapproved', |
||||||
|
metamaskNetworkId: '3', |
||||||
|
originalGasEstimate: '0xea60', |
||||||
|
userEditedGasLimit: false, |
||||||
|
chainId: '0x3', |
||||||
|
loadingDefaults: false, |
||||||
|
dappSuggestedGasFees: { |
||||||
|
gasPrice: '0x4a817c800', |
||||||
|
gas: '0xea60', |
||||||
|
}, |
||||||
|
sendFlowHistory: [], |
||||||
|
txParams: { |
||||||
|
from: '0xdd34b35ca1de17dfcdc07f79ff1f8f94868c40a1', |
||||||
|
to: '0x55797717b9947b31306f4aac7ad1365c6e3923bd', |
||||||
|
value: '0x0', |
||||||
|
data: '0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef40000000000000000000000000000000000000000000000000000000000011170', |
||||||
|
gas: '0xea60', |
||||||
|
maxFeePerGas: '0x4a817c800', |
||||||
|
maxPriorityFeePerGas: '0x4a817c800', |
||||||
|
}, |
||||||
|
origin: 'https://metamask.github.io', |
||||||
|
type: 'approve', |
||||||
|
history: [ |
||||||
|
{ |
||||||
|
id: 3049568294499567, |
||||||
|
time: 1664449552289, |
||||||
|
status: 'unapproved', |
||||||
|
metamaskNetworkId: '3', |
||||||
|
originalGasEstimate: '0xea60', |
||||||
|
userEditedGasLimit: false, |
||||||
|
chainId: '0x3', |
||||||
|
loadingDefaults: true, |
||||||
|
dappSuggestedGasFees: { |
||||||
|
gasPrice: '0x4a817c800', |
||||||
|
gas: '0xea60', |
||||||
|
}, |
||||||
|
sendFlowHistory: [], |
||||||
|
txParams: { |
||||||
|
from: '0xdd34b35ca1de17dfcdc07f79ff1f8f94868c40a1', |
||||||
|
to: '0x55797717b9947b31306f4aac7ad1365c6e3923bd', |
||||||
|
value: '0x0', |
||||||
|
data: '0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef40000000000000000000000000000000000000000000000000000000000011170', |
||||||
|
gas: '0xea60', |
||||||
|
gasPrice: '0x4a817c800', |
||||||
|
}, |
||||||
|
origin: 'https://metamask.github.io', |
||||||
|
type: 'approve', |
||||||
|
}, |
||||||
|
[ |
||||||
|
{ |
||||||
|
op: 'remove', |
||||||
|
path: '/txParams/gasPrice', |
||||||
|
note: 'Added new unapproved transaction.', |
||||||
|
timestamp: 1664449553939, |
||||||
|
}, |
||||||
|
{ |
||||||
|
op: 'add', |
||||||
|
path: '/txParams/maxFeePerGas', |
||||||
|
value: '0x4a817c800', |
||||||
|
}, |
||||||
|
{ |
||||||
|
op: 'add', |
||||||
|
path: '/txParams/maxPriorityFeePerGas', |
||||||
|
value: '0x4a817c800', |
||||||
|
}, |
||||||
|
{ |
||||||
|
op: 'replace', |
||||||
|
path: '/loadingDefaults', |
||||||
|
value: false, |
||||||
|
}, |
||||||
|
{ |
||||||
|
op: 'add', |
||||||
|
path: '/userFeeLevel', |
||||||
|
value: 'custom', |
||||||
|
}, |
||||||
|
{ |
||||||
|
op: 'add', |
||||||
|
path: '/defaultGasEstimates', |
||||||
|
value: { |
||||||
|
estimateType: 'custom', |
||||||
|
gas: '0xea60', |
||||||
|
maxFeePerGas: '0x4a817c800', |
||||||
|
maxPriorityFeePerGas: '0x4a817c800', |
||||||
|
}, |
||||||
|
}, |
||||||
|
], |
||||||
|
], |
||||||
|
userFeeLevel: 'custom', |
||||||
|
defaultGasEstimates: { |
||||||
|
estimateType: 'custom', |
||||||
|
gas: '0xea60', |
||||||
|
maxFeePerGas: '0x4a817c800', |
||||||
|
maxPriorityFeePerGas: '0x4a817c800', |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
export const DefaultStory = (args) => { |
||||||
|
return <TokenAllowance {...args} />; |
||||||
|
}; |
||||||
|
|
||||||
|
DefaultStory.storyName = 'Default'; |
Loading…
Reference in new issue