mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-23 02:10:12 +01:00
Track send flow history on txMeta (#14510)
This commit is contained in:
parent
214211f847
commit
f251ca4ff2
@ -647,6 +647,35 @@ export default class TransactionController extends EventEmitter {
|
|||||||
return this._getTransaction(txId);
|
return this._getTransaction(txId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* append new sendFlowHistory to the transaction with id if the transaction
|
||||||
|
* state is unapproved. Returns the updated transaction.
|
||||||
|
*
|
||||||
|
* @param {string} txId - transaction id
|
||||||
|
* @param {Array<{ entry: string, timestamp: number }>} sendFlowHistory -
|
||||||
|
* history to add to the sendFlowHistory property of txMeta.
|
||||||
|
* @returns {TransactionMeta} the txMeta of the updated transaction
|
||||||
|
*/
|
||||||
|
updateTransactionSendFlowHistory(txId, sendFlowHistory) {
|
||||||
|
this._throwErrorIfNotUnapprovedTx(txId, 'updateTransactionSendFlowHistory');
|
||||||
|
const txMeta = this._getTransaction(txId);
|
||||||
|
|
||||||
|
// only update what is defined
|
||||||
|
const note = `Update sendFlowHistory for ${txId}`;
|
||||||
|
|
||||||
|
this.txStateManager.updateTransaction(
|
||||||
|
{
|
||||||
|
...txMeta,
|
||||||
|
sendFlowHistory: [
|
||||||
|
...(txMeta?.sendFlowHistory ?? []),
|
||||||
|
...sendFlowHistory,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
note,
|
||||||
|
);
|
||||||
|
return this._getTransaction(txId);
|
||||||
|
}
|
||||||
|
|
||||||
// ====================================================================================================================================================
|
// ====================================================================================================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -656,9 +685,15 @@ export default class TransactionController extends EventEmitter {
|
|||||||
* @param txParams
|
* @param txParams
|
||||||
* @param origin
|
* @param origin
|
||||||
* @param transactionType
|
* @param transactionType
|
||||||
|
* @param sendFlowHistory
|
||||||
* @returns {txMeta}
|
* @returns {txMeta}
|
||||||
*/
|
*/
|
||||||
async addUnapprovedTransaction(txParams, origin, transactionType) {
|
async addUnapprovedTransaction(
|
||||||
|
txParams,
|
||||||
|
origin,
|
||||||
|
transactionType,
|
||||||
|
sendFlowHistory = [],
|
||||||
|
) {
|
||||||
if (
|
if (
|
||||||
transactionType !== undefined &&
|
transactionType !== undefined &&
|
||||||
!VALID_UNAPPROVED_TRANSACTION_TYPES.includes(transactionType)
|
!VALID_UNAPPROVED_TRANSACTION_TYPES.includes(transactionType)
|
||||||
@ -683,6 +718,7 @@ export default class TransactionController extends EventEmitter {
|
|||||||
let txMeta = this.txStateManager.generateTxMeta({
|
let txMeta = this.txStateManager.generateTxMeta({
|
||||||
txParams: normalizedTxParams,
|
txParams: normalizedTxParams,
|
||||||
origin,
|
origin,
|
||||||
|
sendFlowHistory,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (origin === ORIGIN_METAMASK) {
|
if (origin === ORIGIN_METAMASK) {
|
||||||
|
@ -127,6 +127,7 @@ export default class TransactionStateManager extends EventEmitter {
|
|||||||
chainId,
|
chainId,
|
||||||
loadingDefaults: true,
|
loadingDefaults: true,
|
||||||
dappSuggestedGasFees,
|
dappSuggestedGasFees,
|
||||||
|
sendFlowHistory: [],
|
||||||
...opts,
|
...opts,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1632,6 +1632,9 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
updateTransactionGasFees: txController.updateTransactionGasFees.bind(
|
updateTransactionGasFees: txController.updateTransactionGasFees.bind(
|
||||||
txController,
|
txController,
|
||||||
),
|
),
|
||||||
|
updateTransactionSendFlowHistory: txController.updateTransactionSendFlowHistory.bind(
|
||||||
|
txController,
|
||||||
|
),
|
||||||
|
|
||||||
updateSwapApprovalTransaction: txController.updateSwapApprovalTransaction.bind(
|
updateSwapApprovalTransaction: txController.updateSwapApprovalTransaction.bind(
|
||||||
txController,
|
txController,
|
||||||
|
@ -60,6 +60,7 @@ import {
|
|||||||
getTokenStandardAndDetails,
|
getTokenStandardAndDetails,
|
||||||
showModal,
|
showModal,
|
||||||
addUnapprovedTransactionAndRouteToConfirmationPage,
|
addUnapprovedTransactionAndRouteToConfirmationPage,
|
||||||
|
updateTransactionSendFlowHistory,
|
||||||
} from '../../store/actions';
|
} from '../../store/actions';
|
||||||
import { setCustomGasLimit } from '../gas/gas.duck';
|
import { setCustomGasLimit } from '../gas/gas.duck';
|
||||||
import {
|
import {
|
||||||
@ -110,6 +111,7 @@ import {
|
|||||||
import { readAddressAsContract } from '../../../shared/modules/contract-utils';
|
import { readAddressAsContract } from '../../../shared/modules/contract-utils';
|
||||||
import { INVALID_ASSET_TYPE } from '../../helpers/constants/error-keys';
|
import { INVALID_ASSET_TYPE } from '../../helpers/constants/error-keys';
|
||||||
import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
|
import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
|
||||||
|
import { getValueFromWeiHex } from '../../helpers/utils/confirm-tx.util';
|
||||||
// typedefs
|
// typedefs
|
||||||
/**
|
/**
|
||||||
* @typedef {import('@reduxjs/toolkit').PayloadAction} PayloadAction
|
* @typedef {import('@reduxjs/toolkit').PayloadAction} PayloadAction
|
||||||
@ -684,12 +686,19 @@ export const initialState = {
|
|||||||
// Layer 1 gas fee total on multi-layer fee networks
|
// Layer 1 gas fee total on multi-layer fee networks
|
||||||
layer1GasTotal: '0x0',
|
layer1GasTotal: '0x0',
|
||||||
},
|
},
|
||||||
|
history: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const slice = createSlice({
|
const slice = createSlice({
|
||||||
name,
|
name,
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
|
addHistoryEntry: (state, action) => {
|
||||||
|
state.history.push({
|
||||||
|
entry: action.payload,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
});
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* update current amount.value in state and run post update validation of
|
* update current amount.value in state and run post update validation of
|
||||||
* the amount field and the send state. Recomputes the draftTransaction
|
* the amount field and the send state. Recomputes the draftTransaction
|
||||||
@ -1402,9 +1411,10 @@ const {
|
|||||||
updateGasLimit,
|
updateGasLimit,
|
||||||
validateRecipientUserInput,
|
validateRecipientUserInput,
|
||||||
updateRecipientSearchMode,
|
updateRecipientSearchMode,
|
||||||
|
addHistoryEntry,
|
||||||
} = actions;
|
} = actions;
|
||||||
|
|
||||||
export { useDefaultGas, useCustomGas, updateGasLimit };
|
export { useDefaultGas, useCustomGas, updateGasLimit, addHistoryEntry };
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
@ -1421,6 +1431,9 @@ export { useDefaultGas, useCustomGas, updateGasLimit };
|
|||||||
*/
|
*/
|
||||||
export function updateGasPrice(gasPrice) {
|
export function updateGasPrice(gasPrice) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
|
dispatch(
|
||||||
|
addHistoryEntry(`sendFlow - user set legacy gasPrice to ${gasPrice}`),
|
||||||
|
);
|
||||||
dispatch(
|
dispatch(
|
||||||
actions.updateGasFees({
|
actions.updateGasFees({
|
||||||
gasPrice,
|
gasPrice,
|
||||||
@ -1452,8 +1465,36 @@ export function resetSendState() {
|
|||||||
*/
|
*/
|
||||||
export function updateSendAmount(amount) {
|
export function updateSendAmount(amount) {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
await dispatch(actions.updateSendAmount(amount));
|
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
let logAmount = amount;
|
||||||
|
if (state[name].asset.type === ASSET_TYPES.TOKEN) {
|
||||||
|
const multiplier = Math.pow(
|
||||||
|
10,
|
||||||
|
Number(state[name].asset.details?.decimals || 0),
|
||||||
|
);
|
||||||
|
const decimalValueString = conversionUtil(addHexPrefix(amount), {
|
||||||
|
fromNumericBase: 'hex',
|
||||||
|
toNumericBase: 'dec',
|
||||||
|
toCurrency: state[name].asset.details?.symbol,
|
||||||
|
conversionRate: multiplier,
|
||||||
|
invertConversionRate: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
logAmount = `${Number(decimalValueString) ? decimalValueString : ''} ${
|
||||||
|
state[name].asset.details?.symbol
|
||||||
|
}`;
|
||||||
|
} else {
|
||||||
|
const ethValue = getValueFromWeiHex({
|
||||||
|
value: amount,
|
||||||
|
toCurrency: ETH,
|
||||||
|
numberOfDecimals: 8,
|
||||||
|
});
|
||||||
|
logAmount = `${ethValue} ${ETH}`;
|
||||||
|
}
|
||||||
|
await dispatch(
|
||||||
|
addHistoryEntry(`sendFlow - user set amount to ${logAmount}`),
|
||||||
|
);
|
||||||
|
await dispatch(actions.updateSendAmount(amount));
|
||||||
if (state.send.amount.mode === AMOUNT_MODES.MAX) {
|
if (state.send.amount.mode === AMOUNT_MODES.MAX) {
|
||||||
await dispatch(actions.updateAmountMode(AMOUNT_MODES.INPUT));
|
await dispatch(actions.updateAmountMode(AMOUNT_MODES.INPUT));
|
||||||
}
|
}
|
||||||
@ -1482,6 +1523,19 @@ export function updateSendAmount(amount) {
|
|||||||
*/
|
*/
|
||||||
export function updateSendAsset({ type, details }) {
|
export function updateSendAsset({ type, details }) {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
|
dispatch(addHistoryEntry(`sendFlow - user set asset type to ${type}`));
|
||||||
|
dispatch(
|
||||||
|
addHistoryEntry(
|
||||||
|
`sendFlow - user set asset symbol to ${details?.symbol ?? 'undefined'}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
dispatch(
|
||||||
|
addHistoryEntry(
|
||||||
|
`sendFlow - user set asset address to ${
|
||||||
|
details?.address ?? 'undefined'
|
||||||
|
}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
const state = getState();
|
const state = getState();
|
||||||
let { balance, error } = state.send.asset;
|
let { balance, error } = state.send.asset;
|
||||||
const userAddress = state.send.account.address ?? getSelectedAddress(state);
|
const userAddress = state.send.account.address ?? getSelectedAddress(state);
|
||||||
@ -1580,6 +1634,11 @@ export function updateSendAsset({ type, details }) {
|
|||||||
* it only applicable for use within action creators.
|
* it only applicable for use within action creators.
|
||||||
*/
|
*/
|
||||||
const debouncedValidateRecipientUserInput = debounce((dispatch, payload) => {
|
const debouncedValidateRecipientUserInput = debounce((dispatch, payload) => {
|
||||||
|
dispatch(
|
||||||
|
addHistoryEntry(
|
||||||
|
`sendFlow - user typed ${payload.userInput} into recipient input field`,
|
||||||
|
),
|
||||||
|
);
|
||||||
dispatch(validateRecipientUserInput(payload));
|
dispatch(validateRecipientUserInput(payload));
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
@ -1600,6 +1659,7 @@ export function updateRecipientUserInput(userInput) {
|
|||||||
const useTokenDetection = getUseTokenDetection(state);
|
const useTokenDetection = getUseTokenDetection(state);
|
||||||
const tokenAddressList = Object.keys(getTokenList(state));
|
const tokenAddressList = Object.keys(getTokenList(state));
|
||||||
debouncedValidateRecipientUserInput(dispatch, {
|
debouncedValidateRecipientUserInput(dispatch, {
|
||||||
|
userInput,
|
||||||
chainId,
|
chainId,
|
||||||
tokens,
|
tokens,
|
||||||
useTokenDetection,
|
useTokenDetection,
|
||||||
@ -1610,12 +1670,22 @@ export function updateRecipientUserInput(userInput) {
|
|||||||
|
|
||||||
export function useContactListForRecipientSearch() {
|
export function useContactListForRecipientSearch() {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
|
dispatch(
|
||||||
|
addHistoryEntry(
|
||||||
|
`sendFlow - user selected back to all on recipient screen`,
|
||||||
|
),
|
||||||
|
);
|
||||||
dispatch(updateRecipientSearchMode(RECIPIENT_SEARCH_MODES.CONTACT_LIST));
|
dispatch(updateRecipientSearchMode(RECIPIENT_SEARCH_MODES.CONTACT_LIST));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useMyAccountsForRecipientSearch() {
|
export function useMyAccountsForRecipientSearch() {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
|
dispatch(
|
||||||
|
addHistoryEntry(
|
||||||
|
`sendFlow - user selected transfer to my accounts on recipient screen`,
|
||||||
|
),
|
||||||
|
);
|
||||||
dispatch(updateRecipientSearchMode(RECIPIENT_SEARCH_MODES.MY_ACCOUNTS));
|
dispatch(updateRecipientSearchMode(RECIPIENT_SEARCH_MODES.MY_ACCOUNTS));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1638,6 +1708,8 @@ export function useMyAccountsForRecipientSearch() {
|
|||||||
*/
|
*/
|
||||||
export function updateRecipient({ address, nickname }) {
|
export function updateRecipient({ address, nickname }) {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
|
// Do not addHistoryEntry here as this is called from a number of places
|
||||||
|
// each with significance to the user and transaction history.
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const nicknameFromAddressBookEntryOrAccountName =
|
const nicknameFromAddressBookEntryOrAccountName =
|
||||||
getAddressBookEntryOrAccountName(state, address) ?? '';
|
getAddressBookEntryOrAccountName(state, address) ?? '';
|
||||||
@ -1656,6 +1728,7 @@ export function updateRecipient({ address, nickname }) {
|
|||||||
*/
|
*/
|
||||||
export function resetRecipientInput() {
|
export function resetRecipientInput() {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
|
await dispatch(addHistoryEntry(`sendFlow - user cleared recipient input`));
|
||||||
await dispatch(updateRecipientUserInput(''));
|
await dispatch(updateRecipientUserInput(''));
|
||||||
await dispatch(updateRecipient({ address: '', nickname: '' }));
|
await dispatch(updateRecipient({ address: '', nickname: '' }));
|
||||||
await dispatch(resetEnsResolution());
|
await dispatch(resetEnsResolution());
|
||||||
@ -1675,6 +1748,9 @@ export function resetRecipientInput() {
|
|||||||
*/
|
*/
|
||||||
export function updateSendHexData(hexData) {
|
export function updateSendHexData(hexData) {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
|
await dispatch(
|
||||||
|
addHistoryEntry(`sendFlow - user added custom hexData ${hexData}`),
|
||||||
|
);
|
||||||
await dispatch(actions.updateUserInputHexData(hexData));
|
await dispatch(actions.updateUserInputHexData(hexData));
|
||||||
const state = getState();
|
const state = getState();
|
||||||
if (state.send.asset.type === ASSET_TYPES.NATIVE) {
|
if (state.send.asset.type === ASSET_TYPES.NATIVE) {
|
||||||
@ -1695,9 +1771,11 @@ export function toggleSendMaxMode() {
|
|||||||
if (state.send.amount.mode === AMOUNT_MODES.MAX) {
|
if (state.send.amount.mode === AMOUNT_MODES.MAX) {
|
||||||
await dispatch(actions.updateAmountMode(AMOUNT_MODES.INPUT));
|
await dispatch(actions.updateAmountMode(AMOUNT_MODES.INPUT));
|
||||||
await dispatch(actions.updateSendAmount('0x0'));
|
await dispatch(actions.updateSendAmount('0x0'));
|
||||||
|
await dispatch(addHistoryEntry(`sendFlow - user toggled max mode off`));
|
||||||
} else {
|
} else {
|
||||||
await dispatch(actions.updateAmountMode(AMOUNT_MODES.MAX));
|
await dispatch(actions.updateAmountMode(AMOUNT_MODES.MAX));
|
||||||
await dispatch(actions.updateAmountToMax());
|
await dispatch(actions.updateAmountToMax());
|
||||||
|
await dispatch(addHistoryEntry(`sendFlow - user toggled max mode on`));
|
||||||
}
|
}
|
||||||
await dispatch(computeEstimatedGasLimit());
|
await dispatch(computeEstimatedGasLimit());
|
||||||
};
|
};
|
||||||
@ -1746,6 +1824,12 @@ export function signTransaction() {
|
|||||||
eip1559support ? eip1559OnlyTxParamsToUpdate : txParams,
|
eip1559support ? eip1559OnlyTxParamsToUpdate : txParams,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
await dispatch(
|
||||||
|
addHistoryEntry(
|
||||||
|
`sendFlow - user clicked next and transaction should be updated in controller`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await dispatch(updateTransactionSendFlowHistory(id, state[name].history));
|
||||||
dispatch(updateEditableParams(id, editingTx.txParams));
|
dispatch(updateEditableParams(id, editingTx.txParams));
|
||||||
dispatch(updateTransactionGasFees(id, editingTx.txParams));
|
dispatch(updateTransactionGasFees(id, editingTx.txParams));
|
||||||
} else {
|
} else {
|
||||||
@ -1757,10 +1841,17 @@ export function signTransaction() {
|
|||||||
? TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER_FROM
|
? TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER_FROM
|
||||||
: TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER;
|
: TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER;
|
||||||
}
|
}
|
||||||
|
await dispatch(
|
||||||
|
addHistoryEntry(
|
||||||
|
`sendFlow - user clicked next and transaction should be added to controller`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
dispatch(
|
dispatch(
|
||||||
addUnapprovedTransactionAndRouteToConfirmationPage(
|
addUnapprovedTransactionAndRouteToConfirmationPage(
|
||||||
txParams,
|
txParams,
|
||||||
transactionType,
|
transactionType,
|
||||||
|
state[name].history,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1775,6 +1866,11 @@ export function editTransaction(
|
|||||||
) {
|
) {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
await dispatch(
|
||||||
|
addHistoryEntry(
|
||||||
|
`sendFlow - user clicked edit on transaction with id ${transactionId}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
const unapprovedTransactions = getUnapprovedTxs(state);
|
const unapprovedTransactions = getUnapprovedTxs(state);
|
||||||
const transaction = unapprovedTransactions[transactionId];
|
const transaction = unapprovedTransactions[transactionId];
|
||||||
const { txParams } = transaction;
|
const { txParams } = transaction;
|
||||||
|
@ -80,9 +80,10 @@ jest.mock('./send', () => {
|
|||||||
|
|
||||||
setBackgroundConnection({
|
setBackgroundConnection({
|
||||||
addPollingTokenToAppState: jest.fn(),
|
addPollingTokenToAppState: jest.fn(),
|
||||||
addUnapprovedTransaction: jest.fn((_x, _y, _z, cb) => {
|
addUnapprovedTransaction: jest.fn((_w, _x, _y, _z, cb) => {
|
||||||
return cb(null, {});
|
cb(null);
|
||||||
}),
|
}),
|
||||||
|
updateTransactionSendFlowHistory: jest.fn((_x, _y, cb) => cb(null)),
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Send Slice', () => {
|
describe('Send Slice', () => {
|
||||||
@ -1247,6 +1248,10 @@ describe('Send Slice', () => {
|
|||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
const expectedActionResult = [
|
const expectedActionResult = [
|
||||||
|
{
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user set legacy gasPrice to 0x0',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: 'send/updateGasFees',
|
type: 'send/updateGasFees',
|
||||||
payload: {
|
payload: {
|
||||||
@ -1302,22 +1307,28 @@ describe('Send Slice', () => {
|
|||||||
};
|
};
|
||||||
const store = mockStore(sendState);
|
const store = mockStore(sendState);
|
||||||
|
|
||||||
const newSendAmount = 'aNewSendAmount';
|
const newSendAmount = 'DE0B6B3A7640000';
|
||||||
|
|
||||||
await store.dispatch(updateSendAmount(newSendAmount));
|
await store.dispatch(updateSendAmount(newSendAmount));
|
||||||
|
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
const expectedFirstActionResult = {
|
const expectedFirstActionResult = {
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user set amount to 1 ETH',
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectedSecondActionResult = {
|
||||||
type: 'send/updateSendAmount',
|
type: 'send/updateSendAmount',
|
||||||
payload: 'aNewSendAmount',
|
payload: 'DE0B6B3A7640000',
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(actionResult[0]).toStrictEqual(expectedFirstActionResult);
|
expect(actionResult[0]).toStrictEqual(expectedFirstActionResult);
|
||||||
expect(actionResult[1].type).toStrictEqual(
|
expect(actionResult[1]).toStrictEqual(expectedSecondActionResult);
|
||||||
|
expect(actionResult[2].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/pending',
|
'send/computeEstimatedGasLimit/pending',
|
||||||
);
|
);
|
||||||
expect(actionResult[2].type).toStrictEqual(
|
expect(actionResult[3].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/rejected',
|
'send/computeEstimatedGasLimit/rejected',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1358,15 +1369,21 @@ describe('Send Slice', () => {
|
|||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
const expectedFirstActionResult = {
|
const expectedFirstActionResult = {
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user set amount to 0 ETH',
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectedSecondActionResult = {
|
||||||
type: 'send/updateSendAmount',
|
type: 'send/updateSendAmount',
|
||||||
payload: undefined,
|
payload: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(actionResult[0]).toStrictEqual(expectedFirstActionResult);
|
expect(actionResult[0]).toStrictEqual(expectedFirstActionResult);
|
||||||
expect(actionResult[1].type).toStrictEqual(
|
expect(actionResult[1]).toStrictEqual(expectedSecondActionResult);
|
||||||
|
expect(actionResult[2].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/pending',
|
'send/computeEstimatedGasLimit/pending',
|
||||||
);
|
);
|
||||||
expect(actionResult[2].type).toStrictEqual(
|
expect(actionResult[3].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/rejected',
|
'send/computeEstimatedGasLimit/rejected',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1407,12 +1424,13 @@ describe('Send Slice', () => {
|
|||||||
|
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
expect(actionResult).toHaveLength(3);
|
expect(actionResult).toHaveLength(4);
|
||||||
expect(actionResult[0].type).toStrictEqual('send/updateSendAmount');
|
expect(actionResult[0].type).toStrictEqual('send/addHistoryEntry');
|
||||||
expect(actionResult[1].type).toStrictEqual(
|
expect(actionResult[1].type).toStrictEqual('send/updateSendAmount');
|
||||||
|
expect(actionResult[2].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/pending',
|
'send/computeEstimatedGasLimit/pending',
|
||||||
);
|
);
|
||||||
expect(actionResult[2].type).toStrictEqual(
|
expect(actionResult[3].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/rejected',
|
'send/computeEstimatedGasLimit/rejected',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1466,19 +1484,31 @@ describe('Send Slice', () => {
|
|||||||
|
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
expect(actionResult).toHaveLength(3);
|
expect(actionResult).toHaveLength(6);
|
||||||
|
expect(actionResult[0]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user set asset type to ',
|
||||||
|
});
|
||||||
|
expect(actionResult[1]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user set asset symbol to ',
|
||||||
|
});
|
||||||
|
expect(actionResult[2]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user set asset address to ',
|
||||||
|
});
|
||||||
|
|
||||||
expect(actionResult[0].type).toStrictEqual('send/updateAsset');
|
expect(actionResult[3].type).toStrictEqual('send/updateAsset');
|
||||||
expect(actionResult[0].payload).toStrictEqual({
|
expect(actionResult[3].payload).toStrictEqual({
|
||||||
...newSendAsset,
|
...newSendAsset,
|
||||||
balance: '',
|
balance: '',
|
||||||
error: null,
|
error: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(actionResult[1].type).toStrictEqual(
|
expect(actionResult[4].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/pending',
|
'send/computeEstimatedGasLimit/pending',
|
||||||
);
|
);
|
||||||
expect(actionResult[2].type).toStrictEqual(
|
expect(actionResult[5].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/rejected',
|
'send/computeEstimatedGasLimit/rejected',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1506,19 +1536,31 @@ describe('Send Slice', () => {
|
|||||||
|
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
expect(actionResult).toHaveLength(5);
|
expect(actionResult).toHaveLength(8);
|
||||||
expect(actionResult[0].type).toStrictEqual('SHOW_LOADING_INDICATION');
|
expect(actionResult[0]).toMatchObject({
|
||||||
expect(actionResult[1].type).toStrictEqual('HIDE_LOADING_INDICATION');
|
type: 'send/addHistoryEntry',
|
||||||
expect(actionResult[2].payload).toStrictEqual({
|
payload: `sendFlow - user set asset type to ${ASSET_TYPES.TOKEN}`,
|
||||||
|
});
|
||||||
|
expect(actionResult[1]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user set asset symbol to tokenSymbol',
|
||||||
|
});
|
||||||
|
expect(actionResult[2]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user set asset address to tokenAddress',
|
||||||
|
});
|
||||||
|
expect(actionResult[3].type).toStrictEqual('SHOW_LOADING_INDICATION');
|
||||||
|
expect(actionResult[4].type).toStrictEqual('HIDE_LOADING_INDICATION');
|
||||||
|
expect(actionResult[5].payload).toStrictEqual({
|
||||||
...newSendAsset,
|
...newSendAsset,
|
||||||
balance: '0x0',
|
balance: '0x0',
|
||||||
error: null,
|
error: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(actionResult[3].type).toStrictEqual(
|
expect(actionResult[6].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/pending',
|
'send/computeEstimatedGasLimit/pending',
|
||||||
);
|
);
|
||||||
expect(actionResult[4].type).toStrictEqual(
|
expect(actionResult[7].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/rejected',
|
'send/computeEstimatedGasLimit/rejected',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1543,10 +1585,22 @@ describe('Send Slice', () => {
|
|||||||
store.dispatch(updateSendAsset(newSendAsset)),
|
store.dispatch(updateSendAsset(newSendAsset)),
|
||||||
).rejects.toThrow('invalidAssetType');
|
).rejects.toThrow('invalidAssetType');
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
expect(actionResult).toHaveLength(3);
|
expect(actionResult).toHaveLength(6);
|
||||||
expect(actionResult[0].type).toStrictEqual('SHOW_LOADING_INDICATION');
|
expect(actionResult[0]).toMatchObject({
|
||||||
expect(actionResult[1].type).toStrictEqual('HIDE_LOADING_INDICATION');
|
type: 'send/addHistoryEntry',
|
||||||
expect(actionResult[2]).toStrictEqual({
|
payload: `sendFlow - user set asset type to ${ASSET_TYPES.TOKEN}`,
|
||||||
|
});
|
||||||
|
expect(actionResult[1]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user set asset symbol to tokenSymbol',
|
||||||
|
});
|
||||||
|
expect(actionResult[2]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user set asset address to tokenAddress',
|
||||||
|
});
|
||||||
|
expect(actionResult[3].type).toStrictEqual('SHOW_LOADING_INDICATION');
|
||||||
|
expect(actionResult[4].type).toStrictEqual('HIDE_LOADING_INDICATION');
|
||||||
|
expect(actionResult[5]).toStrictEqual({
|
||||||
payload: {
|
payload: {
|
||||||
name: 'CONVERT_TOKEN_TO_NFT',
|
name: 'CONVERT_TOKEN_TO_NFT',
|
||||||
tokenAddress: 'tokenAddress',
|
tokenAddress: 'tokenAddress',
|
||||||
@ -1600,24 +1654,32 @@ describe('Send Slice', () => {
|
|||||||
|
|
||||||
await store.dispatch(updateRecipientUserInput(newUserRecipientInput));
|
await store.dispatch(updateRecipientUserInput(newUserRecipientInput));
|
||||||
|
|
||||||
expect(store.getActions()).toHaveLength(1);
|
const actionResult = store.getActions();
|
||||||
expect(store.getActions()[0].type).toStrictEqual(
|
|
||||||
|
expect(actionResult).toHaveLength(1);
|
||||||
|
expect(actionResult[0].type).toStrictEqual(
|
||||||
'send/updateRecipientUserInput',
|
'send/updateRecipientUserInput',
|
||||||
);
|
);
|
||||||
expect(store.getActions()[0].payload).toStrictEqual(
|
expect(actionResult[0].payload).toStrictEqual(newUserRecipientInput);
|
||||||
newUserRecipientInput,
|
|
||||||
);
|
|
||||||
|
|
||||||
clock.tick(300); // debounce
|
clock.tick(300); // debounce
|
||||||
|
|
||||||
expect(store.getActions()).toHaveLength(2);
|
const actionResultAfterDebounce = store.getActions();
|
||||||
expect(store.getActions()[1].type).toStrictEqual(
|
expect(actionResultAfterDebounce).toHaveLength(3);
|
||||||
|
|
||||||
|
expect(actionResultAfterDebounce[1]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: `sendFlow - user typed ${newUserRecipientInput} into recipient input field`,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(actionResultAfterDebounce[2].type).toStrictEqual(
|
||||||
'send/validateRecipientUserInput',
|
'send/validateRecipientUserInput',
|
||||||
);
|
);
|
||||||
expect(store.getActions()[1].payload).toStrictEqual({
|
expect(actionResultAfterDebounce[2].payload).toStrictEqual({
|
||||||
chainId: '',
|
chainId: '',
|
||||||
tokens: [],
|
tokens: [],
|
||||||
useTokenDetection: true,
|
useTokenDetection: true,
|
||||||
|
userInput: newUserRecipientInput,
|
||||||
tokenAddressList: ['0x514910771af9ca656af840dff83e8264ecf986ca'],
|
tokenAddressList: ['0x514910771af9ca656af840dff83e8264ecf986ca'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1630,8 +1692,13 @@ describe('Send Slice', () => {
|
|||||||
await store.dispatch(useContactListForRecipientSearch());
|
await store.dispatch(useContactListForRecipientSearch());
|
||||||
|
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
expect(actionResult).toHaveLength(2);
|
||||||
|
|
||||||
expect(actionResult).toStrictEqual([
|
expect(actionResult).toStrictEqual([
|
||||||
|
{
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user selected back to all on recipient screen',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: 'send/updateRecipientSearchMode',
|
type: 'send/updateRecipientSearchMode',
|
||||||
payload: RECIPIENT_SEARCH_MODES.CONTACT_LIST,
|
payload: RECIPIENT_SEARCH_MODES.CONTACT_LIST,
|
||||||
@ -1648,7 +1715,14 @@ describe('Send Slice', () => {
|
|||||||
|
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
|
expect(actionResult).toHaveLength(2);
|
||||||
|
|
||||||
expect(actionResult).toStrictEqual([
|
expect(actionResult).toStrictEqual([
|
||||||
|
{
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload:
|
||||||
|
'sendFlow - user selected transfer to my accounts on recipient screen',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: 'send/updateRecipientSearchMode',
|
type: 'send/updateRecipientSearchMode',
|
||||||
payload: RECIPIENT_SEARCH_MODES.MY_ACCOUNTS,
|
payload: RECIPIENT_SEARCH_MODES.MY_ACCOUNTS,
|
||||||
@ -1890,20 +1964,24 @@ describe('Send Slice', () => {
|
|||||||
await store.dispatch(resetRecipientInput());
|
await store.dispatch(resetRecipientInput());
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
expect(actionResult).toHaveLength(6);
|
expect(actionResult).toHaveLength(7);
|
||||||
expect(actionResult[0].type).toStrictEqual(
|
expect(actionResult[0]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user cleared recipient input',
|
||||||
|
});
|
||||||
|
expect(actionResult[1].type).toStrictEqual(
|
||||||
'send/updateRecipientUserInput',
|
'send/updateRecipientUserInput',
|
||||||
);
|
);
|
||||||
expect(actionResult[0].payload).toStrictEqual('');
|
expect(actionResult[1].payload).toStrictEqual('');
|
||||||
expect(actionResult[1].type).toStrictEqual('send/updateRecipient');
|
expect(actionResult[2].type).toStrictEqual('send/updateRecipient');
|
||||||
expect(actionResult[2].type).toStrictEqual(
|
expect(actionResult[3].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/pending',
|
'send/computeEstimatedGasLimit/pending',
|
||||||
);
|
);
|
||||||
expect(actionResult[3].type).toStrictEqual(
|
expect(actionResult[4].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/rejected',
|
'send/computeEstimatedGasLimit/rejected',
|
||||||
);
|
);
|
||||||
expect(actionResult[4].type).toStrictEqual('ENS/resetEnsResolution');
|
expect(actionResult[5].type).toStrictEqual('ENS/resetEnsResolution');
|
||||||
expect(actionResult[5].type).toStrictEqual(
|
expect(actionResult[6].type).toStrictEqual(
|
||||||
'send/validateRecipientUserInput',
|
'send/validateRecipientUserInput',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1927,10 +2005,14 @@ describe('Send Slice', () => {
|
|||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
const expectActionResult = [
|
const expectActionResult = [
|
||||||
|
{
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user added custom hexData 0x1',
|
||||||
|
},
|
||||||
{ type: 'send/updateUserInputHexData', payload: hexData },
|
{ type: 'send/updateUserInputHexData', payload: hexData },
|
||||||
];
|
];
|
||||||
|
|
||||||
expect(actionResult).toHaveLength(1);
|
expect(actionResult).toHaveLength(2);
|
||||||
expect(actionResult).toStrictEqual(expectActionResult);
|
expect(actionResult).toStrictEqual(expectActionResult);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1970,13 +2052,17 @@ describe('Send Slice', () => {
|
|||||||
|
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
expect(actionResult).toHaveLength(4);
|
expect(actionResult).toHaveLength(5);
|
||||||
expect(actionResult[0].type).toStrictEqual('send/updateAmountMode');
|
expect(actionResult[0].type).toStrictEqual('send/updateAmountMode');
|
||||||
expect(actionResult[1].type).toStrictEqual('send/updateAmountToMax');
|
expect(actionResult[1].type).toStrictEqual('send/updateAmountToMax');
|
||||||
expect(actionResult[2].type).toStrictEqual(
|
expect(actionResult[2]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user toggled max mode on',
|
||||||
|
});
|
||||||
|
expect(actionResult[3].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/pending',
|
'send/computeEstimatedGasLimit/pending',
|
||||||
);
|
);
|
||||||
expect(actionResult[3].type).toStrictEqual(
|
expect(actionResult[4].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/rejected',
|
'send/computeEstimatedGasLimit/rejected',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -2014,13 +2100,17 @@ describe('Send Slice', () => {
|
|||||||
|
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
expect(actionResult).toHaveLength(4);
|
expect(actionResult).toHaveLength(5);
|
||||||
expect(actionResult[0].type).toStrictEqual('send/updateAmountMode');
|
expect(actionResult[0].type).toStrictEqual('send/updateAmountMode');
|
||||||
expect(actionResult[1].type).toStrictEqual('send/updateSendAmount');
|
expect(actionResult[1].type).toStrictEqual('send/updateSendAmount');
|
||||||
expect(actionResult[2].type).toStrictEqual(
|
expect(actionResult[2]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user toggled max mode off',
|
||||||
|
});
|
||||||
|
expect(actionResult[3].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/pending',
|
'send/computeEstimatedGasLimit/pending',
|
||||||
);
|
);
|
||||||
expect(actionResult[3].type).toStrictEqual(
|
expect(actionResult[4].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/rejected',
|
'send/computeEstimatedGasLimit/rejected',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -2045,8 +2135,13 @@ describe('Send Slice', () => {
|
|||||||
|
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
expect(actionResult).toHaveLength(1);
|
expect(actionResult).toHaveLength(2);
|
||||||
expect(actionResult[0].type).toStrictEqual('SHOW_CONF_TX_PAGE');
|
expect(actionResult[0]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload:
|
||||||
|
'sendFlow - user clicked next and transaction should be added to controller',
|
||||||
|
});
|
||||||
|
expect(actionResult[1].type).toStrictEqual('SHOW_CONF_TX_PAGE');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create actions for updateTransaction rejecting', async () => {
|
it('should create actions for updateTransaction rejecting', async () => {
|
||||||
@ -2081,11 +2176,16 @@ describe('Send Slice', () => {
|
|||||||
|
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
expect(actionResult).toHaveLength(2);
|
expect(actionResult).toHaveLength(3);
|
||||||
expect(actionResult[0].type).toStrictEqual(
|
expect(actionResult[0]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload:
|
||||||
|
'sendFlow - user clicked next and transaction should be updated in controller',
|
||||||
|
});
|
||||||
|
expect(actionResult[1].type).toStrictEqual(
|
||||||
'UPDATE_TRANSACTION_EDITABLE_PARAMS',
|
'UPDATE_TRANSACTION_EDITABLE_PARAMS',
|
||||||
);
|
);
|
||||||
expect(actionResult[1].type).toStrictEqual(
|
expect(actionResult[2].type).toStrictEqual(
|
||||||
'UPDATE_TRANSACTION_GAS_FEES',
|
'UPDATE_TRANSACTION_GAS_FEES',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -2133,9 +2233,13 @@ describe('Send Slice', () => {
|
|||||||
await store.dispatch(editTransaction(ASSET_TYPES.NATIVE, 1));
|
await store.dispatch(editTransaction(ASSET_TYPES.NATIVE, 1));
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
expect(actionResult).toHaveLength(1);
|
expect(actionResult).toHaveLength(2);
|
||||||
expect(actionResult[0].type).toStrictEqual('send/editTransaction');
|
expect(actionResult[0]).toMatchObject({
|
||||||
expect(actionResult[0].payload).toStrictEqual({
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user clicked edit on transaction with id 1',
|
||||||
|
});
|
||||||
|
expect(actionResult[1].type).toStrictEqual('send/editTransaction');
|
||||||
|
expect(actionResult[1].payload).toStrictEqual({
|
||||||
address: '0xRecipientAddress',
|
address: '0xRecipientAddress',
|
||||||
amount: '0xde0b6b3a7640000',
|
amount: '0xde0b6b3a7640000',
|
||||||
data: '',
|
data: '',
|
||||||
@ -2146,7 +2250,7 @@ describe('Send Slice', () => {
|
|||||||
nickname: '',
|
nickname: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const action = actionResult[0];
|
const action = actionResult[1];
|
||||||
|
|
||||||
const result = sendReducer(initialState, action);
|
const result = sendReducer(initialState, action);
|
||||||
|
|
||||||
@ -2254,9 +2358,25 @@ describe('Send Slice', () => {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
expect(actionResult).toHaveLength(5);
|
expect(actionResult).toHaveLength(9);
|
||||||
expect(actionResult[0].type).toStrictEqual('send/updateAsset');
|
expect(actionResult[0]).toMatchObject({
|
||||||
expect(actionResult[0].payload).toStrictEqual({
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user clicked edit on transaction with id 1',
|
||||||
|
});
|
||||||
|
expect(actionResult[1]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: `sendFlow - user set asset type to ${ASSET_TYPES.COLLECTIBLE}`,
|
||||||
|
});
|
||||||
|
expect(actionResult[2]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user set asset symbol to undefined',
|
||||||
|
});
|
||||||
|
expect(actionResult[3]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user set asset address to 0xTokenAddress',
|
||||||
|
});
|
||||||
|
expect(actionResult[4].type).toStrictEqual('send/updateAsset');
|
||||||
|
expect(actionResult[4].payload).toStrictEqual({
|
||||||
balance: '0x1',
|
balance: '0x1',
|
||||||
type: ASSET_TYPES.COLLECTIBLE,
|
type: ASSET_TYPES.COLLECTIBLE,
|
||||||
error: null,
|
error: null,
|
||||||
@ -2270,18 +2390,17 @@ describe('Send Slice', () => {
|
|||||||
tokenId: '26847',
|
tokenId: '26847',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(actionResult[1].type).toStrictEqual(
|
expect(actionResult[5].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/pending',
|
'send/computeEstimatedGasLimit/pending',
|
||||||
);
|
);
|
||||||
expect(actionResult[2].type).toStrictEqual(
|
expect(actionResult[6].type).toStrictEqual(
|
||||||
'metamask/gas/SET_CUSTOM_GAS_LIMIT',
|
'metamask/gas/SET_CUSTOM_GAS_LIMIT',
|
||||||
);
|
);
|
||||||
expect(actionResult[3].type).toStrictEqual(
|
expect(actionResult[7].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/fulfilled',
|
'send/computeEstimatedGasLimit/fulfilled',
|
||||||
);
|
);
|
||||||
expect(actionResult[4].type).toStrictEqual('send/editTransaction');
|
expect(actionResult[8].type).toStrictEqual('send/editTransaction');
|
||||||
|
const action = actionResult[8];
|
||||||
const action = actionResult[4];
|
|
||||||
|
|
||||||
const result = sendReducer(initialState, action);
|
const result = sendReducer(initialState, action);
|
||||||
|
|
||||||
@ -2383,11 +2502,27 @@ describe('Send Slice', () => {
|
|||||||
);
|
);
|
||||||
const actionResult = store.getActions();
|
const actionResult = store.getActions();
|
||||||
|
|
||||||
expect(actionResult).toHaveLength(7);
|
expect(actionResult).toHaveLength(11);
|
||||||
expect(actionResult[0].type).toStrictEqual('SHOW_LOADING_INDICATION');
|
expect(actionResult[0]).toMatchObject({
|
||||||
expect(actionResult[1].type).toStrictEqual('HIDE_LOADING_INDICATION');
|
type: 'send/addHistoryEntry',
|
||||||
expect(actionResult[2].type).toStrictEqual('send/updateAsset');
|
payload: 'sendFlow - user clicked edit on transaction with id 1',
|
||||||
expect(actionResult[2].payload).toStrictEqual({
|
});
|
||||||
|
expect(actionResult[1]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: `sendFlow - user set asset type to ${ASSET_TYPES.TOKEN}`,
|
||||||
|
});
|
||||||
|
expect(actionResult[2]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user set asset symbol to SYMB',
|
||||||
|
});
|
||||||
|
expect(actionResult[3]).toMatchObject({
|
||||||
|
type: 'send/addHistoryEntry',
|
||||||
|
payload: 'sendFlow - user set asset address to 0xTokenAddress',
|
||||||
|
});
|
||||||
|
expect(actionResult[4].type).toStrictEqual('SHOW_LOADING_INDICATION');
|
||||||
|
expect(actionResult[5].type).toStrictEqual('HIDE_LOADING_INDICATION');
|
||||||
|
expect(actionResult[6].type).toStrictEqual('send/updateAsset');
|
||||||
|
expect(actionResult[6].payload).toStrictEqual({
|
||||||
balance: '0x0',
|
balance: '0x0',
|
||||||
type: ASSET_TYPES.TOKEN,
|
type: ASSET_TYPES.TOKEN,
|
||||||
error: null,
|
error: null,
|
||||||
@ -2398,17 +2533,17 @@ describe('Send Slice', () => {
|
|||||||
standard: 'ERC20',
|
standard: 'ERC20',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(actionResult[3].type).toStrictEqual(
|
expect(actionResult[7].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/pending',
|
'send/computeEstimatedGasLimit/pending',
|
||||||
);
|
);
|
||||||
expect(actionResult[4].type).toStrictEqual(
|
expect(actionResult[8].type).toStrictEqual(
|
||||||
'metamask/gas/SET_CUSTOM_GAS_LIMIT',
|
'metamask/gas/SET_CUSTOM_GAS_LIMIT',
|
||||||
);
|
);
|
||||||
expect(actionResult[5].type).toStrictEqual(
|
expect(actionResult[9].type).toStrictEqual(
|
||||||
'send/computeEstimatedGasLimit/fulfilled',
|
'send/computeEstimatedGasLimit/fulfilled',
|
||||||
);
|
);
|
||||||
expect(actionResult[6].type).toStrictEqual('send/editTransaction');
|
expect(actionResult[10].type).toStrictEqual('send/editTransaction');
|
||||||
expect(actionResult[6].payload).toStrictEqual({
|
expect(actionResult[10].payload).toStrictEqual({
|
||||||
address: '0xrecipientaddress', // getting address from tokenData does .toLowerCase
|
address: '0xrecipientaddress', // getting address from tokenData does .toLowerCase
|
||||||
amount: '0x3a98',
|
amount: '0x3a98',
|
||||||
data: '',
|
data: '',
|
||||||
@ -2419,7 +2554,7 @@ describe('Send Slice', () => {
|
|||||||
nickname: '',
|
nickname: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const action = actionResult[6];
|
const action = actionResult[10];
|
||||||
|
|
||||||
const result = sendReducer(initialState, action);
|
const result = sendReducer(initialState, action);
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ export default class AddRecipient extends Component {
|
|||||||
addressBookEntryName: PropTypes.string,
|
addressBookEntryName: PropTypes.string,
|
||||||
contacts: PropTypes.array,
|
contacts: PropTypes.array,
|
||||||
nonContacts: PropTypes.array,
|
nonContacts: PropTypes.array,
|
||||||
|
addHistoryEntry: PropTypes.func,
|
||||||
useMyAccountsForRecipientSearch: PropTypes.func,
|
useMyAccountsForRecipientSearch: PropTypes.func,
|
||||||
useContactListForRecipientSearch: PropTypes.func,
|
useContactListForRecipientSearch: PropTypes.func,
|
||||||
isUsingMyAccountsForRecipientSearch: PropTypes.bool,
|
isUsingMyAccountsForRecipientSearch: PropTypes.bool,
|
||||||
@ -64,7 +65,10 @@ export default class AddRecipient extends Component {
|
|||||||
metricsEvent: PropTypes.func,
|
metricsEvent: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
selectRecipient = (address, nickname = '') => {
|
selectRecipient = (address, nickname = '', type = 'user input') => {
|
||||||
|
this.props.addHistoryEntry(
|
||||||
|
`sendFlow - User clicked recipient from ${type}. address: ${address}, nickname ${nickname}`,
|
||||||
|
);
|
||||||
this.props.updateRecipient({ address, nickname });
|
this.props.updateRecipient({ address, nickname });
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -109,11 +113,13 @@ export default class AddRecipient extends Component {
|
|||||||
content = this.renderExplicitAddress(
|
content = this.renderExplicitAddress(
|
||||||
recipient.address,
|
recipient.address,
|
||||||
recipient.nickname,
|
recipient.nickname,
|
||||||
|
'validated user input',
|
||||||
);
|
);
|
||||||
} else if (ensResolution) {
|
} else if (ensResolution) {
|
||||||
content = this.renderExplicitAddress(
|
content = this.renderExplicitAddress(
|
||||||
ensResolution,
|
ensResolution,
|
||||||
addressBookEntryName || userInput,
|
addressBookEntryName || userInput,
|
||||||
|
'ENS resolution',
|
||||||
);
|
);
|
||||||
} else if (isUsingMyAccountsForRecipientSearch) {
|
} else if (isUsingMyAccountsForRecipientSearch) {
|
||||||
content = this.renderTransfer();
|
content = this.renderTransfer();
|
||||||
@ -127,12 +133,12 @@ export default class AddRecipient extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderExplicitAddress(address, name) {
|
renderExplicitAddress(address, name, type) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={address}
|
key={address}
|
||||||
className="send__select-recipient-wrapper__group-item"
|
className="send__select-recipient-wrapper__group-item"
|
||||||
onClick={() => this.selectRecipient(address, name)}
|
onClick={() => this.selectRecipient(address, name, type)}
|
||||||
>
|
>
|
||||||
<Identicon address={address} diameter={28} />
|
<Identicon address={address} diameter={28} />
|
||||||
<div className="send__select-recipient-wrapper__group-item__content">
|
<div className="send__select-recipient-wrapper__group-item__content">
|
||||||
@ -179,7 +185,9 @@ export default class AddRecipient extends Component {
|
|||||||
<RecipientGroup
|
<RecipientGroup
|
||||||
label={t('myAccounts')}
|
label={t('myAccounts')}
|
||||||
items={ownedAccounts}
|
items={ownedAccounts}
|
||||||
onSelect={this.selectRecipient}
|
onSelect={(address, name) =>
|
||||||
|
this.selectRecipient(address, name, 'my accounts')
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -200,7 +208,9 @@ export default class AddRecipient extends Component {
|
|||||||
addressBook={addressBook}
|
addressBook={addressBook}
|
||||||
searchForContacts={this.searchForContacts.bind(this)}
|
searchForContacts={this.searchForContacts.bind(this)}
|
||||||
searchForRecents={this.searchForRecents.bind(this)}
|
searchForRecents={this.searchForRecents.bind(this)}
|
||||||
selectRecipient={this.selectRecipient.bind(this)}
|
selectRecipient={(address, name) =>
|
||||||
|
this.selectRecipient(address, name, 'contact list')
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{ownedAccounts && ownedAccounts.length > 1 && !userInput && (
|
{ownedAccounts && ownedAccounts.length > 1 && !userInput && (
|
||||||
<Button
|
<Button
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
getIsUsingMyAccountForRecipientSearch,
|
getIsUsingMyAccountForRecipientSearch,
|
||||||
getRecipientUserInput,
|
getRecipientUserInput,
|
||||||
getRecipient,
|
getRecipient,
|
||||||
|
addHistoryEntry,
|
||||||
} from '../../../../ducks/send';
|
} from '../../../../ducks/send';
|
||||||
import {
|
import {
|
||||||
getEnsResolution,
|
getEnsResolution,
|
||||||
@ -55,6 +56,7 @@ function mapStateToProps(state) {
|
|||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
function mapDispatchToProps(dispatch) {
|
||||||
return {
|
return {
|
||||||
|
addHistoryEntry: (entry) => dispatch(addHistoryEntry(entry)),
|
||||||
updateRecipient: ({ address, nickname }) =>
|
updateRecipient: ({ address, nickname }) =>
|
||||||
dispatch(updateRecipient({ address, nickname })),
|
dispatch(updateRecipient({ address, nickname })),
|
||||||
updateRecipientUserInput: (newInput) =>
|
updateRecipientUserInput: (newInput) =>
|
||||||
|
@ -2,6 +2,7 @@ import React, { useEffect, useCallback, useContext } from 'react';
|
|||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { useHistory, useLocation } from 'react-router-dom';
|
import { useHistory, useLocation } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
|
addHistoryEntry,
|
||||||
getIsUsingMyAccountForRecipientSearch,
|
getIsUsingMyAccountForRecipientSearch,
|
||||||
getRecipient,
|
getRecipient,
|
||||||
getRecipientUserInput,
|
getRecipientUserInput,
|
||||||
@ -95,13 +96,23 @@ export default function SendTransactionScreen() {
|
|||||||
userInput={userInput}
|
userInput={userInput}
|
||||||
className="send__to-row"
|
className="send__to-row"
|
||||||
onChange={(address) => dispatch(updateRecipientUserInput(address))}
|
onChange={(address) => dispatch(updateRecipientUserInput(address))}
|
||||||
onValidAddressTyped={(address) =>
|
onValidAddressTyped={(address) => {
|
||||||
dispatch(updateRecipient({ address, nickname: '' }))
|
dispatch(
|
||||||
}
|
addHistoryEntry(`sendFlow - Valid address typed ${address}`),
|
||||||
|
);
|
||||||
|
dispatch(updateRecipient({ address, nickname: '' }));
|
||||||
|
}}
|
||||||
internalSearch={isUsingMyAccountsForRecipientSearch}
|
internalSearch={isUsingMyAccountsForRecipientSearch}
|
||||||
selectedAddress={recipient.address}
|
selectedAddress={recipient.address}
|
||||||
selectedName={recipient.nickname}
|
selectedName={recipient.nickname}
|
||||||
onPaste={(text) => updateRecipient({ address: text, nickname: '' })}
|
onPaste={(text) => {
|
||||||
|
dispatch(
|
||||||
|
addHistoryEntry(
|
||||||
|
`sendFlow - User pasted ${text} into address field`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return dispatch(updateRecipient({ address: text, nickname: '' }));
|
||||||
|
}}
|
||||||
onReset={() => dispatch(resetRecipientInput())}
|
onReset={() => dispatch(resetRecipientInput())}
|
||||||
scanQrCode={() => {
|
scanQrCode={() => {
|
||||||
trackEvent({
|
trackEvent({
|
||||||
|
@ -738,6 +738,32 @@ export function updateEditableParams(txId, editableParams) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends new send flow history to a transaction
|
||||||
|
*
|
||||||
|
* @param {string} txId - the id of the transaction to update
|
||||||
|
* @param {Array<{event: string, timestamp: number}>} sendFlowHistory - the new send flow history to append to the
|
||||||
|
* transaction
|
||||||
|
* @returns {import('../../shared/constants/transaction').TransactionMeta}
|
||||||
|
*/
|
||||||
|
export function updateTransactionSendFlowHistory(txId, sendFlowHistory) {
|
||||||
|
return async (dispatch) => {
|
||||||
|
let updatedTransaction;
|
||||||
|
try {
|
||||||
|
updatedTransaction = await promisifiedBackground.updateTransactionSendFlowHistory(
|
||||||
|
txId,
|
||||||
|
sendFlowHistory,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
dispatch(txError(error));
|
||||||
|
log.error(error.message);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return updatedTransaction;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function updateTransactionGasFees(txId, txGasFees) {
|
export function updateTransactionGasFees(txId, txGasFees) {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
let updatedTransaction;
|
let updatedTransaction;
|
||||||
@ -811,11 +837,14 @@ export function updateTransaction(txData, dontShowLoadingIndicator) {
|
|||||||
* @param {import(
|
* @param {import(
|
||||||
* '../../shared/constants/transaction'
|
* '../../shared/constants/transaction'
|
||||||
* ).TransactionTypeString} type - The type of the transaction being added.
|
* ).TransactionTypeString} type - The type of the transaction being added.
|
||||||
|
* @param {Array<{event: string, timestamp: number}>} sendFlowHistory - The
|
||||||
|
* history of the send flow at time of creation.
|
||||||
* @returns {import('../../shared/constants/transaction').TransactionMeta}
|
* @returns {import('../../shared/constants/transaction').TransactionMeta}
|
||||||
*/
|
*/
|
||||||
export function addUnapprovedTransactionAndRouteToConfirmationPage(
|
export function addUnapprovedTransactionAndRouteToConfirmationPage(
|
||||||
txParams,
|
txParams,
|
||||||
type,
|
type,
|
||||||
|
sendFlowHistory,
|
||||||
) {
|
) {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
try {
|
try {
|
||||||
@ -824,6 +853,7 @@ export function addUnapprovedTransactionAndRouteToConfirmationPage(
|
|||||||
txParams,
|
txParams,
|
||||||
ORIGIN_METAMASK,
|
ORIGIN_METAMASK,
|
||||||
type,
|
type,
|
||||||
|
sendFlowHistory,
|
||||||
);
|
);
|
||||||
dispatch(showConfTxPage());
|
dispatch(showConfTxPage());
|
||||||
return txMeta;
|
return txMeta;
|
||||||
|
Loading…
Reference in New Issue
Block a user