mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
enable direct routing to the send page (#15259)
This commit is contained in:
parent
810c00c108
commit
024a62f401
@ -1079,8 +1079,10 @@ const slice = createSlice({
|
||||
updateGasLimit: (state, action) => {
|
||||
const draftTransaction =
|
||||
state.draftTransactions[state.currentTransactionUUID];
|
||||
draftTransaction.gas.gasLimit = addHexPrefix(action.payload);
|
||||
slice.caseReducers.calculateGasTotal(state);
|
||||
if (draftTransaction) {
|
||||
draftTransaction.gas.gasLimit = addHexPrefix(action.payload);
|
||||
slice.caseReducers.calculateGasTotal(state);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* sets the layer 1 fees total (for a multi-layer fee network)
|
||||
@ -2346,6 +2348,19 @@ export function getCurrentDraftTransaction(state) {
|
||||
return state[name].draftTransactions[getCurrentTransactionUUID(state)] ?? {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Selector that returns true if a draft transaction exists.
|
||||
*
|
||||
* @type {Selector<boolean>}
|
||||
*/
|
||||
export function getDraftTransactionExists(state) {
|
||||
const draftTransaction = getCurrentDraftTransaction(state);
|
||||
if (Object.keys(draftTransaction).length === 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Gas selectors
|
||||
|
||||
/**
|
||||
|
@ -5,6 +5,7 @@ import PageContainerHeader from '../../../components/ui/page-container/page-cont
|
||||
import { getMostRecentOverviewPage } from '../../../ducks/history/history';
|
||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||
import {
|
||||
getDraftTransactionExists,
|
||||
getSendAsset,
|
||||
getSendStage,
|
||||
resetSendState,
|
||||
@ -19,15 +20,18 @@ export default function SendHeader() {
|
||||
const stage = useSelector(getSendStage);
|
||||
const asset = useSelector(getSendAsset);
|
||||
const t = useI18nContext();
|
||||
|
||||
const draftTransactionExists = useSelector(getDraftTransactionExists);
|
||||
const onClose = () => {
|
||||
dispatch(resetSendState());
|
||||
history.push(mostRecentOverviewPage);
|
||||
};
|
||||
|
||||
let title = asset.type === ASSET_TYPES.NATIVE ? t('send') : t('sendTokens');
|
||||
let title = asset?.type === ASSET_TYPES.NATIVE ? t('send') : t('sendTokens');
|
||||
|
||||
if (stage === SEND_STAGES.ADD_RECIPIENT || stage === SEND_STAGES.INACTIVE) {
|
||||
if (
|
||||
draftTransactionExists === false ||
|
||||
[SEND_STAGES.ADD_RECIPIENT, SEND_STAGES.INACTIVE].includes(stage)
|
||||
) {
|
||||
title = t('sendTo');
|
||||
} else if (stage === SEND_STAGES.EDIT) {
|
||||
title = t('edit');
|
||||
|
@ -1,8 +1,9 @@
|
||||
import React, { useEffect, useCallback, useContext } from 'react';
|
||||
import React, { useEffect, useCallback, useContext, useRef } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useHistory, useLocation } from 'react-router-dom';
|
||||
import {
|
||||
addHistoryEntry,
|
||||
getDraftTransactionExists,
|
||||
getIsUsingMyAccountForRecipientSearch,
|
||||
getRecipient,
|
||||
getRecipientUserInput,
|
||||
@ -10,6 +11,7 @@ import {
|
||||
resetRecipientInput,
|
||||
resetSendState,
|
||||
SEND_STAGES,
|
||||
startNewDraftTransaction,
|
||||
updateRecipient,
|
||||
updateRecipientUserInput,
|
||||
} from '../../ducks/send';
|
||||
@ -18,6 +20,7 @@ import { getSendHexDataFeatureFlagState } from '../../ducks/metamask/metamask';
|
||||
import { showQrScanner } from '../../store/actions';
|
||||
import { MetaMetricsContext } from '../../contexts/metametrics';
|
||||
import { EVENT } from '../../../shared/constants/metametrics';
|
||||
import { ASSET_TYPES } from '../../../shared/constants/transaction';
|
||||
import SendHeader from './send-header';
|
||||
import AddRecipient from './send-content/add-recipient';
|
||||
import SendContent from './send-content';
|
||||
@ -29,6 +32,7 @@ const sendSliceIsCustomPriceExcessive = (state) =>
|
||||
|
||||
export default function SendTransactionScreen() {
|
||||
const history = useHistory();
|
||||
const startedNewDraftTransaction = useRef(false);
|
||||
const stage = useSelector(getSendStage);
|
||||
const gasIsExcessive = useSelector(sendSliceIsCustomPriceExcessive);
|
||||
const isUsingMyAccountsForRecipientSearch = useSelector(
|
||||
@ -37,6 +41,7 @@ export default function SendTransactionScreen() {
|
||||
const recipient = useSelector(getRecipient);
|
||||
const showHexData = useSelector(getSendHexDataFeatureFlagState);
|
||||
const userInput = useSelector(getRecipientUserInput);
|
||||
const draftTransactionExists = useSelector(getDraftTransactionExists);
|
||||
const location = useLocation();
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
|
||||
@ -46,6 +51,23 @@ export default function SendTransactionScreen() {
|
||||
dispatch(resetSendState());
|
||||
}, [dispatch]);
|
||||
|
||||
/**
|
||||
* It is possible to route to this page directly, either by typing in the url
|
||||
* or by clicking the browser back button after progressing to the confirm
|
||||
* screen. In the case where a draft transaction does not yet exist, this
|
||||
* hook is responsible for creating it. We will assume that this is a native
|
||||
* asset send.
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (
|
||||
draftTransactionExists === false &&
|
||||
startedNewDraftTransaction.current === false
|
||||
) {
|
||||
startedNewDraftTransaction.current = true;
|
||||
dispatch(startNewDraftTransaction({ type: ASSET_TYPES.NATIVE }));
|
||||
}
|
||||
}, [draftTransactionExists, dispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('beforeunload', cleanup);
|
||||
}, [cleanup]);
|
||||
@ -70,7 +92,10 @@ export default function SendTransactionScreen() {
|
||||
|
||||
let content;
|
||||
|
||||
if ([SEND_STAGES.EDIT, SEND_STAGES.DRAFT].includes(stage)) {
|
||||
if (
|
||||
draftTransactionExists &&
|
||||
[SEND_STAGES.EDIT, SEND_STAGES.DRAFT].includes(stage)
|
||||
) {
|
||||
content = (
|
||||
<>
|
||||
<SendContent
|
||||
|
@ -3,7 +3,7 @@ import configureMockStore from 'redux-mock-store';
|
||||
import thunk from 'redux-thunk';
|
||||
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { SEND_STAGES } from '../../ducks/send';
|
||||
import { SEND_STAGES, startNewDraftTransaction } from '../../ducks/send';
|
||||
import { ensInitialState } from '../../ducks/ens';
|
||||
import { renderWithProvider } from '../../../test/jest';
|
||||
import { RINKEBY_CHAIN_ID } from '../../../shared/constants/network';
|
||||
@ -13,6 +13,20 @@ import Send from './send';
|
||||
|
||||
const middleware = [thunk];
|
||||
|
||||
jest.mock('../../ducks/send/send', () => {
|
||||
const original = jest.requireActual('../../ducks/send/send');
|
||||
return {
|
||||
...original,
|
||||
// We don't really need to start a draft transaction, and the mock store
|
||||
// does not update as a result of action calls so instead we just ensure
|
||||
// that the action WOULD be called.
|
||||
startNewDraftTransaction: jest.fn(() => ({
|
||||
type: 'TEST_START_NEW_DRAFT',
|
||||
payload: null,
|
||||
})),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('react-router-dom', () => {
|
||||
const original = jest.requireActual('react-router-dom');
|
||||
return {
|
||||
@ -160,6 +174,25 @@ describe('Send Page', () => {
|
||||
const { queryByText } = renderWithProvider(<Send />, store);
|
||||
expect(queryByText('Next')).toBeNull();
|
||||
});
|
||||
|
||||
it('should render correctly even when a draftTransaction does not exist', () => {
|
||||
const modifiedStore = {
|
||||
...baseStore,
|
||||
send: {
|
||||
...baseStore.send,
|
||||
currentTransactionUUID: null,
|
||||
},
|
||||
};
|
||||
const store = configureMockStore(middleware)(modifiedStore);
|
||||
const { getByPlaceholderText } = renderWithProvider(<Send />, store);
|
||||
// Ensure that the send flow renders on the add recipient screen when
|
||||
// there is no draft transaction.
|
||||
expect(
|
||||
getByPlaceholderText('Search, public address (0x), or ENS'),
|
||||
).toBeTruthy();
|
||||
// Ensure we start a new draft transaction when its missing.
|
||||
expect(startNewDraftTransaction).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Send and Edit Flow (draft)', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user