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
19 changes: 10 additions & 9 deletions oxlint-suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -1509,6 +1509,11 @@
"count": 1
}
},
"packages/bridge-controller/src/utils/controllers/remote-feature-flags.ts": {
"typescript/explicit-function-return-type": {
"count": 1
}
},
"packages/bridge-controller/src/utils/feature-flags.ts": {
"id-length": {
"count": 1
Expand Down Expand Up @@ -2301,15 +2306,6 @@
"typescript/no-unsafe-argument": {
"count": 18
},
"typescript/no-unsafe-call": {
"count": 2
},
"typescript/no-unsafe-member-access": {
"count": 1
},
"typescript/no-unsafe-return": {
"count": 1
},
"typescript/prefer-nullish-coalescing": {
"count": 18
},
Expand Down Expand Up @@ -4447,6 +4443,11 @@
"count": 2
}
},
"packages/profile-sync-controller/src/sdk/__fixtures__/auth.ts": {
"typescript/no-misused-promises": {
"count": 1
}
},
"packages/profile-sync-controller/src/sdk/__fixtures__/test-utils.ts": {
"typescript/explicit-function-return-type": {
"count": 4
Expand Down
39 changes: 14 additions & 25 deletions packages/bridge-controller/src/bridge-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { InternalAccount } from '@metamask/keyring-internal-api';
import { abiERC20 } from '@metamask/metamask-eth-abis';
import { StaticIntervalPollingController } from '@metamask/polling-controller';
import type { TransactionController } from '@metamask/transaction-controller';
import type { CaipAssetType, Hex } from '@metamask/utils';
import type { CaipAssetType } from '@metamask/utils';
import { v4 as uuid } from 'uuid';

import { toQuoteResponseV2 } from './coercers/quote-response-v1-to-v2.js';
Expand Down Expand Up @@ -52,6 +52,8 @@ import {
formatChainIdToCaip,
formatChainIdToHex,
} from './utils/caip-formatters.js';
import { getAccountByAddress } from './utils/controllers/accounts.js';
import { getNetworkClientByChainId } from './utils/controllers/network.js';
import {
getBridgeFeatureFlags,
hasMinimumRequiredVersion,
Expand Down Expand Up @@ -622,8 +624,10 @@ export class BridgeController extends StaticIntervalPollingController<BridgePoll
) => {
try {
const srcChainIdInHex = formatChainIdToHex(quoteRequest.srcChainId);
const provider =
this.#getNetworkClientByChainId(srcChainIdInHex)?.provider;
const provider = getNetworkClientByChainId(
this.messenger,
srcChainIdInHex,
)?.provider;
const normalizedSrcTokenAddress = formatAddressToCaipReference(
quoteRequest.srcTokenAddress,
);
Expand Down Expand Up @@ -654,7 +658,8 @@ export class BridgeController extends StaticIntervalPollingController<BridgePoll
const isSrcChainNonEVM = isNonEvmChainId(quoteRequest.srcChainId);
const providerConfig = isSrcChainNonEVM
? undefined
: this.#getNetworkClientByChainId(
: getNetworkClientByChainId(
this.messenger,
formatChainIdToHex(quoteRequest.srcChainId),
)?.configuration;

Expand Down Expand Up @@ -1180,28 +1185,10 @@ export class BridgeController extends StaticIntervalPollingController<BridgePoll
if (!addressToUse) {
throw new Error('Account address is required');
}
const selectedAccount = this.messenger.call(
'AccountsController:getAccountByAddress',
addressToUse,
);
const selectedAccount = getAccountByAddress(this.messenger, addressToUse);
return selectedAccount;
}

#getNetworkClientByChainId(chainId: Hex) {
const networkClientId = this.messenger.call(
'NetworkController:findNetworkClientIdByChainId',
chainId,
);
if (!networkClientId) {
throw new Error(`No network client found for chainId: ${chainId}`);
}
const networkClient = this.messenger.call(
'NetworkController:getNetworkClientById',
networkClientId,
);
return networkClient;
}

readonly #getJwt = async (): Promise<string | undefined> => {
try {
const token = await this.messenger.call(
Expand Down Expand Up @@ -1538,8 +1525,10 @@ export class BridgeController extends StaticIntervalPollingController<BridgePoll
contractAddress: string,
destinationChainId: GenericQuoteRequest['destChainId'],
): Promise<string> => {
const networkClient = this.#getNetworkClientByChainId(CHAIN_IDS.MAINNET);
const provider = networkClient?.provider;
const provider = getNetworkClientByChainId(
this.messenger,
CHAIN_IDS.MAINNET,
)?.provider;
if (!provider) {
throw new Error('No provider found');
}
Expand Down
3 changes: 3 additions & 0 deletions packages/bridge-controller/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,3 +291,6 @@ export {
fetchTokens,
type SwapsToken,
} from './utils/swaps.js';

export { getAccountByAddress } from './utils/controllers/accounts.js';
export { getFeatureFlags } from './utils/controllers/remote-feature-flags.js';
4 changes: 2 additions & 2 deletions packages/bridge-controller/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,13 +397,13 @@ export type BridgeControllerEvents = BridgeControllerStateChangeEvent;

export type AllowedActions =
| AccountsControllerGetAccountByAddressAction
| AssetsControllerGetExchangeRatesForBridgeAction
| AuthenticationControllerGetBearerTokenAction
| CurrencyRateControllerGetStateAction
| SnapControllerHandleRequestAction
| NetworkControllerFindNetworkClientIdByChainIdAction
| NetworkControllerGetNetworkClientByIdAction
| RemoteFeatureFlagControllerGetStateAction
| AssetsControllerGetExchangeRatesForBridgeAction;
| SnapControllerHandleRequestAction;
export type AllowedEvents = never;

/**
Expand Down
16 changes: 16 additions & 0 deletions packages/bridge-controller/src/utils/controllers/accounts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import type { AccountsControllerGetAccountByAddressAction } from '@metamask/accounts-controller';

export const getAccountByAddress = <
MessengerType extends {
call(
action: AccountsControllerGetAccountByAddressAction['type'],
address: string,
): ReturnType<AccountsControllerGetAccountByAddressAction['handler']>;
},
>(
messenger: MessengerType,
address: string,
) => {
return messenger.call('AccountsController:getAccountByAddress', address);
};
28 changes: 28 additions & 0 deletions packages/bridge-controller/src/utils/controllers/network.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */

import type { BridgeControllerMessenger } from '../../types.js';

const getNetworkClientIdByChainId = (
messenger: BridgeControllerMessenger,
chainId: `0x${string}`,
) => {
return messenger.call(
'NetworkController:findNetworkClientIdByChainId',
chainId,
);
};

export const getNetworkClientByChainId = (
messenger: BridgeControllerMessenger,
chainId: `0x${string}`,
) => {
const networkClientId = getNetworkClientIdByChainId(messenger, chainId);
if (!networkClientId) {
throw new Error(`No network client found for chainId: ${chainId}`);
}

return messenger.call(
'NetworkController:getNetworkClientById',
networkClientId,
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import type { RemoteFeatureFlagControllerGetStateAction } from '@metamask/remote-feature-flag-controller';

export const getFeatureFlags = <
MessengerType extends {
call(
action: RemoteFeatureFlagControllerGetStateAction['type'],
): ReturnType<RemoteFeatureFlagControllerGetStateAction['handler']>;
},
>(
messenger: MessengerType,
) => {
const remoteFeatureFlags = messenger.call(
'RemoteFeatureFlagController:getState',
)?.remoteFeatureFlags;
return remoteFeatureFlags;
};
22 changes: 10 additions & 12 deletions packages/bridge-controller/src/utils/feature-flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
} from '../types.js';
import { validateFeatureFlagsResponse } from '../validators/feature-flags.js';
import { formatChainIdToCaip } from './caip-formatters.js';
import { getFeatureFlags } from './controllers/remote-feature-flags.js';

export const formatFeatureFlags = (
bridgeFeatureFlags: FeatureFlagsPlatformConfig,
Expand Down Expand Up @@ -55,32 +56,29 @@ export const processFeatureFlags = (
* @param messenger - Any messenger with access to RemoteFeatureFlagController:getState
* @returns The bridge feature flags
*/
export function getBridgeFeatureFlags<
export const getBridgeFeatureFlags = <
T extends {
call(
action: 'RemoteFeatureFlagController:getState',
): RemoteFeatureFlagControllerState;
},
>(messenger: T): FeatureFlagsPlatformConfig {
// This will return the bridgeConfig for the current platform even without specifying the platform
const remoteFeatureFlagControllerState = messenger.call(
'RemoteFeatureFlagController:getState',
);
>(
messenger: T,
): FeatureFlagsPlatformConfig => {
const remoteFeatureFlags = getFeatureFlags(messenger);

// bridgeConfigV2 is the feature flag for the mobile app
// bridgeConfig for Mobile has been deprecated since release of bridge and Solana in 7.46.0 was pushed back
// and there's no way to turn on bridgeConfig for 7.47.0 without affecting 7.46.0 as well.
// You will still get bridgeConfig returned from remoteFeatureFlagControllerState but you should use bridgeConfigV2 instead
// You will still get bridgeConfig returned from remoteFeatureFlags but you should use bridgeConfigV2 instead
// Mobile's bridgeConfig will be permanently serving the disabled variation, so falling back to it in Mobile will be ok
const rawMobileFlags =
remoteFeatureFlagControllerState?.remoteFeatureFlags?.bridgeConfigV2;
const rawMobileFlags = remoteFeatureFlags?.bridgeConfigV2;

// Extension LaunchDarkly will not have the bridgeConfigV2 field, so we'll continue to use bridgeConfig
const rawBridgeConfig =
remoteFeatureFlagControllerState?.remoteFeatureFlags?.bridgeConfig;
const rawBridgeConfig = remoteFeatureFlags?.bridgeConfig;

return processFeatureFlags(rawMobileFlags || rawBridgeConfig);
}
};

/**
* Checks if the client version is greater than or equal to the minimum required version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
QuoteResponse as QuoteResponseV1,
getNativeAssetForChainId,
validateQuoteResponseV1,
MetaMetricsSwapsEventSource,
} from '@metamask/bridge-controller';
import type {
GasFeeEstimates,
Expand Down Expand Up @@ -319,6 +320,7 @@ const setup = (options?: {
traceFn: (_req: any, fn?: any): any => fn?.(),
isQuoteStatusManagerEnabled: options?.isQuoteStatusManagerEnabled,
onQuoteStatusManagerError: options?.onQuoteStatusManagerError,
clientProduct: 'extension',
});

const startPollingSpy = vi
Expand Down Expand Up @@ -964,6 +966,7 @@ describe('BridgeStatusController (subscriptions + bridge polling + wiping)', ()
slippagePercentage: 0,
startTime: Date.now(),
isStxEnabled: false,
location: MetaMetricsSwapsEventSource.MainView,
});

expect(controller.state.txHistory.bridgeToWipe1).toBeDefined();
Expand Down Expand Up @@ -1021,6 +1024,7 @@ describe('BridgeStatusController (target uncovered branches)', () => {
addTransactionBatchFn: vi.fn(),
config: { customBridgeApiBaseUrl: 'http://localhost' },
traceFn: (_r: any, fn?: any): any => fn?.(),
clientProduct: 'extension',
});

expect(controller.state.txHistory.init1.attempts?.counter).toBe(
Expand Down Expand Up @@ -1236,14 +1240,19 @@ describe('BridgeStatusController (target uncovered branches)', () => {
evt === 'TransactionController:transactionStatusUpdated',
)?.[1];

failedCb({
transactionMeta: {
id: 'feat1',
type: TransactionType.bridge,
status: TransactionStatus.failed,
chainId: '0x1',
},
});
failedCb(
historyUtils.resolveHistoryKeyForTxMeta(
{
transactionMeta: {
id: 'feat1',
type: TransactionType.bridge,
status: TransactionStatus.failed,
chainId: '0x1',
} as unknown as TransactionMeta,
},
controller.state.txHistory,
),
);

// should skip due to featureId
expect((messenger.call as Mock).mock.calls).not.toStrictEqual(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ import { QuoteStatusManager } from './quote-status-manager/quotes-status-manager
import { BridgeClientId } from './types.js';
import type {
BridgeId,
StartPollingForBridgeTxStatusArgsSerialized,
StartPollingForBridgeTxStatusArgs,
BridgeHistoryItem,
BridgeStatusControllerState,
BridgeStatusControllerMessenger,
Expand Down Expand Up @@ -317,7 +317,7 @@ const getMockStartPollingForBridgeTxStatusArgs = ({
srcChainId = 42161,
destChainId = 10,
isStxEnabled = false,
} = {}): StartPollingForBridgeTxStatusArgsSerialized => ({
} = {}): StartPollingForBridgeTxStatusArgs => ({
bridgeTxMeta: {
id: txMetaId,
hash: srcTxHash === 'undefined' ? undefined : srcTxHash,
Expand Down
Loading
Loading