Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ export type PreferencesControllerSetUseTransactionSimulationsAction = {
*
* @param options
* @param options.chainId - The chainId the advancedGasFees should be set on
* @param options.account - The account the advancedGasFees should be set for
* @param options.gasFeePreferences - The advancedGasFee options to set
*/
export type PreferencesControllerSetAdvancedGasFeeAction = {
Expand Down
54 changes: 51 additions & 3 deletions app/scripts/controllers/preferences-controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,25 +265,65 @@ describe('preferences controller', () => {

describe('setAdvancedGasFee', () => {
const { controller } = setupController({});
const account = '0xabc';

it('should default to an empty object', () => {
expect(controller.state.advancedGasFee).toStrictEqual({});
});

it('should set the setAdvancedGasFee property in state', () => {
controller.setAdvancedGasFee({
account: '0xABC',
chainId: CHAIN_IDS.GOERLI,
gasFeePreferences: {
userFeeLevel: 'custom',
maxBaseFee: '1.5',
priorityFee: '2',
},
});
expect(
controller.state.advancedGasFee[CHAIN_IDS.GOERLI].maxBaseFee,
controller.state.advancedGasFee[CHAIN_IDS.GOERLI][account].userFeeLevel,
).toStrictEqual('custom');
expect(
controller.state.advancedGasFee[CHAIN_IDS.GOERLI][account].maxBaseFee,
).toStrictEqual('1.5');
expect(
controller.state.advancedGasFee[CHAIN_IDS.GOERLI].priorityFee,
controller.state.advancedGasFee[CHAIN_IDS.GOERLI][account].priorityFee,
).toStrictEqual('2');
});

it('should clear advancedGasFee for one account without clearing other accounts', () => {
const { controller: accountScopedController } = setupController({});
accountScopedController.setAdvancedGasFee({
account: '0xabc',
chainId: CHAIN_IDS.GOERLI,
gasFeePreferences: {
userFeeLevel: 'custom',
maxBaseFee: '1.5',
priorityFee: '2',
},
});
accountScopedController.setAdvancedGasFee({
account: '0xdef',
chainId: CHAIN_IDS.GOERLI,
gasFeePreferences: {
userFeeLevel: 'high',
},
});

accountScopedController.setAdvancedGasFee({
account: '0xabc',
chainId: CHAIN_IDS.GOERLI,
});

expect(
accountScopedController.state.advancedGasFee[CHAIN_IDS.GOERLI],
).toStrictEqual({
'0xdef': {
userFeeLevel: 'high',
},
});
});
});

describe('setTheme', () => {
Expand Down Expand Up @@ -1226,7 +1266,15 @@ describe('preferences controller', () => {
currentLocale: 'ja',
theme: ThemeType.dark,
knownMethodData: { '0x12345678': 'transfer' },
advancedGasFee: { '0x1': { maxBaseFee: '100', priorityFee: '10' } },
advancedGasFee: {
'0x1': {
'0xabc': {
userFeeLevel: 'custom',
maxBaseFee: '100',
priorityFee: '10',
},
},
},
preferences: {
autoLockTimeLimit: undefined,
avatarType: 'jazzicon',
Expand Down
36 changes: 31 additions & 5 deletions app/scripts/controllers/preferences-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ import {
DEFAULT_AUTO_LOCK_TIME_LIMIT,
ThemeType,
} from '../../../shared/constants/preferences';
import type {
AdvancedGasFeePreferences,
AdvancedGasFeePreferencesByChain,
} from '../../../shared/constants/gas';
import { type DefaultAddressScope } from '../../../shared/constants/default-address';
import { DefiReferralPartner } from '../../../shared/constants/defi-referrals';
import { FALLBACK_LOCALE } from '../../../shared/lib/i18n';
Expand Down Expand Up @@ -96,7 +100,7 @@ export type PreferencesControllerState = Omit<
| 'tokenNetworkFilter'
> & {
addSnapAccountEnabled?: boolean;
advancedGasFee: Record<string, Record<string, string>>;
advancedGasFee: AdvancedGasFeePreferencesByChain;
currentLocale: string;
dismissSeedBackUpReminder: boolean;
enableMV3TimestampSave: boolean;
Expand Down Expand Up @@ -697,20 +701,42 @@ export class PreferencesController extends BaseController<
*
* @param options
* @param options.chainId - The chainId the advancedGasFees should be set on
* @param options.account - The account the advancedGasFees should be set for
* @param options.gasFeePreferences - The advancedGasFee options to set
*/
setAdvancedGasFee({
account,
chainId,
gasFeePreferences,
}: {
account: string;
chainId: string;
gasFeePreferences: Record<string, string>;
gasFeePreferences?: AdvancedGasFeePreferences;
}): void {
const { advancedGasFee } = this.state;
this.update((state) => {
const normalizedAccount = account.toLowerCase();
const chainPreferences = state.advancedGasFee[chainId] ?? {};

if (!gasFeePreferences) {
const {
[normalizedAccount]: _removedPreference,
...remainingChainPreferences
} = chainPreferences;

state.advancedGasFee = {
...state.advancedGasFee,
[chainId]: remainingChainPreferences,
};

return;
}

state.advancedGasFee = {
...advancedGasFee,
[chainId]: gasFeePreferences,
...state.advancedGasFee,
[chainId]: {
...chainPreferences,
[normalizedAccount]: gasFeePreferences,
},
};
});
}
Expand Down
18 changes: 18 additions & 0 deletions app/scripts/lib/transaction/metrics-builders/gas.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,29 @@ describe('gas builder', () => {
}),
);
expect(result.properties.gas_fee_selected).toBe('dapp_proposed');
expect(result.properties.gas_fee_presented).toBe('medium');
expect(result.sensitiveProperties.max_fee_per_gas).toBe(
hexWEIToDecGWEI('0x3b9aca00'),
);
expect(result.sensitiveProperties.max_priority_fee_per_gas).toBe(
hexWEIToDecGWEI('0x59682f00'),
);
});

it('normalizes dapp suggested presented gas fee metrics', async () => {
const result = await getGasMetricsProperties(
createBuilderRequest({
transactionMeta: {
...createBuilderRequest().transactionMeta,
userFeeLevel: 'custom',
defaultGasEstimates: {
estimateType: 'dappSuggested',
},
} as never,
}),
);

expect(result.properties.gas_fee_presented).toBe('dapp_proposed');
expect(result.properties.gas_fee_selected).toBe('custom');
});
});
13 changes: 9 additions & 4 deletions app/scripts/lib/transaction/metrics-builders/gas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ export const getGasMetricsProperties: TransactionMetricsBuilder = async ({
transactionMeta,
transactionMetricsRequest,
}) => {
const gasFeeSelected =
transactionMeta.userFeeLevel === 'dappSuggested'
? 'dapp_proposed'
: transactionMeta.userFeeLevel;
const gasFeeSelected = normalizeGasFeeLevel(transactionMeta.userFeeLevel);
const gasFeePresented = normalizeGasFeeLevel(
transactionMeta.defaultGasEstimates?.estimateType,
);

const gasParams: Record<string, unknown> = {};

Expand Down Expand Up @@ -70,6 +70,7 @@ export const getGasMetricsProperties: TransactionMetricsBuilder = async ({
}
return {
properties: {
gas_fee_presented: gasFeePresented,
gas_fee_selected: gasFeeSelected,
},
sensitiveProperties: {
Expand All @@ -85,3 +86,7 @@ export const getGasMetricsProperties: TransactionMetricsBuilder = async ({
},
};
};

function normalizeGasFeeLevel(userFeeLevel: string | undefined) {
return userFeeLevel === 'dappSuggested' ? 'dapp_proposed' : userFeeLevel;
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,19 +152,56 @@ describe('Transaction Controller Init', () => {
preferencesState: {
advancedGasFee: {
[CHAIN_ID_MOCK]: {
maxBaseFee: '0x1',
priorityFee: '0x2',
'0xabc': {
userFeeLevel: 'custom',
maxBaseFee: '0x1',
priorityFee: '0x2',
},
},
},
},
});

expect(getSavedGasFees?.(CHAIN_ID_MOCK)).toStrictEqual({
expect(
getSavedGasFees?.({
chainId: CHAIN_ID_MOCK,
txParams: {
from: '0xABC',
},
} as unknown as TransactionMeta),
).toStrictEqual({
level: 'custom',
maxBaseFee: '0x1',
priorityFee: '0x2',
});
});

it('does not retrieve saved gas fees for MetaMask Pay transactions', () => {
const getSavedGasFees = testConstructorOption('getSavedGasFees', {
preferencesState: {
advancedGasFee: {
[CHAIN_ID_MOCK]: {
'0xabc': {
userFeeLevel: 'custom',
maxBaseFee: '0x1',
priorityFee: '0x2',
},
},
},
},
});

expect(
getSavedGasFees?.({
chainId: CHAIN_ID_MOCK,
metamaskPay: {},
txParams: {
from: '0xabc',
},
} as unknown as TransactionMeta),
).toBeUndefined();
});

describe('determines incoming transactions is disabled', () => {
it('when useExternalServices is enabled in preferences and onboarding complete', () => {
const incomingTransactionsIsEnabled = testConstructorOption(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { PRODUCT_TYPES } from '@metamask/subscription-controller';
import { ORIGIN_METAMASK } from '@metamask/controller-utils';
import {
GasFeeEstimateLevel,
SavedGasFees,
TransactionController,
TransactionControllerMessenger,
TransactionMeta,
TransactionType,
UserFeeLevel,
} from '@metamask/transaction-controller';
import { Hex } from '@metamask/utils';
import { trace } from '../../../../shared/lib/trace';
Expand Down Expand Up @@ -203,10 +205,47 @@ function addTransactionControllerListeners(

function getSavedGasFees(
{ messenger }: { messenger: TransactionControllerInitMessenger },
chainId: string,
transactionMeta: TransactionMeta,
): SavedGasFees | undefined {
const account = transactionMeta.txParams.from?.toLowerCase();

if (!account || transactionMeta.metamaskPay) {
return undefined;
}
Comment thread
cursor[bot] marked this conversation as resolved.

const { advancedGasFee } = messenger.call('PreferencesController:getState');
return advancedGasFee[chainId] as unknown as SavedGasFees | undefined;
const savedGasFeePreference =
advancedGasFee[transactionMeta.chainId]?.[account];

if (!savedGasFeePreference) {
return undefined;
}

const savedGasFeeLevel = getSavedGasFeeLevel(
savedGasFeePreference.userFeeLevel,
);

if (!savedGasFeeLevel) {
return undefined;
}

const savedGasFees: SavedGasFees = {
level: savedGasFeeLevel,
};

if (savedGasFeePreference.maxBaseFee) {
savedGasFees.maxBaseFee = savedGasFeePreference.maxBaseFee;
}

if (savedGasFeePreference.priorityFee) {
savedGasFees.priorityFee = savedGasFeePreference.priorityFee;
}

if (savedGasFeePreference.gasPrice) {
savedGasFees.gasPrice = savedGasFeePreference.gasPrice;
}

return savedGasFees;
}

async function getSimulationConfig(
Expand Down Expand Up @@ -289,3 +328,16 @@ function isAutomaticGasFeeUpdateEnabled(transaction: TransactionMeta) {
DISABLED_AUTOMATIC_GAS_FEE_UPDATE_TYPES,
);
}

function getSavedGasFeeLevel(
userFeeLevel: string,
): SavedGasFees['level'] | undefined {
const savedGasFeeLevels = [
GasFeeEstimateLevel.Low,
GasFeeEstimateLevel.Medium,
GasFeeEstimateLevel.High,
UserFeeLevel.CUSTOM,
] as const;

return savedGasFeeLevels.find((level) => level === userFeeLevel);
}
Loading
Loading