mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-10-22 19:26:13 +02:00
parent
84b1379b40
commit
b21cc5660f
@ -385,7 +385,7 @@ export default class TransactionController extends EventEmitter {
|
|||||||
* @param {string} [customGasPrice] - the hex value to use for the cancel transaction
|
* @param {string} [customGasPrice] - the hex value to use for the cancel transaction
|
||||||
* @returns {txMeta}
|
* @returns {txMeta}
|
||||||
*/
|
*/
|
||||||
async createCancelTransaction(originalTxId, customGasPrice) {
|
async createCancelTransaction(originalTxId, customGasPrice, customGasLimit) {
|
||||||
const originalTxMeta = this.txStateManager.getTx(originalTxId);
|
const originalTxMeta = this.txStateManager.getTx(originalTxId);
|
||||||
const { txParams } = originalTxMeta;
|
const { txParams } = originalTxMeta;
|
||||||
const { gasPrice: lastGasPrice, from, nonce } = txParams;
|
const { gasPrice: lastGasPrice, from, nonce } = txParams;
|
||||||
@ -398,7 +398,7 @@ export default class TransactionController extends EventEmitter {
|
|||||||
from,
|
from,
|
||||||
to: from,
|
to: from,
|
||||||
nonce,
|
nonce,
|
||||||
gas: '0x5208',
|
gas: customGasLimit || '0x5208',
|
||||||
value: '0x0',
|
value: '0x0',
|
||||||
gasPrice: newGasPrice,
|
gasPrice: newGasPrice,
|
||||||
},
|
},
|
||||||
|
@ -1858,10 +1858,11 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
* @param {string} [customGasPrice] - the hex value to use for the cancel transaction
|
* @param {string} [customGasPrice] - the hex value to use for the cancel transaction
|
||||||
* @returns {Object} MetaMask state
|
* @returns {Object} MetaMask state
|
||||||
*/
|
*/
|
||||||
async createCancelTransaction(originalTxId, customGasPrice) {
|
async createCancelTransaction(originalTxId, customGasPrice, customGasLimit) {
|
||||||
await this.txController.createCancelTransaction(
|
await this.txController.createCancelTransaction(
|
||||||
originalTxId,
|
originalTxId,
|
||||||
customGasPrice,
|
customGasPrice,
|
||||||
|
customGasLimit,
|
||||||
);
|
);
|
||||||
const state = await this.getState();
|
const state = await this.getState();
|
||||||
return state;
|
return state;
|
||||||
|
@ -61,7 +61,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
const { currentNetworkTxList, send } = state.metamask;
|
const { currentNetworkTxList, send } = state.metamask;
|
||||||
const { modalState: { props: modalProps } = {} } = state.appState.modal || {};
|
const { modalState: { props: modalProps } = {} } = state.appState.modal || {};
|
||||||
const { txData = {} } = modalProps || {};
|
const { txData = {} } = modalProps || {};
|
||||||
const { transaction = {} } = ownProps;
|
const { transaction = {}, onSubmit } = ownProps;
|
||||||
const selectedTransaction = currentNetworkTxList.find(
|
const selectedTransaction = currentNetworkTxList.find(
|
||||||
({ id }) => id === (transaction.id || txData.id),
|
({ id }) => id === (transaction.id || txData.id),
|
||||||
);
|
);
|
||||||
@ -77,7 +77,8 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
value: sendToken ? '0x0' : send.amount,
|
value: sendToken ? '0x0' : send.amount,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { gasPrice: currentGasPrice, gas: currentGasLimit, value } = txParams;
|
const { gasPrice: currentGasPrice, gas: currentGasLimit } = txParams;
|
||||||
|
const value = ownProps.transaction?.txParams?.value || txParams.value;
|
||||||
const customModalGasPriceInHex = getCustomGasPrice(state) || currentGasPrice;
|
const customModalGasPriceInHex = getCustomGasPrice(state) || currentGasPrice;
|
||||||
const customModalGasLimitInHex =
|
const customModalGasLimitInHex =
|
||||||
getCustomGasLimit(state) || currentGasLimit || '0x5208';
|
getCustomGasLimit(state) || currentGasLimit || '0x5208';
|
||||||
@ -175,6 +176,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
tokenBalance: getTokenBalance(state),
|
tokenBalance: getTokenBalance(state),
|
||||||
conversionRate,
|
conversionRate,
|
||||||
value,
|
value,
|
||||||
|
onSubmit,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -253,6 +255,12 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
|||||||
...otherDispatchProps,
|
...otherDispatchProps,
|
||||||
...ownProps,
|
...ownProps,
|
||||||
onSubmit: (gasLimit, gasPrice) => {
|
onSubmit: (gasLimit, gasPrice) => {
|
||||||
|
if (ownProps.onSubmit) {
|
||||||
|
dispatchHideSidebar();
|
||||||
|
dispatchCancelAndClose();
|
||||||
|
ownProps.onSubmit(gasLimit, gasPrice);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (isConfirm) {
|
if (isConfirm) {
|
||||||
const updatedTx = {
|
const updatedTx = {
|
||||||
...transaction,
|
...transaction,
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import proxyquire from 'proxyquire';
|
import proxyquire from 'proxyquire';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import { TRANSACTION_STATUSES } from '../../../../../../../shared/constants/transaction';
|
|
||||||
|
|
||||||
let mapStateToProps;
|
|
||||||
let mapDispatchToProps;
|
let mapDispatchToProps;
|
||||||
let mergeProps;
|
let mergeProps;
|
||||||
|
|
||||||
@ -25,8 +23,7 @@ const sendActionSpies = {
|
|||||||
|
|
||||||
proxyquire('../gas-modal-page-container.container.js', {
|
proxyquire('../gas-modal-page-container.container.js', {
|
||||||
'react-redux': {
|
'react-redux': {
|
||||||
connect: (ms, md, mp) => {
|
connect: (_, md, mp) => {
|
||||||
mapStateToProps = ms;
|
|
||||||
mapDispatchToProps = md;
|
mapDispatchToProps = md;
|
||||||
mergeProps = mp;
|
mergeProps = mp;
|
||||||
return () => ({});
|
return () => ({});
|
||||||
@ -48,225 +45,6 @@ proxyquire('../gas-modal-page-container.container.js', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('gas-modal-page-container container', function () {
|
describe('gas-modal-page-container container', function () {
|
||||||
describe('mapStateToProps()', function () {
|
|
||||||
it('should map the correct properties to props', function () {
|
|
||||||
const baseMockState = {
|
|
||||||
appState: {
|
|
||||||
modal: {
|
|
||||||
modalState: {
|
|
||||||
props: {
|
|
||||||
hideBasic: true,
|
|
||||||
txData: {
|
|
||||||
id: 34,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
metamask: {
|
|
||||||
send: {
|
|
||||||
gasLimit: '16',
|
|
||||||
gasPrice: '32',
|
|
||||||
amount: '64',
|
|
||||||
maxModeOn: false,
|
|
||||||
},
|
|
||||||
currentCurrency: 'abc',
|
|
||||||
conversionRate: 50,
|
|
||||||
usdConversionRate: 123,
|
|
||||||
preferences: {
|
|
||||||
showFiatInTestnets: false,
|
|
||||||
},
|
|
||||||
provider: {
|
|
||||||
type: 'mainnet',
|
|
||||||
chainId: '0x1',
|
|
||||||
},
|
|
||||||
currentNetworkTxList: [
|
|
||||||
{
|
|
||||||
id: 34,
|
|
||||||
txParams: {
|
|
||||||
gas: '0x1600000',
|
|
||||||
gasPrice: '0x3200000',
|
|
||||||
value: '0x640000000000000',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
gas: {
|
|
||||||
basicEstimates: {
|
|
||||||
blockTime: 12,
|
|
||||||
safeLow: 2,
|
|
||||||
},
|
|
||||||
customData: {
|
|
||||||
limit: 'aaaaaaaa',
|
|
||||||
price: 'ffffffff',
|
|
||||||
},
|
|
||||||
priceAndTimeEstimates: [
|
|
||||||
{ gasprice: 3, expectedTime: 31 },
|
|
||||||
{ gasprice: 4, expectedTime: 62 },
|
|
||||||
{ gasprice: 5, expectedTime: 93 },
|
|
||||||
{ gasprice: 6, expectedTime: 124 },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
confirmTransaction: {
|
|
||||||
txData: {
|
|
||||||
txParams: {
|
|
||||||
gas: '0x1600000',
|
|
||||||
gasPrice: '0x3200000',
|
|
||||||
value: '0x640000000000000',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const baseExpectedResult = {
|
|
||||||
balance: '0x0',
|
|
||||||
isConfirm: true,
|
|
||||||
customGasPrice: 4.294967295,
|
|
||||||
customGasLimit: 2863311530,
|
|
||||||
newTotalFiat: '637.41',
|
|
||||||
conversionRate: 50,
|
|
||||||
customModalGasLimitInHex: 'aaaaaaaa',
|
|
||||||
customModalGasPriceInHex: 'ffffffff',
|
|
||||||
customPriceIsExcessive: false,
|
|
||||||
customGasTotal: 'aaaaaaa955555556',
|
|
||||||
customPriceIsSafe: true,
|
|
||||||
gasPriceButtonGroupProps: {
|
|
||||||
buttonDataLoading: 'mockBasicGasEstimateLoadingStatus:4',
|
|
||||||
defaultActiveButtonIndex: 'mockRenderableBasicEstimateData:4ffffffff',
|
|
||||||
gasButtonInfo: 'mockRenderableBasicEstimateData:4',
|
|
||||||
},
|
|
||||||
hideBasic: true,
|
|
||||||
infoRowProps: {
|
|
||||||
originalTotalFiat: '637.41',
|
|
||||||
originalTotalEth: '12.748189 ETH',
|
|
||||||
newTotalFiat: '637.41',
|
|
||||||
newTotalEth: '12.748189 ETH',
|
|
||||||
sendAmount: '0.45036 ETH',
|
|
||||||
transactionFee: '12.297829 ETH',
|
|
||||||
},
|
|
||||||
insufficientBalance: true,
|
|
||||||
isSpeedUp: false,
|
|
||||||
isRetry: false,
|
|
||||||
txId: 34,
|
|
||||||
isMainnet: true,
|
|
||||||
maxModeOn: false,
|
|
||||||
sendToken: null,
|
|
||||||
tokenBalance: '0x0',
|
|
||||||
transaction: {
|
|
||||||
id: 34,
|
|
||||||
},
|
|
||||||
value: '0x640000000000000',
|
|
||||||
};
|
|
||||||
const baseMockOwnProps = { transaction: { id: 34 } };
|
|
||||||
const tests = [
|
|
||||||
{
|
|
||||||
mockState: baseMockState,
|
|
||||||
expectedResult: baseExpectedResult,
|
|
||||||
mockOwnProps: baseMockOwnProps,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
mockState: {
|
|
||||||
...baseMockState,
|
|
||||||
metamask: {
|
|
||||||
...baseMockState.metamask,
|
|
||||||
balance: '0xfffffffffffffffffffff',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectedResult: {
|
|
||||||
...baseExpectedResult,
|
|
||||||
balance: '0xfffffffffffffffffffff',
|
|
||||||
insufficientBalance: false,
|
|
||||||
},
|
|
||||||
mockOwnProps: baseMockOwnProps,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
mockState: baseMockState,
|
|
||||||
mockOwnProps: {
|
|
||||||
...baseMockOwnProps,
|
|
||||||
transaction: { id: 34, status: TRANSACTION_STATUSES.SUBMITTED },
|
|
||||||
},
|
|
||||||
expectedResult: {
|
|
||||||
...baseExpectedResult,
|
|
||||||
isSpeedUp: true,
|
|
||||||
transaction: { id: 34 },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
mockState: {
|
|
||||||
...baseMockState,
|
|
||||||
metamask: {
|
|
||||||
...baseMockState.metamask,
|
|
||||||
preferences: {
|
|
||||||
...baseMockState.metamask.preferences,
|
|
||||||
showFiatInTestnets: false,
|
|
||||||
},
|
|
||||||
provider: {
|
|
||||||
...baseMockState.metamask.provider,
|
|
||||||
type: 'rinkeby',
|
|
||||||
chainId: '0x4',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mockOwnProps: baseMockOwnProps,
|
|
||||||
expectedResult: {
|
|
||||||
...baseExpectedResult,
|
|
||||||
infoRowProps: {
|
|
||||||
...baseExpectedResult.infoRowProps,
|
|
||||||
newTotalFiat: '',
|
|
||||||
},
|
|
||||||
isMainnet: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
mockState: {
|
|
||||||
...baseMockState,
|
|
||||||
metamask: {
|
|
||||||
...baseMockState.metamask,
|
|
||||||
preferences: {
|
|
||||||
...baseMockState.metamask.preferences,
|
|
||||||
showFiatInTestnets: true,
|
|
||||||
},
|
|
||||||
provider: {
|
|
||||||
...baseMockState.metamask.provider,
|
|
||||||
type: 'rinkeby',
|
|
||||||
chainId: '0x4',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mockOwnProps: baseMockOwnProps,
|
|
||||||
expectedResult: {
|
|
||||||
...baseExpectedResult,
|
|
||||||
isMainnet: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
mockState: {
|
|
||||||
...baseMockState,
|
|
||||||
metamask: {
|
|
||||||
...baseMockState.metamask,
|
|
||||||
preferences: {
|
|
||||||
...baseMockState.metamask.preferences,
|
|
||||||
showFiatInTestnets: true,
|
|
||||||
},
|
|
||||||
provider: {
|
|
||||||
...baseMockState.metamask.provider,
|
|
||||||
type: 'mainnet',
|
|
||||||
chainId: '0x1',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mockOwnProps: baseMockOwnProps,
|
|
||||||
expectedResult: baseExpectedResult,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
let result;
|
|
||||||
tests.forEach(({ mockState, mockOwnProps, expectedResult }) => {
|
|
||||||
result = mapStateToProps(mockState, mockOwnProps);
|
|
||||||
assert.deepStrictEqual(result, expectedResult);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('mapDispatchToProps()', function () {
|
describe('mapDispatchToProps()', function () {
|
||||||
let dispatchSpy;
|
let dispatchSpy;
|
||||||
let mapDispatchToPropsObject;
|
let mapDispatchToPropsObject;
|
||||||
|
@ -1,47 +1,40 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { compose } from 'redux';
|
import { compose } from 'redux';
|
||||||
import { multiplyCurrencies } from '../../../../helpers/utils/conversion-util';
|
|
||||||
import withModalProps from '../../../../helpers/higher-order-components/with-modal-props';
|
import withModalProps from '../../../../helpers/higher-order-components/with-modal-props';
|
||||||
import { showModal, createCancelTransaction } from '../../../../store/actions';
|
import { showModal, createCancelTransaction } from '../../../../store/actions';
|
||||||
import { getHexGasTotal } from '../../../../helpers/utils/confirm-tx.util';
|
|
||||||
import { addHexPrefix } from '../../../../../../app/scripts/lib/util';
|
|
||||||
import CancelTransaction from './cancel-transaction.component';
|
import CancelTransaction from './cancel-transaction.component';
|
||||||
|
|
||||||
const mapStateToProps = (state, ownProps) => {
|
const mapStateToProps = (state, ownProps) => {
|
||||||
const { metamask } = state;
|
const { metamask } = state;
|
||||||
const { transactionId, originalGasPrice } = ownProps;
|
const {
|
||||||
|
transactionId,
|
||||||
|
originalGasPrice,
|
||||||
|
newGasFee,
|
||||||
|
defaultNewGasPrice,
|
||||||
|
gasLimit,
|
||||||
|
} = ownProps;
|
||||||
const { currentNetworkTxList } = metamask;
|
const { currentNetworkTxList } = metamask;
|
||||||
const transaction = currentNetworkTxList.find(
|
const transaction = currentNetworkTxList.find(
|
||||||
({ id }) => id === transactionId,
|
({ id }) => id === transactionId,
|
||||||
);
|
);
|
||||||
const transactionStatus = transaction ? transaction.status : '';
|
const transactionStatus = transaction ? transaction.status : '';
|
||||||
|
|
||||||
const defaultNewGasPrice = addHexPrefix(
|
|
||||||
multiplyCurrencies(originalGasPrice, 1.1, {
|
|
||||||
toNumericBase: 'hex',
|
|
||||||
multiplicandBase: 16,
|
|
||||||
multiplierBase: 10,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const newGasFee = getHexGasTotal({
|
|
||||||
gasPrice: defaultNewGasPrice,
|
|
||||||
gasLimit: '0x5208',
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
transactionId,
|
transactionId,
|
||||||
transactionStatus,
|
transactionStatus,
|
||||||
originalGasPrice,
|
originalGasPrice,
|
||||||
defaultNewGasPrice,
|
defaultNewGasPrice,
|
||||||
newGasFee,
|
newGasFee,
|
||||||
|
gasLimit,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
createCancelTransaction: (txId, customGasPrice) => {
|
createCancelTransaction: (txId, customGasPrice, customGasLimit) => {
|
||||||
return dispatch(createCancelTransaction(txId, customGasPrice));
|
return dispatch(
|
||||||
|
createCancelTransaction(txId, customGasPrice, customGasLimit),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
showTransactionConfirmedModal: () =>
|
showTransactionConfirmedModal: () =>
|
||||||
dispatch(showModal({ name: 'TRANSACTION_CONFIRMED' })),
|
dispatch(showModal({ name: 'TRANSACTION_CONFIRMED' })),
|
||||||
@ -49,7 +42,12 @@ const mapDispatchToProps = (dispatch) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||||
const { transactionId, defaultNewGasPrice, ...restStateProps } = stateProps;
|
const {
|
||||||
|
transactionId,
|
||||||
|
defaultNewGasPrice,
|
||||||
|
gasLimit,
|
||||||
|
...restStateProps
|
||||||
|
} = stateProps;
|
||||||
// eslint-disable-next-line no-shadow
|
// eslint-disable-next-line no-shadow
|
||||||
const { createCancelTransaction, ...restDispatchProps } = dispatchProps;
|
const { createCancelTransaction, ...restDispatchProps } = dispatchProps;
|
||||||
|
|
||||||
@ -58,7 +56,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
|||||||
...restDispatchProps,
|
...restDispatchProps,
|
||||||
...ownProps,
|
...ownProps,
|
||||||
createCancelTransaction: () =>
|
createCancelTransaction: () =>
|
||||||
createCancelTransaction(transactionId, defaultNewGasPrice),
|
createCancelTransaction(transactionId, defaultNewGasPrice, gasLimit),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@ export default class Sidebar extends Component {
|
|||||||
|
|
||||||
renderSidebarContent() {
|
renderSidebarContent() {
|
||||||
const { type, sidebarProps = {} } = this.props;
|
const { type, sidebarProps = {} } = this.props;
|
||||||
const { transaction = {} } = sidebarProps;
|
const { transaction = {}, onSubmit } = sidebarProps;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'customize-gas':
|
case 'customize-gas':
|
||||||
return (
|
return (
|
||||||
<div className="sidebar-left">
|
<div className="sidebar-left">
|
||||||
<CustomizeGas transaction={transaction} />
|
<CustomizeGas transaction={transaction} onSubmit={onSubmit} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
|
@ -118,13 +118,21 @@ export default function TransactionListItem({
|
|||||||
<Button
|
<Button
|
||||||
type="secondary"
|
type="secondary"
|
||||||
rounded
|
rounded
|
||||||
onClick={retryTransaction}
|
onClick={hasCancelled ? cancelTransaction : retryTransaction}
|
||||||
className="transaction-list-item-details__header-button"
|
style={hasCancelled ? { width: 'auto' } : null}
|
||||||
>
|
>
|
||||||
{t('speedUp')}
|
{hasCancelled ? t('speedUpCancellation') : t('speedUp')}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}, [shouldShowSpeedUp, isUnapproved, t, isPending, retryTransaction]);
|
}, [
|
||||||
|
shouldShowSpeedUp,
|
||||||
|
isUnapproved,
|
||||||
|
t,
|
||||||
|
isPending,
|
||||||
|
retryTransaction,
|
||||||
|
hasCancelled,
|
||||||
|
cancelTransaction,
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -7,6 +7,7 @@ import { getConversionRate, getSelectedAccount } from '../../selectors';
|
|||||||
import { useCancelTransaction } from '../useCancelTransaction';
|
import { useCancelTransaction } from '../useCancelTransaction';
|
||||||
import { showModal } from '../../store/actions';
|
import { showModal } from '../../store/actions';
|
||||||
import { increaseLastGasPrice } from '../../helpers/utils/confirm-tx.util';
|
import { increaseLastGasPrice } from '../../helpers/utils/confirm-tx.util';
|
||||||
|
import * as actionConstants from '../../store/actionConstants';
|
||||||
|
|
||||||
describe('useCancelTransaction', function () {
|
describe('useCancelTransaction', function () {
|
||||||
let useSelector;
|
let useSelector;
|
||||||
@ -46,7 +47,7 @@ describe('useCancelTransaction', function () {
|
|||||||
);
|
);
|
||||||
assert.strictEqual(result.current[0], false);
|
assert.strictEqual(result.current[0], false);
|
||||||
});
|
});
|
||||||
it(`should return a function that kicks off cancellation for id ${transactionId}`, function () {
|
it(`should return a function that opens the gas sidebar onsubmit kicks off cancellation for id ${transactionId}`, function () {
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useCancelTransaction(transactionGroup),
|
useCancelTransaction(transactionGroup),
|
||||||
);
|
);
|
||||||
@ -55,12 +56,35 @@ describe('useCancelTransaction', function () {
|
|||||||
preventDefault: () => undefined,
|
preventDefault: () => undefined,
|
||||||
stopPropagation: () => undefined,
|
stopPropagation: () => undefined,
|
||||||
});
|
});
|
||||||
|
const dispatchAction = dispatch.args;
|
||||||
|
|
||||||
|
// calls customize-gas sidebar
|
||||||
|
// also check type= customize-gas
|
||||||
|
assert.strictEqual(
|
||||||
|
dispatchAction[dispatchAction.length - 1][0].type,
|
||||||
|
actionConstants.SIDEBAR_OPEN,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
dispatchAction[dispatchAction.length - 1][0].value.props.transaction
|
||||||
|
.id,
|
||||||
|
transactionId,
|
||||||
|
);
|
||||||
|
|
||||||
|
// call onSubmit myself
|
||||||
|
dispatchAction[dispatchAction.length - 1][0].value.props.onSubmit(
|
||||||
|
'0x5208',
|
||||||
|
'0x1',
|
||||||
|
);
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
dispatch.calledWith(
|
dispatch.calledWith(
|
||||||
showModal({
|
showModal({
|
||||||
name: 'CANCEL_TRANSACTION',
|
name: 'CANCEL_TRANSACTION',
|
||||||
transactionId,
|
transactionId,
|
||||||
originalGasPrice,
|
newGasFee: '0x5208',
|
||||||
|
defaultNewGasPrice: '0x1',
|
||||||
|
gasLimit: '0x5208',
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
@ -98,7 +122,7 @@ describe('useCancelTransaction', function () {
|
|||||||
);
|
);
|
||||||
assert.strictEqual(result.current[0], true);
|
assert.strictEqual(result.current[0], true);
|
||||||
});
|
});
|
||||||
it(`should return a function that kicks off cancellation for id ${transactionId}`, function () {
|
it(`should return a function that opens the gas sidebar onsubmit kicks off cancellation for id ${transactionId}`, function () {
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useCancelTransaction(transactionGroup),
|
useCancelTransaction(transactionGroup),
|
||||||
);
|
);
|
||||||
@ -107,12 +131,31 @@ describe('useCancelTransaction', function () {
|
|||||||
preventDefault: () => undefined,
|
preventDefault: () => undefined,
|
||||||
stopPropagation: () => undefined,
|
stopPropagation: () => undefined,
|
||||||
});
|
});
|
||||||
|
const dispatchAction = dispatch.args;
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
dispatchAction[dispatchAction.length - 1][0].type,
|
||||||
|
actionConstants.SIDEBAR_OPEN,
|
||||||
|
);
|
||||||
|
assert.strictEqual(
|
||||||
|
dispatchAction[dispatchAction.length - 1][0].value.props.transaction
|
||||||
|
.id,
|
||||||
|
transactionId,
|
||||||
|
);
|
||||||
|
|
||||||
|
dispatchAction[dispatchAction.length - 1][0].value.props.onSubmit(
|
||||||
|
'0x5208',
|
||||||
|
'0x1',
|
||||||
|
);
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
dispatch.calledWith(
|
dispatch.calledWith(
|
||||||
showModal({
|
showModal({
|
||||||
name: 'CANCEL_TRANSACTION',
|
name: 'CANCEL_TRANSACTION',
|
||||||
transactionId,
|
transactionId,
|
||||||
originalGasPrice,
|
newGasFee: '0x5208',
|
||||||
|
defaultNewGasPrice: '0x1',
|
||||||
|
gasLimit: '0x5208',
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
|
@ -64,6 +64,50 @@ describe('useRetryTransaction', function () {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle cancelled or multiple speedup transactions', async function () {
|
||||||
|
const cancelledTransaction = {
|
||||||
|
initialTransaction: {
|
||||||
|
...transactions[0].initialTransaction,
|
||||||
|
txParams: {
|
||||||
|
...transactions[0].initialTransaction.txParams,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
primaryTransaction: {
|
||||||
|
...transactions[0].primaryTransaction,
|
||||||
|
txParams: {
|
||||||
|
from: '0xee014609ef9e09776ac5fe00bdbfef57bcdefebb',
|
||||||
|
gas: '0x5308',
|
||||||
|
gasPrice: '0x77359400',
|
||||||
|
nonce: '0x3',
|
||||||
|
to: '0xabca64466f257793eaa52fcfff5066894b76a149',
|
||||||
|
value: '0x0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
transactions: [
|
||||||
|
{
|
||||||
|
submittedTime: new Date() - 5001,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
hasRetried: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const { result } = renderHook(() =>
|
||||||
|
useRetryTransaction(cancelledTransaction, true),
|
||||||
|
);
|
||||||
|
const retry = result.current;
|
||||||
|
await retry(event);
|
||||||
|
assert.strictEqual(
|
||||||
|
dispatch.calledWith(
|
||||||
|
showSidebar({
|
||||||
|
transitionName: 'sidebar-left',
|
||||||
|
type: 'customize-gas',
|
||||||
|
props: { transaction: cancelledTransaction.primaryTransaction },
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
after(function () {
|
after(function () {
|
||||||
sinon.restore();
|
sinon.restore();
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { showModal } from '../store/actions';
|
import { addHexPrefix } from 'ethereumjs-util';
|
||||||
|
import { showModal, showSidebar } from '../store/actions';
|
||||||
import { isBalanceSufficient } from '../pages/send/send.utils';
|
import { isBalanceSufficient } from '../pages/send/send.utils';
|
||||||
import {
|
import {
|
||||||
getHexGasTotal,
|
getHexGasTotal,
|
||||||
increaseLastGasPrice,
|
increaseLastGasPrice,
|
||||||
} from '../helpers/utils/confirm-tx.util';
|
} from '../helpers/utils/confirm-tx.util';
|
||||||
import { getConversionRate, getSelectedAccount } from '../selectors';
|
import { getConversionRate, getSelectedAccount } from '../selectors';
|
||||||
|
import {
|
||||||
|
setCustomGasLimit,
|
||||||
|
setCustomGasPriceForRetry,
|
||||||
|
} from '../ducks/gas/gas.duck';
|
||||||
|
import { multiplyCurrencies } from '../helpers/utils/conversion-util';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether a transaction can be cancelled and provide a method to
|
* Determine whether a transaction can be cancelled and provide a method to
|
||||||
@ -19,27 +25,61 @@ import { getConversionRate, getSelectedAccount } from '../selectors';
|
|||||||
* @return {[boolean, Function]}
|
* @return {[boolean, Function]}
|
||||||
*/
|
*/
|
||||||
export function useCancelTransaction(transactionGroup) {
|
export function useCancelTransaction(transactionGroup) {
|
||||||
const { primaryTransaction, initialTransaction } = transactionGroup;
|
const { primaryTransaction } = transactionGroup;
|
||||||
const gasPrice = primaryTransaction.txParams?.gasPrice?.startsWith('-')
|
const gasPrice = primaryTransaction.txParams?.gasPrice?.startsWith('-')
|
||||||
? '0x0'
|
? '0x0'
|
||||||
: primaryTransaction.txParams?.gasPrice;
|
: primaryTransaction.txParams?.gasPrice;
|
||||||
const { id } = initialTransaction;
|
const transaction = primaryTransaction;
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const selectedAccount = useSelector(getSelectedAccount);
|
const selectedAccount = useSelector(getSelectedAccount);
|
||||||
const conversionRate = useSelector(getConversionRate);
|
const conversionRate = useSelector(getConversionRate);
|
||||||
|
const defaultNewGasPrice = addHexPrefix(
|
||||||
|
multiplyCurrencies(gasPrice, 1.1, {
|
||||||
|
toNumericBase: 'hex',
|
||||||
|
multiplicandBase: 16,
|
||||||
|
multiplierBase: 10,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
const cancelTransaction = useCallback(
|
const cancelTransaction = useCallback(
|
||||||
(event) => {
|
(event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
dispatch(setCustomGasLimit('0x5208'));
|
||||||
|
dispatch(setCustomGasPriceForRetry(defaultNewGasPrice));
|
||||||
|
const tx = {
|
||||||
|
...transaction,
|
||||||
|
txParams: {
|
||||||
|
...transaction.txParams,
|
||||||
|
gas: '0x5208',
|
||||||
|
value: '0x0',
|
||||||
|
},
|
||||||
|
};
|
||||||
return dispatch(
|
return dispatch(
|
||||||
|
showSidebar({
|
||||||
|
transitionName: 'sidebar-left',
|
||||||
|
type: 'customize-gas',
|
||||||
|
props: {
|
||||||
|
transaction: tx,
|
||||||
|
onSubmit: (newGasLimit, newGasPrice) => {
|
||||||
|
const userCustomizedGasTotal = getHexGasTotal({
|
||||||
|
gasPrice: newGasPrice,
|
||||||
|
gasLimit: newGasLimit,
|
||||||
|
});
|
||||||
|
dispatch(
|
||||||
showModal({
|
showModal({
|
||||||
name: 'CANCEL_TRANSACTION',
|
name: 'CANCEL_TRANSACTION',
|
||||||
transactionId: id,
|
newGasFee: userCustomizedGasTotal,
|
||||||
originalGasPrice: gasPrice,
|
transactionId: transaction.id,
|
||||||
|
defaultNewGasPrice: newGasPrice,
|
||||||
|
gasLimit: newGasLimit,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[dispatch, id, gasPrice],
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[dispatch, transaction, defaultNewGasPrice],
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasEnoughCancelGas =
|
const hasEnoughCancelGas =
|
||||||
|
@ -16,7 +16,7 @@ import { useMetricEvent } from './useMetricEvent';
|
|||||||
* @return {Function}
|
* @return {Function}
|
||||||
*/
|
*/
|
||||||
export function useRetryTransaction(transactionGroup) {
|
export function useRetryTransaction(transactionGroup) {
|
||||||
const { primaryTransaction, initialTransaction } = transactionGroup;
|
const { primaryTransaction } = transactionGroup;
|
||||||
// Signature requests do not have a txParams, but this hook is called indiscriminately
|
// Signature requests do not have a txParams, but this hook is called indiscriminately
|
||||||
const gasPrice = primaryTransaction.txParams?.gasPrice;
|
const gasPrice = primaryTransaction.txParams?.gasPrice;
|
||||||
const trackMetricsEvent = useMetricEvent({
|
const trackMetricsEvent = useMetricEvent({
|
||||||
@ -34,7 +34,7 @@ export function useRetryTransaction(transactionGroup) {
|
|||||||
|
|
||||||
trackMetricsEvent();
|
trackMetricsEvent();
|
||||||
await dispatch(fetchBasicGasEstimates);
|
await dispatch(fetchBasicGasEstimates);
|
||||||
const transaction = initialTransaction;
|
const transaction = primaryTransaction;
|
||||||
const increasedGasPrice = increaseLastGasPrice(gasPrice);
|
const increasedGasPrice = increaseLastGasPrice(gasPrice);
|
||||||
await dispatch(
|
await dispatch(
|
||||||
setCustomGasPriceForRetry(
|
setCustomGasPriceForRetry(
|
||||||
@ -50,7 +50,7 @@ export function useRetryTransaction(transactionGroup) {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[dispatch, trackMetricsEvent, initialTransaction, gasPrice],
|
[dispatch, trackMetricsEvent, gasPrice, primaryTransaction],
|
||||||
);
|
);
|
||||||
|
|
||||||
return retryTransaction;
|
return retryTransaction;
|
||||||
|
@ -1483,7 +1483,7 @@ export function clearPendingTokens() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createCancelTransaction(txId, customGasPrice) {
|
export function createCancelTransaction(txId, customGasPrice, customGasLimit) {
|
||||||
log.debug('background.cancelTransaction');
|
log.debug('background.cancelTransaction');
|
||||||
let newTxId;
|
let newTxId;
|
||||||
|
|
||||||
@ -1492,6 +1492,7 @@ export function createCancelTransaction(txId, customGasPrice) {
|
|||||||
background.createCancelTransaction(
|
background.createCancelTransaction(
|
||||||
txId,
|
txId,
|
||||||
customGasPrice,
|
customGasPrice,
|
||||||
|
customGasLimit,
|
||||||
(err, newState) => {
|
(err, newState) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
dispatch(displayWarning(err.message));
|
dispatch(displayWarning(err.message));
|
||||||
|
Loading…
Reference in New Issue
Block a user