Skip to content

Commit 2e7f7a6

Browse files
fix: restore saved custom gas settings
1 parent c531c94 commit 2e7f7a6

4 files changed

Lines changed: 136 additions & 41 deletions

File tree

app/components/Views/confirmations/hooks/gas/usePersistGasFeePreference.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ describe('usePersistGasFeePreference', () => {
3434
chainId: '0x1',
3535
gasFeePreferences: {
3636
userFeeLevel: 'custom',
37-
maxBaseFee: '0x1',
38-
priorityFee: '0x2',
37+
maxBaseFee: '0.000000001',
38+
priorityFee: '0.000000002',
3939
},
4040
});
4141
});

app/components/Views/confirmations/hooks/gas/usePersistGasFeePreference.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { Hex } from '@metamask/utils';
44

55
import Engine from '../../../../../core/Engine';
66
import type { AdvancedGasFeePreferences } from '../../../../../core/Engine/controllers/preferences-controller-types';
7+
import { hexWEIToDecGWEI } from '../../../../../util/conversions';
78

89
export function usePersistGasFeePreference() {
910
return useCallback(
@@ -21,9 +22,30 @@ export function usePersistGasFeePreference() {
2122
Engine.context.PreferencesController.setAdvancedGasFee({
2223
account,
2324
chainId,
24-
gasFeePreferences,
25+
gasFeePreferences: normalizeGasFeePreferences(gasFeePreferences),
2526
});
2627
},
2728
[],
2829
);
2930
}
31+
32+
function normalizeGasFeePreferences(
33+
gasFeePreferences: AdvancedGasFeePreferences,
34+
): AdvancedGasFeePreferences {
35+
return {
36+
...gasFeePreferences,
37+
...(gasFeePreferences.maxBaseFee && {
38+
maxBaseFee: hexWEIToDecGWEI(
39+
gasFeePreferences.maxBaseFee as Hex,
40+
).toString(),
41+
}),
42+
...(gasFeePreferences.priorityFee && {
43+
priorityFee: hexWEIToDecGWEI(
44+
gasFeePreferences.priorityFee as Hex,
45+
).toString(),
46+
}),
47+
...(gasFeePreferences.gasPrice && {
48+
gasPrice: hexWEIToDecGWEI(gasFeePreferences.gasPrice as Hex).toString(),
49+
}),
50+
};
51+
}

app/core/Engine/controllers/transaction-controller/transaction-controller-init.test.ts

Lines changed: 75 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
TransactionType,
1010
UserFeeLevel,
1111
type PublishBatchHookTransaction,
12+
type SavedGasFees,
1213
} from '@metamask/transaction-controller';
1314

1415
import { ORIGIN_METAMASK, toHex } from '@metamask/controller-utils';
@@ -190,6 +191,15 @@ function buildInitRequestMock(
190191
return requestMock;
191192
}
192193

194+
type SavedGasFeesWithLevel = SavedGasFees & {
195+
gasPrice?: string;
196+
level?: UserFeeLevel | GasFeeEstimateLevel;
197+
};
198+
199+
type GetSavedGasFeesOption = (
200+
chainIdOrTransactionMeta: Hex | TransactionMeta,
201+
) => SavedGasFeesWithLevel | undefined;
202+
193203
describe('Transaction Controller Init', () => {
194204
const transactionControllerClassMock = jest.mocked(TransactionController);
195205
const selectShouldUseSmartTransactionMock = jest.mocked(
@@ -336,23 +346,43 @@ describe('Transaction Controller Init', () => {
336346
},
337347
selectedAccountAddress: account,
338348
},
339-
);
349+
) as unknown as GetSavedGasFeesOption | undefined;
340350
}
341351

342-
it('returns saved custom gas fees for the selected account on the chain', () => {
352+
it('returns saved custom gas fees for the transaction account on the chain', () => {
343353
const optionFn = getSavedGasFeesOption({
344354
userFeeLevel: UserFeeLevel.CUSTOM,
345-
maxBaseFee: '0x1',
346-
priorityFee: '0x2',
355+
maxBaseFee: '1',
356+
priorityFee: '2',
347357
});
348358

349-
expect(optionFn?.('0x1')).toEqual({
350-
maxBaseFee: '0x1',
351-
priorityFee: '0x2',
359+
expect(optionFn?.(MOCK_TRANSACTION_META)).toEqual({
360+
level: UserFeeLevel.CUSTOM,
361+
maxBaseFee: '1',
362+
priorityFee: '2',
363+
});
364+
});
365+
366+
it('normalizes the transaction account before lookup', () => {
367+
const optionFn = getSavedGasFeesOption({
368+
userFeeLevel: UserFeeLevel.CUSTOM,
369+
maxBaseFee: '1',
370+
priorityFee: '2',
371+
});
372+
373+
expect(
374+
optionFn?.({
375+
...MOCK_TRANSACTION_META,
376+
txParams: { from: account.toUpperCase() },
377+
} as TransactionMeta),
378+
).toEqual({
379+
level: UserFeeLevel.CUSTOM,
380+
maxBaseFee: '1',
381+
priorityFee: '2',
352382
});
353383
});
354384

355-
it('normalizes the selected account before lookup', () => {
385+
it('uses the transaction account instead of the selected account', () => {
356386
const optionFn = testConstructorOption(
357387
'getSavedGasFees',
358388
{},
@@ -363,49 +393,71 @@ describe('Transaction Controller Init', () => {
363393
useTransactionSimulations: true,
364394
advancedGasFee: {
365395
'0x1': {
366-
[account]: {
396+
'0x456': {
367397
userFeeLevel: UserFeeLevel.CUSTOM,
368-
maxBaseFee: '0x1',
369-
priorityFee: '0x2',
398+
maxBaseFee: '1',
399+
priorityFee: '2',
370400
},
371401
},
372402
},
373403
},
374-
selectedAccountAddress: account.toUpperCase(),
404+
selectedAccountAddress: account,
375405
},
376-
);
406+
) as unknown as GetSavedGasFeesOption | undefined;
377407

378-
expect(optionFn?.('0x1')).toEqual({
379-
maxBaseFee: '0x1',
380-
priorityFee: '0x2',
408+
expect(
409+
optionFn?.({
410+
...MOCK_TRANSACTION_META,
411+
txParams: { from: '0x456' },
412+
} as TransactionMeta),
413+
).toEqual({
414+
level: UserFeeLevel.CUSTOM,
415+
maxBaseFee: '1',
416+
priorityFee: '2',
381417
});
382418
});
383419

384-
it('returns undefined for estimate-level saved preferences', () => {
420+
it('returns saved estimate-level preferences', () => {
385421
const optionFn = getSavedGasFeesOption({
386422
userFeeLevel: GasFeeEstimateLevel.Low,
387423
});
388424

389-
expect(optionFn?.('0x1')).toBeUndefined();
425+
expect(optionFn?.(MOCK_TRANSACTION_META)).toEqual({
426+
level: GasFeeEstimateLevel.Low,
427+
});
428+
});
429+
430+
it('returns saved legacy custom gas price preferences', () => {
431+
const optionFn = getSavedGasFeesOption({
432+
userFeeLevel: UserFeeLevel.CUSTOM,
433+
gasPrice: '10',
434+
});
435+
436+
expect(optionFn?.(MOCK_TRANSACTION_META)).toEqual({
437+
gasPrice: '10',
438+
level: UserFeeLevel.CUSTOM,
439+
});
390440
});
391441

392442
it('returns undefined when the custom fees are incomplete', () => {
393443
const optionFn = getSavedGasFeesOption({
394444
userFeeLevel: UserFeeLevel.CUSTOM,
395-
maxBaseFee: '0x1',
445+
maxBaseFee: '1',
396446
});
397447

398-
expect(optionFn?.('0x1')).toBeUndefined();
448+
expect(optionFn?.(MOCK_TRANSACTION_META)).toBeUndefined();
399449
});
400450

401451
it('returns undefined when there is no saved preference for the chain', () => {
402452
const optionFn = getSavedGasFeesOption({
403453
userFeeLevel: UserFeeLevel.CUSTOM,
404-
maxBaseFee: '0x1',
405-
priorityFee: '0x2',
454+
maxBaseFee: '1',
455+
priorityFee: '2',
406456
});
407457

408-
expect(optionFn?.('0x2')).toBeUndefined();
458+
expect(
459+
optionFn?.({ ...MOCK_TRANSACTION_META, chainId: '0x2' }),
460+
).toBeUndefined();
409461
});
410462
});
411463

app/core/Engine/controllers/transaction-controller/transaction-controller-init.ts

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
GasFeeEstimateLevel,
23
TransactionController,
34
TransactionType,
45
UserFeeLevel,
@@ -96,7 +97,8 @@ export const TransactionControllerInit: MessengerClientInitFunction<
9697
isSimulationEnabled: () =>
9798
initMessenger.call('PreferencesController:getState')
9899
.useTransactionSimulations,
99-
getSavedGasFees: (chainId) => getSavedGasFees(chainId, initMessenger),
100+
getSavedGasFees: (chainIdOrTransactionMeta) =>
101+
getSavedGasFees(chainIdOrTransactionMeta, initMessenger),
100102
messenger: controllerMessenger,
101103
publicKeyEIP7702: AppConstants.EIP_7702_PUBLIC_KEY as Hex | undefined,
102104
state: persistedState.TransactionController,
@@ -120,21 +122,31 @@ function isFirstTimeInteractionEnabled(
120122
);
121123
}
122124

125+
type SavedGasFeesWithLevel = SavedGasFees & {
126+
gasPrice?: string;
127+
level?: UserFeeLevel | GasFeeEstimateLevel;
128+
};
129+
123130
/**
124-
* `TransactionController` only exposes this hook as `(chainId) => SavedGasFees`,
125-
* with no account context, so the selected account is used as the best
126-
* available proxy for "the account this transaction is from". Only a custom
127-
* EIP-1559 fee override (both `maxBaseFee` and `priorityFee` present) can be
128-
* expressed by `SavedGasFees` — estimate-level preferences (Low/Medium/High)
129-
* and legacy `gasPrice` overrides aren't restored through this hook.
131+
* Retrieve saved gas fee preferences for the transaction account and chain.
130132
*/
131133
function getSavedGasFees(
132-
chainId: Hex,
134+
chainIdOrTransactionMeta: Hex | TransactionMeta,
133135
initMessenger: TransactionControllerInitMessenger,
134-
): SavedGasFees | undefined {
135-
const account = initMessenger
136-
.call('AccountsController:getSelectedAccount')
137-
.address.toLowerCase();
136+
): SavedGasFeesWithLevel | undefined {
137+
const selectedAccount = initMessenger.call(
138+
'AccountsController:getSelectedAccount',
139+
).address;
140+
const isTransactionMeta = typeof chainIdOrTransactionMeta !== 'string';
141+
const transactionMeta = isTransactionMeta
142+
? chainIdOrTransactionMeta
143+
: undefined;
144+
const account = (
145+
transactionMeta?.txParams.from ?? selectedAccount
146+
).toLowerCase();
147+
const chainId = isTransactionMeta
148+
? chainIdOrTransactionMeta.chainId
149+
: chainIdOrTransactionMeta;
138150

139151
const preferencesState = initMessenger.call(
140152
'PreferencesController:getState',
@@ -143,17 +155,26 @@ function getSavedGasFees(
143155
const savedGasFeePreference =
144156
preferencesState.advancedGasFee?.[chainId]?.[account];
145157

146-
if (savedGasFeePreference?.userFeeLevel !== UserFeeLevel.CUSTOM) {
158+
if (!savedGasFeePreference) {
147159
return undefined;
148160
}
149161

150-
const { maxBaseFee, priorityFee } = savedGasFeePreference;
162+
const { gasPrice, maxBaseFee, priorityFee, userFeeLevel } =
163+
savedGasFeePreference;
164+
165+
if (userFeeLevel !== UserFeeLevel.CUSTOM) {
166+
return { level: userFeeLevel as UserFeeLevel | GasFeeEstimateLevel };
167+
}
168+
169+
if (gasPrice) {
170+
return { gasPrice, level: UserFeeLevel.CUSTOM };
171+
}
151172

152173
if (!maxBaseFee || !priorityFee) {
153174
return undefined;
154175
}
155176

156-
return { maxBaseFee, priorityFee };
177+
return { maxBaseFee, priorityFee, level: UserFeeLevel.CUSTOM };
157178
}
158179

159180
function getKeyringController(messenger: TransactionControllerInitMessenger) {

0 commit comments

Comments
 (0)