Skip to content

Commit 47b743e

Browse files
authored
fix: cp-13.11.0 dapp swap request for batch requests (#38190)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Fix issue with dapp swap comparison metrics and UI not working for batched requests. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: MetaMask/metamask-mobile#23186 ## **Manual testing steps** 1. Submit batched swap request 2. Check that metrics and UI work as expected ## **Screenshots/Recordings** TODO ## **Pre-merge author checklist** - [X] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [X] I've completed the PR template to the best of my ability - [X] I’ve included tests if applicable - [X] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [X] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds batch support for dapp swap comparison, moves quote fetching to a shared util used by middleware and wallet_sendCalls, and improves metrics/error capture and UI tab control. > > - **Backend/Controllers**: > - Expand `AppStateController` `dappSwapComparisonData` to include `commands`, `error`, and `tokenAddresses`; add `Hex` usage. > - Extract `getQuotesForConfirmation` to `app/scripts/lib/dapp-swap/dapp-swap-util` and simplify `dapp-swap-middleware` to call it; also call from `wallet_sendCalls` to access `securityAlertId`. > - Add batch transaction validation and command parsing (`parseTransactionData`, `checkValidSingleOrBatchTransaction`); change `getDataFromSwap` to accept `commandBytes`/`inputs`. > - Update selectors to surface new dapp swap fields. > - **UI**: > - Make `Tabs` controllable via new `activeTabKey`; update tests. > - Update Dapp Swap banner to use controlled tabs and `SwapType` enum; refine selection/metrics flow. > - Show decoded tx data from quoted swap only when selected (`isQuotedSwapDisplayedInInfo`). > - Metrics hooks now include commands and detailed failure reasons; submit capture timing adjusted. > - **Tests**: > - Add/adjust tests for middleware error/command capture, batch validation/parsing, tabs control, hooks, and transaction confirm behavior. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 83873f0. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 771ae71 commit 47b743e

File tree

21 files changed

+671
-222
lines changed

21 files changed

+671
-222
lines changed

app/scripts/controllers/app-state-controller.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ import {
1111
AcceptRequest,
1212
AddApprovalRequest,
1313
} from '@metamask/approval-controller';
14-
import { DeferredPromise, Json, createDeferredPromise } from '@metamask/utils';
14+
import {
15+
DeferredPromise,
16+
Hex,
17+
Json,
18+
createDeferredPromise,
19+
} from '@metamask/utils';
1520
import type { QrScanRequest, SerializedUR } from '@metamask/eth-qr-keyring';
1621
import type { Messenger } from '@metamask/messenger';
1722
import { Browser } from 'webextension-polyfill';
@@ -61,6 +66,14 @@ import type {
6166
PreferencesControllerStateChangeEvent,
6267
} from './preferences-controller';
6368

69+
export type DappSwapComparisonData = {
70+
quotes?: QuoteResponse[];
71+
latency?: number;
72+
commands?: string;
73+
error?: string;
74+
tokenAddresses?: Hex[];
75+
};
76+
6477
export type AppStateControllerState = {
6578
activeQrCodeScanRequest: QrScanRequest | null;
6679
addressSecurityAlertResponses: Record<string, CachedScanAddressResponse>;
@@ -133,7 +146,7 @@ export type AppStateControllerState = {
133146
pendingShieldCohortTxType: string | null;
134147
defaultSubscriptionPaymentOptions?: DefaultSubscriptionPaymentOptions;
135148
dappSwapComparisonData?: {
136-
[uniqueId: string]: { quotes?: QuoteResponse[]; latency?: number };
149+
[uniqueId: string]: DappSwapComparisonData;
137150
};
138151

139152
/**
@@ -1636,7 +1649,7 @@ export class AppStateController extends BaseController<
16361649

16371650
setDappSwapComparisonData(
16381651
uniqueId: string,
1639-
info: { quotes?: QuoteResponse[]; latency?: number },
1652+
info: DappSwapComparisonData,
16401653
): void {
16411654
this.update((state) => {
16421655
state.dappSwapComparisonData = {
@@ -1646,12 +1659,9 @@ export class AppStateController extends BaseController<
16461659
});
16471660
}
16481661

1649-
getDappSwapComparisonData(uniqueId: string):
1650-
| {
1651-
quotes?: QuoteResponse[];
1652-
latency?: number;
1653-
}
1654-
| undefined {
1662+
getDappSwapComparisonData(
1663+
uniqueId: string,
1664+
): DappSwapComparisonData | undefined {
16551665
return this.state.dappSwapComparisonData?.[uniqueId] ?? undefined;
16561666
}
16571667
}

app/scripts/lib/dapp-swap/dapp-swap-middleware.test.ts

Lines changed: 89 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ import { JsonRpcResponseStruct } from '@metamask/utils';
22

33
import { flushPromises } from '../../../../test/lib/timer-helpers';
44
import { mockBridgeQuotes } from '../../../../test/data/confirmations/contract-interaction';
5-
import {
6-
createDappSwapMiddleware,
7-
DappSwapMiddlewareRequest,
8-
} from './dapp-swap-middleware';
5+
import { createDappSwapMiddleware } from './dapp-swap-middleware';
6+
import { DappSwapMiddlewareRequest } from './dapp-swap-util';
97

108
const REQUEST_MOCK = {
119
params: [],
@@ -15,8 +13,8 @@ const REQUEST_MOCK = {
1513
networkClientId: 'networkClientId',
1614
};
1715

18-
const fetchQuotes = jest.fn();
19-
const setSwapQuotes = jest.fn();
16+
let fetchQuotes = jest.fn();
17+
const setDappSwapComparisonData = jest.fn();
2018
const getNetworkConfigurationByNetworkClientId = jest.fn();
2119

2220
const createMiddleware = (
@@ -27,7 +25,7 @@ const createMiddleware = (
2725
) => {
2826
const middlewareFunction = createDappSwapMiddleware({
2927
fetchQuotes,
30-
setSwapQuotes,
28+
setDappSwapComparisonData,
3129
getNetworkConfigurationByNetworkClientId,
3230
// eslint-disable-next-line @typescript-eslint/naming-convention
3331
dappSwapMetricsFlag: { enabled: true, bridge_quote_fees: 250 },
@@ -139,4 +137,88 @@ describe('DappSwapMiddleware', () => {
139137
walletAddress: '0x12312312312312',
140138
});
141139
});
140+
141+
it('capture error and commands if quote fetching fails', async () => {
142+
fetchQuotes = jest.fn().mockRejectedValue(new Error('fail'));
143+
getNetworkConfigurationByNetworkClientId.mockReturnValueOnce({
144+
chainId: '0x1',
145+
rpcEndpoints: [],
146+
});
147+
const { middlewareFunction } = createMiddleware();
148+
149+
const req = {
150+
...REQUEST_MOCK,
151+
method: 'eth_sendTransaction',
152+
origin: 'https://metamask.github.io',
153+
securityAlertResponse: {
154+
securityAlertId: '123',
155+
},
156+
params: [
157+
{
158+
data: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000068f0dd1b0000000000000000000000000000000000000000000000000000000000000003100604000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000003070b0e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000005af3107a4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e583100000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000007ffc3dbf3b2b50ff3a1d5523bc24bb5043837b1400000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000060000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000178239802520a9c99dcbd791f81326b70298d62900000000000000000000000000000000000000000000000000000000000601470c',
159+
from: '0x12312312312312',
160+
calls: [],
161+
},
162+
],
163+
networkClientId: 'networkClientId',
164+
};
165+
166+
await middlewareFunction(
167+
req as unknown as DappSwapMiddlewareRequest<(string | { to: string })[]>,
168+
{ ...JsonRpcResponseStruct.TYPE },
169+
() => undefined,
170+
);
171+
172+
await flushPromises();
173+
174+
expect(setDappSwapComparisonData).toHaveBeenCalledWith('123', {
175+
commands: '0x100604',
176+
error: 'Error fetching bridge quotes: fail',
177+
});
178+
});
179+
180+
it('capture error if request if not valid batch request', async () => {
181+
fetchQuotes = jest.fn().mockRejectedValue(new Error('fail'));
182+
getNetworkConfigurationByNetworkClientId.mockReturnValueOnce({
183+
chainId: '0x1',
184+
rpcEndpoints: [],
185+
});
186+
const { middlewareFunction } = createMiddleware();
187+
188+
const req = {
189+
...REQUEST_MOCK,
190+
method: 'eth_sendTransaction',
191+
origin: 'https://metamask.github.io',
192+
securityAlertResponse: {
193+
securityAlertId: '123',
194+
},
195+
params: [
196+
{
197+
data: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000068f0dd1b0000000000000000000000000000000000000000000000000000000000000003100604000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000003070b0e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000005af3107a4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e583100000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000007ffc3dbf3b2b50ff3a1d5523bc24bb5043837b1400000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000060000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000178239802520a9c99dcbd791f81326b70298d62900000000000000000000000000000000000000000000000000000000000601470c',
198+
from: '0x12312312312312',
199+
calls: [
200+
{
201+
data: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000068f0dd1b0000000000000000000000000000000000000000000000000000000000000003100604000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000003070b0e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000005af3107a4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e583100000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000007ffc3dbf3b2b50ff3a1d5523bc24bb5043837b1400000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000060000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000178239802520a9c99dcbd791f81326b70298d62900000000000000000000000000000000000000000000000000000000000601470c',
202+
},
203+
{ data: 'dummy_test_data' },
204+
],
205+
},
206+
],
207+
networkClientId: 'networkClientId',
208+
};
209+
210+
await middlewareFunction(
211+
req as unknown as DappSwapMiddlewareRequest<(string | { to: string })[]>,
212+
{ ...JsonRpcResponseStruct.TYPE },
213+
() => undefined,
214+
);
215+
216+
await flushPromises();
217+
218+
expect(setDappSwapComparisonData).toHaveBeenCalledWith('123', {
219+
commands: '0x100604',
220+
error:
221+
'Error fetching bridge quotes: Error: Error getting data from swap: invalid batch transaction, invalid command',
222+
});
223+
});
142224
});
Lines changed: 25 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,32 @@
1-
import log from 'loglevel';
1+
import { Json, JsonRpcResponse } from '@metamask/utils';
22
import {
3-
Hex,
4-
Json,
5-
JsonRpcParams,
6-
JsonRpcRequest,
7-
JsonRpcResponse,
8-
} from '@metamask/utils';
3+
GenericQuoteRequest,
4+
QuoteResponse,
5+
} from '@metamask/bridge-controller';
96
import {
107
NetworkClientId,
118
NetworkConfiguration,
129
} from '@metamask/network-controller';
13-
import {
14-
GenericQuoteRequest,
15-
QuoteResponse,
16-
} from '@metamask/bridge-controller';
17-
18-
import { captureException } from '../../../../shared/lib/sentry';
19-
import { getDataFromSwap } from '../../../../shared/modules/dapp-swap-comparison/dapp-swap-comparison-utils';
20-
import { SecurityAlertResponse } from '../ppom/types';
2110

22-
export type DappSwapMiddlewareRequest<
23-
Params extends JsonRpcParams = JsonRpcParams,
24-
> = Required<JsonRpcRequest<Params>> & {
25-
origin?: string;
26-
securityAlertResponse?: SecurityAlertResponse | undefined;
27-
networkClientId: NetworkClientId;
28-
params: {
29-
data: string;
30-
from: string;
31-
calls: { data: string; from: string }[];
32-
}[];
33-
};
34-
35-
const FOUR_BYTE_EXECUTE_SWAP_CONTRACT = '0x3593564c';
36-
const DAPP_SWAP_COMPARISON_ORIGIN = 'https://app.uniswap.org';
37-
const TEST_DAPP_ORIGIN = 'https://metamask.github.io';
38-
const DEFAULT_QUOTEFEE = 250;
39-
40-
const getSwapDetails = (params: DappSwapMiddlewareRequest['params']) => {
41-
if (!params?.length) {
42-
return {
43-
data: undefined,
44-
from: undefined,
45-
chainId: undefined,
46-
};
47-
}
48-
const { calls, data, from } = params[0];
49-
let transactionData = data;
50-
if (calls?.length) {
51-
const executeSwapCall = calls?.find(({ data: trxnData }) =>
52-
trxnData?.startsWith(FOUR_BYTE_EXECUTE_SWAP_CONTRACT),
53-
);
54-
if (executeSwapCall) {
55-
transactionData = executeSwapCall?.data;
56-
}
57-
}
58-
return {
59-
data: transactionData,
60-
from,
61-
};
62-
};
11+
import { DappSwapComparisonData } from '../../controllers/app-state-controller';
12+
import {
13+
DappSwapMiddlewareRequest,
14+
getQuotesForConfirmation,
15+
} from './dapp-swap-util';
6316

6417
export function createDappSwapMiddleware<
6518
Params extends (string | { to: string })[],
6619
Result extends Json,
6720
>({
6821
fetchQuotes,
69-
setSwapQuotes,
22+
setDappSwapComparisonData,
7023
getNetworkConfigurationByNetworkClientId,
7124
dappSwapMetricsFlag,
7225
}: {
7326
fetchQuotes: (quotesInput: GenericQuoteRequest) => Promise<QuoteResponse[]>;
74-
setSwapQuotes: (
27+
setDappSwapComparisonData: (
7528
uniqueId: string,
76-
info: { quotes?: QuoteResponse[]; latency?: number },
29+
info: DappSwapComparisonData,
7730
) => void;
7831
getNetworkConfigurationByNetworkClientId: (
7932
networkClientId: NetworkClientId,
@@ -86,54 +39,20 @@ export function createDappSwapMiddleware<
8639
_res: JsonRpcResponse<Result>,
8740
next: () => void,
8841
) => {
89-
try {
90-
// eslint-disable-next-line @typescript-eslint/naming-convention
91-
const { enabled: dappSwapEnabled, bridge_quote_fees: bridgeQuoteFees } =
92-
dappSwapMetricsFlag;
93-
if (!dappSwapEnabled) {
94-
next();
95-
return;
96-
}
97-
const { securityAlertResponse, params, origin } = req;
98-
const { securityAlertId } = securityAlertResponse ?? {};
99-
100-
if (
101-
(req.method === 'eth_sendTransaction' ||
102-
req.method === 'wallet_sendCalls') &&
103-
(origin === DAPP_SWAP_COMPARISON_ORIGIN || origin === TEST_DAPP_ORIGIN)
104-
) {
105-
const { chainId } =
106-
getNetworkConfigurationByNetworkClientId(req.networkClientId) ?? {};
42+
const { securityAlertResponse } = req;
43+
const { securityAlertId } = securityAlertResponse ?? {};
10744

108-
const { data, from } = getSwapDetails(params);
109-
if (data && securityAlertId && chainId) {
110-
const { quotesInput } = getDataFromSwap(chainId as Hex, data);
111-
if (quotesInput) {
112-
const startTime = new Date().getTime();
113-
fetchQuotes({
114-
...quotesInput,
115-
walletAddress: from,
116-
fee: bridgeQuoteFees ?? DEFAULT_QUOTEFEE,
117-
})
118-
.then((quotes) => {
119-
const endTime = new Date().getTime();
120-
const latency = endTime - startTime;
121-
if (quotes) {
122-
setSwapQuotes(securityAlertId, { quotes, latency });
123-
}
124-
})
125-
.catch((error) => {
126-
log.error('Error fetching dapp swap quotes', error);
127-
captureException(error);
128-
});
129-
}
130-
}
131-
}
132-
} catch (error) {
133-
log.error('Error fetching dapp swap quotes', error);
134-
captureException(error);
135-
} finally {
136-
next();
45+
if (securityAlertId && req.method === 'eth_sendTransaction') {
46+
getQuotesForConfirmation({
47+
req,
48+
fetchQuotes,
49+
setDappSwapComparisonData,
50+
getNetworkConfigurationByNetworkClientId,
51+
dappSwapMetricsFlag,
52+
securityAlertId,
53+
});
13754
}
55+
56+
next();
13857
};
13958
}

0 commit comments

Comments
 (0)