Skip to content

Commit 0282a9d

Browse files
authored
Merge branch 'Version-v12.16.0' into cp-fix-12.16-swap-commits
2 parents e7c83e7 + 0161c3c commit 0282a9d

File tree

6 files changed

+76
-62
lines changed

6 files changed

+76
-62
lines changed

app/scripts/controller-init/confirmations/transaction-controller-init.ts

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,26 @@ function getControllers(
224224
};
225225
}
226226

227+
function getSmartTransactionCommonParams(flatState: ControllerFlatState) {
228+
// UI state is required to support shared selectors to avoid duplicate logic in frontend and backend.
229+
// Ideally all backend logic would instead rely on messenger event / state subscriptions.
230+
const uiState = getUIState(flatState);
231+
232+
// @ts-expect-error Smart transaction selector types does not match controller state
233+
const isSmartTransaction = getIsSmartTransaction(uiState);
234+
235+
// @ts-expect-error Smart transaction selector types does not match controller state
236+
const featureFlags = getFeatureFlagsByChainId(uiState);
237+
238+
const isHardwareWalletAccount = isHardwareWallet(uiState);
239+
240+
return {
241+
isSmartTransaction,
242+
featureFlags,
243+
isHardwareWalletAccount,
244+
};
245+
}
246+
227247
function publishSmartTransactionHook(
228248
transactionController: TransactionController,
229249
smartTransactionsController: SmartTransactionsController,
@@ -232,29 +252,22 @@ function publishSmartTransactionHook(
232252
transactionMeta: TransactionMeta,
233253
signedTransactionInHex: Hex,
234254
) {
235-
// UI state is required to support shared selectors to avoid duplicate logic in frontend and backend.
236-
// Ideally all backend logic would instead rely on messenger event / state subscriptions.
237-
const uiState = getUIState(flatState);
238-
239-
// @ts-expect-error Smart transaction selector types does not match controller state
240-
const isSmartTransaction = getIsSmartTransaction(uiState);
255+
const { isSmartTransaction, featureFlags, isHardwareWalletAccount } =
256+
getSmartTransactionCommonParams(flatState);
241257

242258
if (!isSmartTransaction) {
243259
// Will cause TransactionController to publish to the RPC provider as normal.
244260
return { transactionHash: undefined };
245261
}
246262

247-
// @ts-expect-error Smart transaction selector types does not match controller state
248-
const featureFlags = getFeatureFlagsByChainId(uiState);
249-
250263
return submitSmartTransactionHook({
251264
transactionMeta,
252265
signedTransactionInHex,
253266
transactionController,
254267
smartTransactionsController,
255268
controllerMessenger: hookControllerMessenger,
256269
isSmartTransaction,
257-
isHardwareWallet: isHardwareWallet(uiState),
270+
isHardwareWallet: isHardwareWalletAccount,
258271
// @ts-expect-error Smart transaction selector return type does not match FeatureFlags type from hook
259272
featureFlags,
260273
});
@@ -273,21 +286,16 @@ function publishBatchSmartTransactionHook({
273286
flatState: ControllerFlatState;
274287
transactions: PublishBatchHookTransaction[];
275288
}) {
276-
// UI state is required to support shared selectors to avoid duplicate logic in frontend and backend.
277-
// Ideally all backend logic would instead rely on messenger event / state subscriptions.
278-
const uiState = getUIState(flatState);
279-
280-
// @ts-expect-error Smart transaction selector types does not match controller state
281-
const isSmartTransaction = getIsSmartTransaction(uiState);
289+
const { isSmartTransaction, featureFlags, isHardwareWalletAccount } =
290+
getSmartTransactionCommonParams(flatState);
282291

283292
if (!isSmartTransaction) {
284293
// Will cause TransactionController to publish to the RPC provider as normal.
285-
return undefined;
294+
throw new Error(
295+
'publishBatchSmartTransactionHook: Smart Transaction is required for batch submissions',
296+
);
286297
}
287298

288-
// @ts-expect-error Smart transaction selector types does not match controller state
289-
const featureFlags = getFeatureFlagsByChainId(uiState);
290-
291299
// Get transactionMeta based on the last transaction ID
292300
const lastTransaction = transactions[transactions.length - 1];
293301
const transactionMeta = getTransactionById(
@@ -297,10 +305,9 @@ function publishBatchSmartTransactionHook({
297305

298306
// If we couldn't find the transaction, we should handle that gracefully
299307
if (!transactionMeta) {
300-
console.warn(
301-
`Publish batch hook: could not find transaction with id ${lastTransaction.id}`,
308+
throw new Error(
309+
`publishBatchSmartTransactionHook: Could not find transaction with id ${lastTransaction.id}`,
302310
);
303-
return undefined;
304311
}
305312

306313
return submitBatchSmartTransactionHook({
@@ -309,7 +316,7 @@ function publishBatchSmartTransactionHook({
309316
smartTransactionsController,
310317
controllerMessenger: hookControllerMessenger,
311318
isSmartTransaction,
312-
isHardwareWallet: isHardwareWallet(uiState),
319+
isHardwareWallet: isHardwareWalletAccount,
313320
// @ts-expect-error Smart transaction selector return type does not match FeatureFlags type from hook
314321
featureFlags,
315322
transactionMeta,

app/scripts/controller-init/messengers/transaction-controller-messenger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ export function getTransactionControllerInitMessenger(
9898
'SmartTransactionsController:smartTransaction',
9999
],
100100
allowedActions: [
101+
'ApprovalController:acceptRequest',
101102
'ApprovalController:addRequest',
102103
'ApprovalController:endFlow',
103104
'ApprovalController:startFlow',
104105
'ApprovalController:updateRequestState',
105-
'ApprovalController:acceptRequest',
106106
'NetworkController:getEIP1559Compatibility',
107107
'RemoteFeatureFlagController:getState',
108108
'SwapsController:setApproveTxId',

app/scripts/lib/transaction/smart-transactions.test.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,13 @@ function withRequest<ReturnValue>(
7979
const startFlowSpy = jest.fn().mockResolvedValue({ id: 'approvalId' });
8080
messenger.registerActionHandler('ApprovalController:startFlow', startFlowSpy);
8181

82-
const addRequestSpy = jest.fn().mockImplementation(() => ({
83-
then: (callback: () => void) => {
84-
addRequestCallback = callback;
85-
},
86-
}));
82+
const addRequestSpy = jest.fn().mockImplementation(() => {
83+
return Promise.resolve().then(() => {
84+
if (typeof addRequestCallback === 'function') {
85+
addRequestCallback();
86+
}
87+
});
88+
});
8789
messenger.registerActionHandler(
8890
'ApprovalController:addRequest',
8991
addRequestSpy,
@@ -142,7 +144,8 @@ function withRequest<ReturnValue>(
142144
txParams: {
143145
from: addressFrom,
144146
to: '0x1678a085c290ebd122dc42cba69373b5953b831d',
145-
gasPrice: '0x77359400',
147+
maxFeePerGas: '0x2fd8a58d7',
148+
maxPriorityFeePerGas: '0xaa0f8a94',
146149
gas: '0x7b0d',
147150
nonce: '0x4b',
148151
},
@@ -551,6 +554,7 @@ describe('submitSmartTransactionHook', () => {
551554

552555
const endFlowSpy = jest.fn();
553556
const acceptRequestSpy = jest.fn();
557+
const addRequestSpy = jest.fn(() => Promise.resolve());
554558

555559
// Create a mock messenger
556560
const mockMessenger = {
@@ -564,6 +568,9 @@ describe('submitSmartTransactionHook', () => {
564568
if (method === 'ApprovalController:acceptRequest') {
565569
return acceptRequestSpy(...args);
566570
}
571+
if (method === 'ApprovalController:addRequest') {
572+
return addRequestSpy();
573+
}
567574
return undefined;
568575
}),
569576
subscribe: jest.fn(),
@@ -631,8 +638,9 @@ describe('submitBatchSmartTransactionHook', () => {
631638
},
632639
},
633640
async ({ request }) => {
634-
const result = await submitBatchSmartTransactionHook(request);
635-
expect(result).toEqual({ results: [] });
641+
await expect(submitBatchSmartTransactionHook(request)).rejects.toThrow(
642+
'submitBatch: Smart Transaction is required for batch submissions',
643+
);
636644
},
637645
);
638646
});

app/scripts/lib/transaction/smart-transactions.ts

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,11 @@ class SmartTransactionHook {
217217
}
218218

219219
async submitBatch() {
220-
// Will cause TransactionController to publish to the RPC provider as normal.
221-
const useRegularTransactionSubmit = undefined;
222-
220+
// No fallback to regular transaction submission
223221
if (!this.#isSmartTransaction) {
224-
return useRegularTransactionSubmit;
222+
throw new Error(
223+
'submitBatch: Smart Transaction is required for batch submissions',
224+
);
225225
}
226226

227227
if (this.#shouldShowStatusPage) {
@@ -233,7 +233,7 @@ class SmartTransactionHook {
233233
const uuid = submitTransactionResponse?.uuid;
234234

235235
if (!uuid) {
236-
throw new Error('No smart transaction UUID');
236+
throw new Error('submitBatch: No smart transaction UUID');
237237
}
238238

239239
await this.#processApprovalIfNeeded(uuid);
@@ -244,7 +244,7 @@ class SmartTransactionHook {
244244

245245
if (transactionHash === null) {
246246
throw new Error(
247-
'Transaction does not have a transaction hash, there was a problem',
247+
'submitBatch: Transaction does not have a transaction hash, there was a problem',
248248
);
249249
}
250250

@@ -263,24 +263,29 @@ class SmartTransactionHook {
263263

264264
return submitBatchResponse;
265265
} catch (error) {
266-
log.error('Error in smart transaction publish batch hook', error);
266+
log.error(
267+
'submitBatch: Error in smart transaction publish batch hook',
268+
error,
269+
);
267270
this.#onApproveOrReject();
268271
throw error;
269272
}
270273
}
271274

272-
/**
273-
* Ends an existing approval flow and clears the shared approval flow ID
274-
*
275-
* @param approvalFlowId - The ID of the approval flow to end
276-
* @returns Promise that resolves when the flow is successfully ended or errors are handled
277-
*/
278-
async #endExistingApprovalFlow(approvalFlowId: string): Promise<void> {
275+
async #endApprovalFlow(flowId: string): Promise<void> {
279276
try {
280-
// End the existing flow
281277
await this.#controllerMessenger.call('ApprovalController:endFlow', {
282-
id: approvalFlowId,
278+
id: flowId,
283279
});
280+
} catch (error) {
281+
// If the flow is already ended, we can ignore the error.
282+
}
283+
}
284+
285+
async #endExistingApprovalFlow(approvalFlowId: string): Promise<void> {
286+
try {
287+
// End the existing flow
288+
await this.#endApprovalFlow(approvalFlowId);
284289

285290
// Accept the request to close the UI
286291
await this.#controllerMessenger.call(
@@ -327,13 +332,7 @@ class SmartTransactionHook {
327332
return;
328333
}
329334
this.#approvalFlowEnded = true;
330-
try {
331-
this.#controllerMessenger.call('ApprovalController:endFlow', {
332-
id: this.#approvalFlowId,
333-
});
334-
} catch (error) {
335-
// If the flow is already ended, we can ignore the error.
336-
}
335+
this.#endApprovalFlow(this.#approvalFlowId);
337336

338337
// Clear the shared approval flow ID when we end the flow
339338
if (SmartTransactionHook.#sharedApprovalFlowId === this.#approvalFlowId) {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@
315315
"@metamask/scure-bip39": "^2.0.3",
316316
"@metamask/selected-network-controller": "^19.0.0",
317317
"@metamask/signature-controller": "^26.0.0",
318-
"@metamask/smart-transactions-controller": "^16.2.0",
318+
"@metamask/smart-transactions-controller": "^16.3.0",
319319
"@metamask/snaps-controllers": "^11.1.0",
320320
"@metamask/snaps-execution-environments": "^7.1.0",
321321
"@metamask/snaps-rpc-methods": "^12.0.0",

yarn.lock

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6344,9 +6344,9 @@ __metadata:
63446344
languageName: node
63456345
linkType: hard
63466346

6347-
"@metamask/smart-transactions-controller@npm:^16.2.0":
6348-
version: 16.2.0
6349-
resolution: "@metamask/smart-transactions-controller@npm:16.2.0"
6347+
"@metamask/smart-transactions-controller@npm:^16.3.0":
6348+
version: 16.3.0
6349+
resolution: "@metamask/smart-transactions-controller@npm:16.3.0"
63506350
dependencies:
63516351
"@babel/runtime": "npm:^7.24.1"
63526352
"@ethereumjs/tx": "npm:^5.2.1"
@@ -6368,7 +6368,7 @@ __metadata:
63686368
optional: true
63696369
"@metamask/approval-controller":
63706370
optional: true
6371-
checksum: 10/3cf74a5ab01ce62e32d0c006d1519bdaccf3252636d83be9537c915caba049e151d981b74a58e4a1122defcf6a1d13d689d53b8f3cbbc31870d2896fa43a5b31
6371+
checksum: 10/0dc4fc7ce58c45af6598b8209646e8ce1eff7f31fc3fd7abe6ceae5d3ead9e4eafa7445eff6ecdc2b606fea9af30658adf5e2e15fce3bdbfdcee41bceb31795e
63726372
languageName: node
63736373
linkType: hard
63746374

@@ -27376,7 +27376,7 @@ __metadata:
2737627376
"@metamask/scure-bip39": "npm:^2.0.3"
2737727377
"@metamask/selected-network-controller": "npm:^19.0.0"
2737827378
"@metamask/signature-controller": "npm:^26.0.0"
27379-
"@metamask/smart-transactions-controller": "npm:^16.2.0"
27379+
"@metamask/smart-transactions-controller": "npm:^16.3.0"
2738027380
"@metamask/snaps-controllers": "npm:^11.1.0"
2738127381
"@metamask/snaps-execution-environments": "npm:^7.1.0"
2738227382
"@metamask/snaps-rpc-methods": "npm:^12.0.0"

0 commit comments

Comments
 (0)