mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-22 17:33:23 +01:00
[MMI] Added note to trader code fencing (#18051)
* Added note to trader code fencing * Started adding code fences in signature-request * Finished code fencing * Improving code * adds check and runs prettier * Fixed storybook and code fences bundle * Added missing dependency * updates fences * fewer lines * undo previously merged PR * ran lavamoat auto * adds test * prettier --------- Co-authored-by: António Regadas <apregadas@gmail.com> Co-authored-by: Antonio Regadas <antonio.regadas@consensys.net> Co-authored-by: Brad Decker <bhdecker84@gmail.com>
This commit is contained in:
parent
b982bea130
commit
a017a1bae0
9
app/_locales/en/messages.json
generated
9
app/_locales/en/messages.json
generated
@ -2519,6 +2519,12 @@
|
||||
"notEnoughGas": {
|
||||
"message": "Not enough gas"
|
||||
},
|
||||
"note": {
|
||||
"message": "Note"
|
||||
},
|
||||
"notePlaceholder": {
|
||||
"message": "The approver will see this note when approving the transaction at the custodian."
|
||||
},
|
||||
"notifications": {
|
||||
"message": "Notifications"
|
||||
},
|
||||
@ -4675,6 +4681,9 @@
|
||||
"transactionHistoryTotalGasFee": {
|
||||
"message": "Total gas fee"
|
||||
},
|
||||
"transactionNote": {
|
||||
"message": "Transaction note"
|
||||
},
|
||||
"transactionResubmitted": {
|
||||
"message": "Transaction resubmitted with estimated gas fee increased to $1 at $2"
|
||||
},
|
||||
|
@ -18,6 +18,9 @@ import { ConfirmPageContainerSummary, ConfirmPageContainerWarning } from '.';
|
||||
export default class ConfirmPageContainerContent extends Component {
|
||||
static contextTypes = {
|
||||
t: PropTypes.func.isRequired,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
trackEvent: PropTypes.func,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
@ -55,6 +58,9 @@ export default class ConfirmPageContainerContent extends Component {
|
||||
transactionType: PropTypes.string,
|
||||
isBuyableChain: PropTypes.bool,
|
||||
txData: PropTypes.object,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
noteComponent: PropTypes.node,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
metaMetricsId: PropTypes.string,
|
||||
};
|
||||
|
||||
@ -69,6 +75,14 @@ export default class ConfirmPageContainerContent extends Component {
|
||||
}
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
const { noteComponent } = this.props;
|
||||
|
||||
if (noteComponent) {
|
||||
return this.renderTabs();
|
||||
}
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
if (detailsComponent && dataComponent) {
|
||||
return this.renderTabs();
|
||||
}
|
||||
@ -91,6 +105,9 @@ export default class ConfirmPageContainerContent extends Component {
|
||||
///: BEGIN:ONLY_INCLUDE_IN(snaps)
|
||||
insightComponent,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
noteComponent,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@ -102,6 +119,25 @@ export default class ConfirmPageContainerContent extends Component {
|
||||
>
|
||||
{detailsComponent}
|
||||
</Tab>
|
||||
{
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
noteComponent && (
|
||||
<Tab
|
||||
className="confirm-page-container-content__tab"
|
||||
name={t('note')}
|
||||
pillText={t('new')}
|
||||
onClick={() => {
|
||||
this.context.trackEvent({
|
||||
category: 'Note to trader',
|
||||
event: 'Clicked on Notes tab on a transaction window',
|
||||
});
|
||||
}}
|
||||
>
|
||||
{noteComponent}
|
||||
</Tab>
|
||||
)
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
}
|
||||
{dataComponent && (
|
||||
<Tab
|
||||
className="confirm-page-container-content__tab"
|
||||
@ -221,6 +257,7 @@ export default class ConfirmPageContainerContent extends Component {
|
||||
{t('insufficientCurrencyBuyOrDeposit', [
|
||||
nativeCurrency,
|
||||
networkName,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask)
|
||||
<Button
|
||||
type="inline"
|
||||
className="confirm-page-container-content__link"
|
||||
@ -237,6 +274,7 @@ export default class ConfirmPageContainerContent extends Component {
|
||||
>
|
||||
{t('buyAsset', [nativeCurrency])}
|
||||
</Button>,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
])}
|
||||
</Typography>
|
||||
) : (
|
||||
|
@ -99,6 +99,9 @@ const ConfirmPageContainer = (props) => {
|
||||
txData,
|
||||
assetStandard,
|
||||
isApprovalOrRejection,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
noteComponent,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
} = props;
|
||||
|
||||
const t = useI18nContext();
|
||||
@ -238,6 +241,9 @@ const ConfirmPageContainer = (props) => {
|
||||
transactionType={currentTransaction.type}
|
||||
isBuyableChain={isBuyableChain}
|
||||
txData={txData}
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
noteComponent={noteComponent}
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
/>
|
||||
)}
|
||||
{shouldDisplayWarning && errorKey === INSUFFICIENT_FUNDS_ERROR_KEY && (
|
||||
@ -398,6 +404,9 @@ ConfirmPageContainer.propTypes = {
|
||||
supportsEIP1559: PropTypes.bool,
|
||||
nativeCurrency: PropTypes.string,
|
||||
isApprovalOrRejection: PropTypes.bool,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
noteComponent: PropTypes.node,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
};
|
||||
|
||||
export default ConfirmPageContainer;
|
||||
|
@ -3,33 +3,41 @@
|
||||
exports[`NoteToTrader should render the Note to trader component 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="box note-header box--display-flex box--flex-direction-row box--justify-content-space-between"
|
||||
class="box confirm-page-container-content__data box--flex-direction-row"
|
||||
>
|
||||
<label
|
||||
class="box mm-text mm-label mm-label--html-for mm-text--body-md mm-text--font-weight-bold box--display-inline-flex box--flex-direction-row box--align-items-center box--color-text-default"
|
||||
for="transaction-note"
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-row"
|
||||
>
|
||||
Transaction note
|
||||
</label>
|
||||
<p
|
||||
class="box mm-text note-header__counter mm-text--body-md box--flex-direction-row box--color-text-default"
|
||||
>
|
||||
9
|
||||
/
|
||||
280
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="box note-field box--display-flex box--flex-direction-column"
|
||||
>
|
||||
<textarea
|
||||
data-testid="transaction-note"
|
||||
id="transaction-note"
|
||||
maxlength="280"
|
||||
placeholder=""
|
||||
>
|
||||
some text
|
||||
</textarea>
|
||||
<div
|
||||
class="box note-header box--display-flex box--flex-direction-row box--justify-content-space-between"
|
||||
>
|
||||
<label
|
||||
class="box mm-text mm-label mm-label--html-for mm-text--body-md mm-text--font-weight-bold box--display-inline-flex box--flex-direction-row box--align-items-center box--color-text-default"
|
||||
for="transaction-note"
|
||||
>
|
||||
Transaction note
|
||||
</label>
|
||||
<p
|
||||
class="box mm-text note-header__counter mm-text--body-md box--flex-direction-row box--color-text-default"
|
||||
>
|
||||
9
|
||||
/
|
||||
280
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="box note-field box--display-flex box--flex-direction-column"
|
||||
>
|
||||
<textarea
|
||||
data-testid="transaction-note"
|
||||
id="transaction-note"
|
||||
maxlength="280"
|
||||
placeholder=""
|
||||
>
|
||||
some text
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -12,33 +12,35 @@ const NoteToTrader = (props) => {
|
||||
const { placeholder, maxLength, onChange, noteText, labelText } = props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
className="note-header"
|
||||
display={DISPLAY.FLEX}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
>
|
||||
<Label htmlFor="transaction-note">{labelText}</Label>
|
||||
<Text className="note-header__counter">
|
||||
{noteText.length}/{maxLength}
|
||||
</Text>
|
||||
<Box className="confirm-page-container-content__data">
|
||||
<Box display={DISPLAY.FLEX} flexDirection={FLEX_DIRECTION.ROW}>
|
||||
<Box
|
||||
className="note-header"
|
||||
display={DISPLAY.FLEX}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
>
|
||||
<Label htmlFor="transaction-note">{labelText}</Label>
|
||||
<Text className="note-header__counter">
|
||||
{noteText.length}/{maxLength}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||
className="note-field"
|
||||
>
|
||||
<textarea
|
||||
id="transaction-note"
|
||||
data-testid="transaction-note"
|
||||
onChange={({ target: { value } }) => onChange(value)}
|
||||
autoFocus
|
||||
maxLength={maxLength}
|
||||
placeholder={placeholder}
|
||||
value={noteText}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||
className="note-field"
|
||||
>
|
||||
<textarea
|
||||
id="transaction-note"
|
||||
data-testid="transaction-note"
|
||||
onChange={({ target: { value } }) => onChange(value)}
|
||||
autoFocus
|
||||
maxLength={maxLength}
|
||||
placeholder={placeholder}
|
||||
value={noteText}
|
||||
/>
|
||||
</Box>
|
||||
</>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -25,6 +25,10 @@ import {
|
||||
isLegacyTransaction,
|
||||
} from '../../helpers/utils/transactions.util';
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
import NoteToTrader from '../../components/institutional/note-to-trader';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
import { TransactionModalContextProvider } from '../../contexts/transaction-modal';
|
||||
import TransactionDetail from '../../components/app/transaction-detail/transaction-detail.component';
|
||||
import TransactionDetailItem from '../../components/app/transaction-detail-item/transaction-detail-item.component';
|
||||
@ -129,6 +133,10 @@ export default class ConfirmTransactionBase extends Component {
|
||||
hardwareWalletRequiresConnection: PropTypes.bool,
|
||||
isMultiLayerFeeNetwork: PropTypes.bool,
|
||||
isBuyableChain: PropTypes.bool,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
accountType: PropTypes.string,
|
||||
isNoteToTraderSupported: PropTypes.bool,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
isApprovalOrRejection: PropTypes.bool,
|
||||
assetStandard: PropTypes.string,
|
||||
useCurrencyRateCheck: PropTypes.bool,
|
||||
@ -142,6 +150,9 @@ export default class ConfirmTransactionBase extends Component {
|
||||
editingGas: false,
|
||||
userAcknowledgedGasMissing: false,
|
||||
showWarningModal: false,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
noteText: '',
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
@ -594,10 +605,31 @@ export default class ConfirmTransactionBase extends Component {
|
||||
addToAddressBookIfNew,
|
||||
toAccounts,
|
||||
toAddress,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
accountType,
|
||||
isNoteToTraderSupported,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
} = this.props;
|
||||
const { submitting } = this.state;
|
||||
const {
|
||||
submitting,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
noteText,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
} = this.state;
|
||||
const { name } = methodData;
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
if (accountType === 'custody') {
|
||||
txData.custodyStatus = 'created';
|
||||
|
||||
if (isNoteToTraderSupported) {
|
||||
txData.metadata = {
|
||||
note: noteText,
|
||||
};
|
||||
}
|
||||
}
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
if (txData.type === TransactionType.simpleSend) {
|
||||
addToAddressBookIfNew(toAddress, toAccounts);
|
||||
}
|
||||
@ -802,6 +834,9 @@ export default class ConfirmTransactionBase extends Component {
|
||||
isApprovalOrRejection,
|
||||
assetStandard,
|
||||
title,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
isNoteToTraderSupported,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
} = this.props;
|
||||
const {
|
||||
submitting,
|
||||
@ -869,6 +904,19 @@ export default class ConfirmTransactionBase extends Component {
|
||||
dataComponent={this.renderData(functionType)}
|
||||
dataHexComponent={this.renderDataHex(functionType)}
|
||||
contentComponent={contentComponent}
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
noteComponent={
|
||||
isNoteToTraderSupported && (
|
||||
<NoteToTrader
|
||||
maxLength="280"
|
||||
placeholder={t('notePlaceholder')}
|
||||
onChange={(value) => this.setState({ noteText: value })}
|
||||
noteText={this.state.noteText}
|
||||
labelText={t('transactionNote')}
|
||||
/>
|
||||
)
|
||||
}
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
nonce={customNonceValue || nonce}
|
||||
unapprovedTxCount={unapprovedTxCount}
|
||||
tokenAddress={tokenAddress}
|
||||
|
@ -60,6 +60,9 @@ import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
|
||||
import { getGasLoadingAnimationIsShowing } from '../../ducks/app/app';
|
||||
import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
|
||||
import { CUSTOM_GAS_ESTIMATE } from '../../../shared/constants/gas';
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
import { getAccountType } from '../../selectors/selectors';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
import {
|
||||
TransactionStatus,
|
||||
TransactionType,
|
||||
@ -196,6 +199,23 @@ const mapStateToProps = (state, ownProps) => {
|
||||
|
||||
const isMultiLayerFeeNetwork = getIsMultiLayerFeeNetwork(state);
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
const accountType = getAccountType(state);
|
||||
|
||||
const fromChecksumHexAddress = toChecksumHexAddress(fromAddress);
|
||||
let isNoteToTraderSupported = false;
|
||||
if (
|
||||
state.metamask.custodyAccountDetails &&
|
||||
state.metamask.custodyAccountDetails[fromChecksumHexAddress]
|
||||
) {
|
||||
const { custodianName } =
|
||||
state.metamask.custodyAccountDetails[fromChecksumHexAddress];
|
||||
isNoteToTraderSupported = state.metamask.mmiConfiguration?.custodians?.find(
|
||||
(custodian) => custodian.name === custodianName,
|
||||
)?.isNoteToTraderSupported;
|
||||
}
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
return {
|
||||
balance,
|
||||
fromAddress,
|
||||
@ -246,6 +266,10 @@ const mapStateToProps = (state, ownProps) => {
|
||||
chainId,
|
||||
isBuyableChain,
|
||||
useCurrencyRateCheck: getUseCurrencyRateCheck(state),
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
accountType,
|
||||
isNoteToTraderSupported,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -166,4 +166,32 @@ describe('Confirm Transaction Base', () => {
|
||||
expect(getByText('Layer 1 fees')).toBeInTheDocument();
|
||||
expect(getByText('Layer 2 gas fee')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render NoteToTrader when isNoteToTraderSupported is true', () => {
|
||||
baseStore.metamask.custodyAccountDetails = {
|
||||
'0x0': {
|
||||
address: '0x0',
|
||||
details: 'details',
|
||||
custodyType: 'testCustody - Saturn',
|
||||
custodianName: 'saturn-dev',
|
||||
},
|
||||
};
|
||||
|
||||
baseStore.metamask.mmiConfiguration = {
|
||||
custodians: [
|
||||
{
|
||||
name: 'saturn-dev',
|
||||
displayName: 'Saturn Custody',
|
||||
isNoteToTraderSupported: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const store = configureMockStore(middleware)(baseStore);
|
||||
const { getByTestId } = renderWithProvider(
|
||||
<ConfirmTransactionBase actionKey="confirm" />,
|
||||
store,
|
||||
);
|
||||
expect(getByTestId('transaction-note')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user