mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-11 20:27:12 +01:00
904dad256f
* Connect ledger via webhid if that option is available * Explicitly setting preference for webhid * Use ledgerTransportType enum instead of booleans for ledger live and webhid preferences * Use single setLEdgerTransport preference methods and property * Temp * Lint fix * Unit test fix * Remove async keyword from setLedgerTransportPreference function definition in preferences controller * Fix ledgelive setting toggle logic * Migrate useLedgerLive preference property to ledgerTransportType * Use shared constants for ledger transport type enums * Use constant for ledger usb vendor id * Use correct property to check if ledgerLive preference is set when deciding whether to ask for webhid connection * Update eth-ledger-bridge-keyring to v0.9.0 * Only show ledger live transaction helper messages if using ledger live * Only show ledger live part of tutorial if ledger live setting is on * Fix ledger related prop type errors * Explicitly use u2f enum instead of empty string as a transport type; default transport type to webhid if available; use constants for u2f and webhid * Cleanup * Wrap ledger webhid device request in try/catch * Clean up * Lint fix * Ensure user can easily connect their ledger wallet when they need to. * Fix locales * Fix/improve locales changes * Remove unused isFirefox property from confirm-transaction-base.container.js * Disable transaction and message signing confirmation if ledger webhid requires connection * Ensure translation keys for ledger connection options in settings dropdown can be properly detected by verify-locales * Drop .component from ledger-instruction-field file name * Move renderLedgerLiveStep to module scope * Remove ledgerLive from function and message names in ledger-instruction-field * Wrap ledger connection logic in ledger-instruction-field in try catch * Clean up signature-request.component.js * Check whether the signing address, and not the selected address, is a ledger account in singature-request.container * Ensure ledger instructions and webhid connection button are shown on signature-request-original signatures * Improve webhid selection handling in select-ledger-transport-type onChange handler * Move metamask redux focused ledger selectors to metamask duck * Lint fix * Use async await in checkWebHidStatusRef.current * Remove unnecessary use of ref in ledger-instruction-field.js * Lint fix * Remove unnecessary try/catch in ledger-instruction-field.js * Check if from address, not selected address, is from a ledger account in confirm-approve * Move findKeyringForAddress to metamask duck * Fix typo in function name * Ensure isEqualCaseInsensitive handles possible differences in address casing * Fix Learn More link size in advanced settings tab * Update app/scripts/migrations/066.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Update ui/pages/settings/advanced-tab/advanced-tab.component.test.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Add jsdoc comments for new selectors * Use jest.spyOn for mocking navigator in ledger webhid migration tests * Use LEDGER_TRANSPORT_TYPES values to set proptype of ledgerTransportType * Use LEDGER_TRANSPORT_TYPES values to set proptype of ledgerTransportType * Fix font size of link in ledger connection description in advanced settings * Fix return type in setLedgerTransportPreference comment * Clean up connectHardware code for webhid connection in actions.js * Update app/scripts/migrations/066.test.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Update ui/ducks/metamask/metamask.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Add migration test for when useLedgerLive is true in a browser that supports webhid * Lint fix * Fix inline-link size Co-authored-by: Mark Stacey <markjstacey@gmail.com>
295 lines
8.7 KiB
JavaScript
295 lines
8.7 KiB
JavaScript
import { connect } from 'react-redux';
|
|
import { compose } from 'redux';
|
|
import { withRouter } from 'react-router-dom';
|
|
import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck';
|
|
|
|
import {
|
|
updateCustomNonce,
|
|
cancelTx,
|
|
cancelTxs,
|
|
updateAndApproveTx,
|
|
showModal,
|
|
getNextNonce,
|
|
tryReverseResolveAddress,
|
|
setDefaultHomeActiveTabName,
|
|
} from '../../store/actions';
|
|
import { isBalanceSufficient, calcGasTotal } from '../send/send.utils';
|
|
import { shortenAddress, valuesFor } from '../../helpers/utils/util';
|
|
import {
|
|
getAdvancedInlineGasShown,
|
|
getCustomNonceValue,
|
|
getIsMainnet,
|
|
getKnownMethodData,
|
|
getMetaMaskAccounts,
|
|
getUseNonceField,
|
|
transactionFeeSelector,
|
|
getNoGasPriceFetched,
|
|
getIsEthGasPriceFetched,
|
|
getShouldShowFiat,
|
|
checkNetworkAndAccountSupports1559,
|
|
getPreferences,
|
|
doesAddressRequireLedgerHidConnection,
|
|
getUseTokenDetection,
|
|
getTokenList,
|
|
} from '../../selectors';
|
|
import { getMostRecentOverviewPage } from '../../ducks/history/history';
|
|
import {
|
|
isAddressLedger,
|
|
updateTransactionGasFees,
|
|
getIsGasEstimatesLoading,
|
|
getNativeCurrency,
|
|
} from '../../ducks/metamask/metamask';
|
|
|
|
import {
|
|
transactionMatchesNetwork,
|
|
txParamsAreDappSuggested,
|
|
} from '../../../shared/modules/transaction.utils';
|
|
import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
|
|
|
|
import { getGasLoadingAnimationIsShowing } from '../../ducks/app/app';
|
|
import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
|
|
import ConfirmTransactionBase from './confirm-transaction-base.component';
|
|
|
|
let customNonceValue = '';
|
|
const customNonceMerge = (txData) =>
|
|
customNonceValue
|
|
? {
|
|
...txData,
|
|
customNonceValue,
|
|
}
|
|
: txData;
|
|
|
|
const mapStateToProps = (state, ownProps) => {
|
|
const {
|
|
toAddress: propsToAddress,
|
|
customTxParamsData,
|
|
match: { params = {} },
|
|
} = ownProps;
|
|
const { id: paramsTransactionId } = params;
|
|
const isMainnet = getIsMainnet(state);
|
|
|
|
const isGasEstimatesLoading = getIsGasEstimatesLoading(state);
|
|
const gasLoadingAnimationIsShowing = getGasLoadingAnimationIsShowing(state);
|
|
|
|
const { confirmTransaction, metamask } = state;
|
|
const {
|
|
ensResolutionsByAddress,
|
|
conversionRate,
|
|
identities,
|
|
addressBook,
|
|
network,
|
|
unapprovedTxs,
|
|
nextNonce,
|
|
provider: { chainId },
|
|
} = metamask;
|
|
const { tokenData, txData, tokenProps, nonce } = confirmTransaction;
|
|
const { txParams = {}, id: transactionId, type } = txData;
|
|
const transaction =
|
|
Object.values(unapprovedTxs).find(
|
|
({ id }) => id === (transactionId || Number(paramsTransactionId)),
|
|
) || {};
|
|
const {
|
|
from: fromAddress,
|
|
to: txParamsToAddress,
|
|
gasPrice,
|
|
gas: gasLimit,
|
|
value: amount,
|
|
data,
|
|
} = (transaction && transaction.txParams) || txParams;
|
|
const accounts = getMetaMaskAccounts(state);
|
|
|
|
const { balance } = accounts[fromAddress];
|
|
const { name: fromName } = identities[fromAddress];
|
|
const toAddress = propsToAddress || txParamsToAddress;
|
|
|
|
const tokenList = getTokenList(state);
|
|
const useTokenDetection = getUseTokenDetection(state);
|
|
const casedTokenList = useTokenDetection
|
|
? tokenList
|
|
: Object.keys(tokenList).reduce((acc, base) => {
|
|
return {
|
|
...acc,
|
|
[base.toLowerCase()]: tokenList[base],
|
|
};
|
|
}, {});
|
|
const toName =
|
|
identities[toAddress]?.name ||
|
|
casedTokenList[toAddress]?.name ||
|
|
shortenAddress(toChecksumHexAddress(toAddress));
|
|
|
|
const checksummedAddress = toChecksumHexAddress(toAddress);
|
|
const addressBookObject = addressBook[checksummedAddress];
|
|
const toEns = ensResolutionsByAddress[checksummedAddress] || '';
|
|
const toNickname = addressBookObject ? addressBookObject.name : '';
|
|
const transactionStatus = transaction ? transaction.status : '';
|
|
const supportsEIP1559 =
|
|
checkNetworkAndAccountSupports1559(state) && !isLegacyTransaction(txParams);
|
|
|
|
const {
|
|
hexTransactionAmount,
|
|
hexMinimumTransactionFee,
|
|
hexMaximumTransactionFee,
|
|
hexTransactionTotal,
|
|
gasEstimationObject,
|
|
} = transactionFeeSelector(state, transaction);
|
|
|
|
if (transaction && transaction.simulationFails) {
|
|
txData.simulationFails = transaction.simulationFails;
|
|
}
|
|
|
|
const currentNetworkUnapprovedTxs = Object.keys(unapprovedTxs)
|
|
.filter((key) =>
|
|
transactionMatchesNetwork(unapprovedTxs[key], chainId, network),
|
|
)
|
|
.reduce((acc, key) => ({ ...acc, [key]: unapprovedTxs[key] }), {});
|
|
const unapprovedTxCount = valuesFor(currentNetworkUnapprovedTxs).length;
|
|
|
|
const insufficientBalance = !isBalanceSufficient({
|
|
amount,
|
|
gasTotal: calcGasTotal(gasLimit, gasPrice),
|
|
balance,
|
|
conversionRate,
|
|
});
|
|
|
|
const methodData = getKnownMethodData(state, data) || {};
|
|
|
|
let fullTxData = { ...txData, ...transaction };
|
|
if (customTxParamsData) {
|
|
fullTxData = {
|
|
...fullTxData,
|
|
txParams: {
|
|
...fullTxData.txParams,
|
|
data: customTxParamsData,
|
|
},
|
|
};
|
|
}
|
|
customNonceValue = getCustomNonceValue(state);
|
|
const isEthGasPrice = getIsEthGasPriceFetched(state);
|
|
const noGasPrice = !supportsEIP1559 && getNoGasPriceFetched(state);
|
|
const { useNativeCurrencyAsPrimaryCurrency } = getPreferences(state);
|
|
const gasFeeIsCustom =
|
|
fullTxData.userFeeLevel === 'custom' ||
|
|
txParamsAreDappSuggested(fullTxData);
|
|
const fromAddressIsLedger = isAddressLedger(state, fromAddress);
|
|
const nativeCurrency = getNativeCurrency(state);
|
|
|
|
const hardwareWalletRequiresConnection = doesAddressRequireLedgerHidConnection(
|
|
state,
|
|
fromAddress,
|
|
);
|
|
|
|
return {
|
|
balance,
|
|
fromAddress,
|
|
fromName,
|
|
toAddress,
|
|
toEns,
|
|
toName,
|
|
toNickname,
|
|
hexTransactionAmount,
|
|
hexMinimumTransactionFee,
|
|
hexMaximumTransactionFee,
|
|
hexTransactionTotal,
|
|
txData: fullTxData,
|
|
tokenData,
|
|
methodData,
|
|
tokenProps,
|
|
conversionRate,
|
|
transactionStatus,
|
|
nonce,
|
|
unapprovedTxs,
|
|
unapprovedTxCount,
|
|
currentNetworkUnapprovedTxs,
|
|
customGas: {
|
|
gasLimit,
|
|
gasPrice,
|
|
},
|
|
advancedInlineGasShown: getAdvancedInlineGasShown(state),
|
|
useNonceField: getUseNonceField(state),
|
|
customNonceValue,
|
|
insufficientBalance,
|
|
hideSubtitle: !getShouldShowFiat(state),
|
|
hideFiatConversion: !getShouldShowFiat(state),
|
|
type,
|
|
nextNonce,
|
|
mostRecentOverviewPage: getMostRecentOverviewPage(state),
|
|
isMainnet,
|
|
isEthGasPrice,
|
|
noGasPrice,
|
|
supportsEIP1559,
|
|
gasIsLoading: isGasEstimatesLoading || gasLoadingAnimationIsShowing,
|
|
useNativeCurrencyAsPrimaryCurrency,
|
|
maxFeePerGas: gasEstimationObject.maxFeePerGas,
|
|
maxPriorityFeePerGas: gasEstimationObject.maxPriorityFeePerGas,
|
|
baseFeePerGas: gasEstimationObject.baseFeePerGas,
|
|
gasFeeIsCustom,
|
|
showLedgerSteps: fromAddressIsLedger,
|
|
nativeCurrency,
|
|
hardwareWalletRequiresConnection,
|
|
};
|
|
};
|
|
|
|
export const mapDispatchToProps = (dispatch) => {
|
|
return {
|
|
tryReverseResolveAddress: (address) => {
|
|
return dispatch(tryReverseResolveAddress(address));
|
|
},
|
|
updateCustomNonce: (value) => {
|
|
customNonceValue = value;
|
|
dispatch(updateCustomNonce(value));
|
|
},
|
|
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
|
|
showTransactionConfirmedModal: ({ onSubmit }) => {
|
|
return dispatch(showModal({ name: 'TRANSACTION_CONFIRMED', onSubmit }));
|
|
},
|
|
showRejectTransactionsConfirmationModal: ({
|
|
onSubmit,
|
|
unapprovedTxCount,
|
|
}) => {
|
|
return dispatch(
|
|
showModal({ name: 'REJECT_TRANSACTIONS', onSubmit, unapprovedTxCount }),
|
|
);
|
|
},
|
|
cancelTransaction: ({ id }) => dispatch(cancelTx({ id })),
|
|
cancelAllTransactions: (txList) => dispatch(cancelTxs(txList)),
|
|
sendTransaction: (txData) =>
|
|
dispatch(updateAndApproveTx(customNonceMerge(txData))),
|
|
getNextNonce: () => dispatch(getNextNonce()),
|
|
setDefaultHomeActiveTabName: (tabName) =>
|
|
dispatch(setDefaultHomeActiveTabName(tabName)),
|
|
updateTransactionGasFees: (gasFees) => {
|
|
dispatch(updateTransactionGasFees({ ...gasFees, expectHexWei: true }));
|
|
},
|
|
};
|
|
};
|
|
|
|
const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
|
const { txData, unapprovedTxs } = stateProps;
|
|
|
|
const {
|
|
cancelAllTransactions: dispatchCancelAllTransactions,
|
|
updateTransactionGasFees: dispatchUpdateTransactionGasFees,
|
|
...otherDispatchProps
|
|
} = dispatchProps;
|
|
|
|
return {
|
|
...stateProps,
|
|
...otherDispatchProps,
|
|
...ownProps,
|
|
cancelAllTransactions: () =>
|
|
dispatchCancelAllTransactions(valuesFor(unapprovedTxs)),
|
|
updateGasAndCalculate: ({ gasLimit, gasPrice }) => {
|
|
dispatchUpdateTransactionGasFees({
|
|
gasLimit,
|
|
gasPrice,
|
|
transaction: txData,
|
|
});
|
|
},
|
|
};
|
|
};
|
|
|
|
export default compose(
|
|
withRouter,
|
|
connect(mapStateToProps, mapDispatchToProps, mergeProps),
|
|
)(ConfirmTransactionBase);
|