Skip to content

Commit

Permalink
feat: support updated Linea gas fee estimation (#8581)
Browse files Browse the repository at this point in the history
When creating transactions on a Linea network, use the updated gas fee
estimates provided by the `linea_estimateGas` RPC method.
Create selectors for the `GasFeeController`, `TransactionController`,
and for general transaction confirmation.
Use these new selectors in place of any direct state references to
ensure the transaction specific estimates are used whenever they are
available.
Resolve a Redux / selector limitation of `BaseControllerV1`
controllers.
Fix saving custom gas fee values in the send flow.
Reject approval request when closing send confirm component.
  • Loading branch information
matthewwalsh0 authored Feb 26, 2024
1 parent 4869690 commit 9e4c51d
Show file tree
Hide file tree
Showing 23 changed files with 1,260 additions and 154 deletions.
12 changes: 12 additions & 0 deletions app/actions/transaction/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,18 @@ export function setTransactionObject(transaction) {
};
}

/**
* Sets the current transaction ID only.
*
* @param {object} transactionId - Id of the current transaction.
*/
export function setTransactionId(transactionId) {
return {
type: 'SET_TRANSACTION_ID',
transactionId,
};
}

/**
* Enable selectable tokens (ERC20 and Ether) to send in a transaction
*
Expand Down
4 changes: 2 additions & 2 deletions app/components/UI/Swaps/QuotesView.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ import {
import { useMetrics } from '../../../components/hooks/useMetrics';
import { addTransaction } from '../../../util/transaction-controller';
import trackErrorAsAnalytics from '../../../util/metrics/TrackError/trackErrorAsAnalytics';
import { selectGasFeeEstimates } from '../../../selectors/confirmTransaction';

const POLLING_INTERVAL = 30000;
const SLIPPAGE_BUCKETS = {
Expand Down Expand Up @@ -2325,8 +2326,7 @@ const mapStateToProps = (state) => ({
state.engine.backgroundState.SwapsController.quoteRefreshSeconds,
gasEstimateType:
state.engine.backgroundState.GasFeeController.gasEstimateType,
gasFeeEstimates:
state.engine.backgroundState.GasFeeController.gasFeeEstimates,
gasFeeEstimates: selectGasFeeEstimates(state),
usedGasEstimate: state.engine.backgroundState.SwapsController.usedGasEstimate,
usedCustomGas: state.engine.backgroundState.SwapsController.usedCustomGas,
primaryCurrency: state.settings.primaryCurrency,
Expand Down
4 changes: 2 additions & 2 deletions app/components/UI/Transactions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import {
speedUpTransaction,
updateIncomingTransactions,
} from '../../../util/transaction-controller';
import { selectGasFeeEstimates } from '../../../selectors/confirmTransaction';

const createStyles = (colors, typography) =>
StyleSheet.create({
Expand Down Expand Up @@ -867,8 +868,7 @@ const mapStateToProps = (state) => ({
selectedAddress: selectSelectedAddress(state),
networkConfigurations: selectNetworkConfigurations(state),
providerConfig: selectProviderConfig(state),
gasFeeEstimates:
state.engine.backgroundState.GasFeeController.gasFeeEstimates,
gasFeeEstimates: selectGasFeeEstimates(state),
primaryCurrency: state.settings.primaryCurrency,
tokens: selectTokensByAddress(state),
gasEstimateType:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ import {
import { selectAccounts } from '../../../../../../selectors/accountTrackerController';
import { selectContractBalances } from '../../../../../../selectors/tokenBalancesController';
import { selectSelectedAddress } from '../../../../../../selectors/preferencesController';
import { selectGasFeeEstimates } from '../../../../../../selectors/confirmTransaction';
import { selectGasFeeControllerEstimateType } from '../../../../../../selectors/gasFeeController';

const EDIT = 'edit';
const REVIEW = 'review';
Expand Down Expand Up @@ -970,10 +972,8 @@ const mapStateToProps = (state) => ({
ticker: selectTicker(state),
transaction: getNormalizedTxState(state),
activeTabUrl: getActiveTabUrl(state),
gasFeeEstimates:
state.engine.backgroundState.GasFeeController.gasFeeEstimates,
gasEstimateType:
state.engine.backgroundState.GasFeeController.gasEstimateType,
gasFeeEstimates: selectGasFeeEstimates(state),
gasEstimateType: selectGasFeeControllerEstimateType(state),
conversionRate: selectConversionRate(state),
currentCurrency: selectCurrentCurrency(state),
nativeCurrency: selectNativeCurrency(state),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ import { getLedgerKeyring } from '../../../../../core/Ledger/Ledger';
import ExtendedKeyringTypes from '../../../../../constants/keyringTypes';
import { updateTransaction } from '../../../../../util/transaction-controller';
import { withMetricsAwareness } from '../../../../../components/hooks/useMetrics';
import { selectGasFeeEstimates } from '../../../../../selectors/confirmTransaction';
import { selectGasFeeControllerEstimateType } from '../../../../../selectors/gasFeeController';

const EDIT = 'edit';
const REVIEW = 'review';
Expand Down Expand Up @@ -893,10 +895,8 @@ const mapStateToProps = (state) => ({
accountsLength: selectAccountsLength(state),
primaryCurrency: state.settings.primaryCurrency,
chainId: selectChainId(state),
gasFeeEstimates:
state.engine.backgroundState.GasFeeController.gasFeeEstimates,
gasEstimateType:
state.engine.backgroundState.GasFeeController.gasEstimateType,
gasFeeEstimates: selectGasFeeEstimates(state),
gasEstimateType: selectGasFeeControllerEstimateType(state),
conversionRate: selectConversionRate(state),
currentCurrency: selectCurrentCurrency(state),
nativeCurrency: selectNativeCurrency(state),
Expand Down
42 changes: 24 additions & 18 deletions app/components/Views/confirmations/SendFlow/Amount/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ import { regex } from '../../../../../util/regex';
import { AmountViewSelectorsIDs } from '../../../../../../e2e/selectors/SendFlow/AmountView.selectors';
import { isNetworkRampNativeTokenSupported } from '../../../../../components/UI/Ramp/utils';
import { withMetricsAwareness } from '../../../../../components/hooks/useMetrics';
import { selectGasFeeEstimates } from '../../../../../selectors/confirmTransaction';
import { selectGasFeeControllerEstimateType } from '../../../../../selectors/gasFeeController';

const KEYBOARD_OFFSET = Device.isSmallDevice() ? 80 : 120;

Expand Down Expand Up @@ -480,6 +482,14 @@ class Amount extends PureComponent {
* Metrics injected by withMetricsAwareness HOC
*/
metrics: PropTypes.object,
/**
* Gas fee estimates for the transaction.
*/
gasFeeEstimates: PropTypes.object,
/**
* Type of gas fee estimate provided by the gas fee controller.
*/
gasEstimateType: PropTypes.string,
};

state = {
Expand Down Expand Up @@ -520,6 +530,8 @@ class Amount extends PureComponent {
providerType,
selectedAsset,
isPaymentRequest,
gasEstimateType,
gasFeeEstimates,
} = this.props;
// For analytics
this.updateNavBar();
Expand All @@ -534,23 +546,19 @@ class Amount extends PureComponent {
this.onInputChange(readableValue);
!selectedAsset.tokenId && this.handleSelectedAssetBalance(selectedAsset);

const { GasFeeController } = Engine.context;
const [gasEstimates, gas] = await Promise.all([
GasFeeController.fetchGasFeeEstimates({ shouldUpdateState: false }),
this.estimateGasLimit(),
]);
const [gas] = await Promise.all([this.estimateGasLimit()]);

if (gasEstimates.gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET) {
const gasFeeEstimates =
gasEstimates.gasFeeEstimates[AppConstants.GAS_OPTIONS.MEDIUM];
if (gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET) {
const mediumGasFeeEstimates =
gasFeeEstimates[AppConstants.GAS_OPTIONS.MEDIUM];
const estimatedBaseFeeHex = decGWEIToHexWEI(
gasEstimates.gasFeeEstimates.estimatedBaseFee,
gasFeeEstimates.estimatedBaseFee,
);
const suggestedMaxPriorityFeePerGasHex = decGWEIToHexWEI(
gasFeeEstimates.suggestedMaxPriorityFeePerGas,
mediumGasFeeEstimates.suggestedMaxPriorityFeePerGas,
);
const suggestedMaxFeePerGasHex = decGWEIToHexWEI(
gasFeeEstimates.suggestedMaxFeePerGas,
mediumGasFeeEstimates.suggestedMaxFeePerGas,
);
const gasLimitHex = BNToHex(gas);
const gasHexes = calculateEIP1559GasFeeHexes({
Expand All @@ -562,17 +570,13 @@ class Amount extends PureComponent {
this.setState({
estimatedTotalGas: hexToBN(gasHexes.gasFeeMaxHex),
});
} else if (gasEstimates.gasEstimateType === GAS_ESTIMATE_TYPES.LEGACY) {
} else if (gasEstimateType === GAS_ESTIMATE_TYPES.LEGACY) {
const gasPrice = hexToBN(
decGWEIToHexWEI(
gasEstimates.gasFeeEstimates[AppConstants.GAS_OPTIONS.MEDIUM],
),
decGWEIToHexWEI(gasFeeEstimates[AppConstants.GAS_OPTIONS.MEDIUM]),
);
this.setState({ estimatedTotalGas: gas.mul(gasPrice) });
} else {
const gasPrice = hexToBN(
decGWEIToHexWEI(gasEstimates.gasFeeEstimates.gasPrice),
);
const gasPrice = hexToBN(decGWEIToHexWEI(gasFeeEstimates.gasPrice));
this.setState({ estimatedTotalGas: gas.mul(gasPrice) });
}

Expand Down Expand Up @@ -1514,6 +1518,8 @@ const mapStateToProps = (state, ownProps) => ({
collectibleContracts: collectibleContractsSelector(state),
conversionRate: selectConversionRate(state),
currentCurrency: selectCurrentCurrency(state),
gasEstimateType: selectGasFeeControllerEstimateType(state),
gasFeeEstimates: selectGasFeeEstimates(state),
providerType: selectProviderType(state),
primaryCurrency: state.settings.primaryCurrency,
selectedAddress: selectSelectedAddress(state),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import EditGasFee1559 from '../../../../components/EditGasFee1559Update';
import EditGasFeeLegacy from '../../../../components/EditGasFeeLegacyUpdate';
import createStyles from './CustomGasModal.styles';
import { CustomGasModalProps } from './CustomGasModal.types';
import { selectGasFeeEstimates } from '../../../../../../../selectors/confirmTransaction';

const CustomGasModal = ({
gasSelected,
Expand All @@ -27,9 +28,8 @@ const CustomGasModal = ({
const { colors } = useAppThemeFromContext();
const styles = createStyles();
const transaction = useSelector((state: any) => state.transaction);
const gasFeeEstimate = useSelector(
(state: any) =>
state.engine.backgroundState.GasFeeController.gasFeeEstimates,
const gasFeeEstimate = useSelector((state: any) =>
selectGasFeeEstimates(state),
);
const primaryCurrency = useSelector(
(state: any) => state.settings.primaryCurrency,
Expand Down
Loading

0 comments on commit 9e4c51d

Please sign in to comment.