Skip to content

Commit

Permalink
Merge branch 'develop' into developer-settings
Browse files Browse the repository at this point in the history
  • Loading branch information
pnarayanaswamy committed Jul 22, 2024
2 parents 5cac014 + 62e01ef commit da6a204
Show file tree
Hide file tree
Showing 27 changed files with 351 additions and 133 deletions.
8 changes: 8 additions & 0 deletions app/scripts/lib/transaction/smart-transactions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ describe('submitSmartTransactionHook', () => {
smartTransactionsController: createSmartTransactionsControllerMock(),
transactionController: createTransactionControllerMock(),
isSmartTransaction: true,
isHardwareWallet: false,
controllerMessenger: createSmartTransactionsControllerMessengerMock(),
featureFlags: {
extensionActive: true,
Expand Down Expand Up @@ -148,6 +149,13 @@ describe('submitSmartTransactionHook', () => {
expect(result).toEqual({ transactionHash: undefined });
});

it('falls back to regular transaction submit if a hardware wallet is used', async () => {
const request: SubmitSmartTransactionRequestMocked = createRequest();
request.isHardwareWallet = true;
const result = await submitSmartTransactionHook(request);
expect(result).toEqual({ transactionHash: undefined });
});

it('falls back to regular transaction submit if /getFees throws an error', async () => {
const request: SubmitSmartTransactionRequestMocked = createRequest();
jest
Expand Down
6 changes: 6 additions & 0 deletions app/scripts/lib/transaction/smart-transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export type SubmitSmartTransactionRequest = {
smartTransactionsController: SmartTransactionsController;
transactionController: TransactionController;
isSmartTransaction: boolean;
isHardwareWallet: boolean;
controllerMessenger: SmartTransactionsControllerMessenger;
featureFlags: FeatureFlags;
};
Expand Down Expand Up @@ -90,6 +91,8 @@ class SmartTransactionHook {

#isSmartTransaction: boolean;

#isHardwareWallet: boolean;

#smartTransactionsController: SmartTransactionsController;

#transactionController: TransactionController;
Expand All @@ -104,6 +107,7 @@ class SmartTransactionHook {
smartTransactionsController,
transactionController,
isSmartTransaction,
isHardwareWallet,
controllerMessenger,
featureFlags,
} = request;
Expand All @@ -113,6 +117,7 @@ class SmartTransactionHook {
this.#smartTransactionsController = smartTransactionsController;
this.#transactionController = transactionController;
this.#isSmartTransaction = isSmartTransaction;
this.#isHardwareWallet = isHardwareWallet;
this.#controllerMessenger = controllerMessenger;
this.#featureFlags = featureFlags;
this.#isDapp = transactionMeta.origin !== ORIGIN_METAMASK;
Expand All @@ -132,6 +137,7 @@ class SmartTransactionHook {
const useRegularTransactionSubmit = { transactionHash: undefined };
if (
!this.#isSmartTransaction ||
this.#isHardwareWallet ||
isUnsupportedTransactionTypeForSmartTransaction
) {
return useRegularTransactionSubmit;
Expand Down
2 changes: 2 additions & 0 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ import { isManifestV3 } from '../../shared/modules/mv3.utils';
import { convertNetworkId } from '../../shared/modules/network.utils';
import {
getIsSmartTransaction,
isHardwareWallet,
getFeatureFlagsByChainId,
getSmartTransactionsOptInStatus,
getCurrentChainSupportsSmartTransactions,
Expand Down Expand Up @@ -6752,6 +6753,7 @@ export default class MetamaskController extends EventEmitter {
smartTransactionsController: this.smartTransactionsController,
controllerMessenger: this.controllerMessenger,
isSmartTransaction,
isHardwareWallet: isHardwareWallet(state),
featureFlags,
});
}
Expand Down
3 changes: 3 additions & 0 deletions shared/modules/selectors/account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { isHardwareWallet } from '../../../ui/selectors/selectors';

export { isHardwareWallet };
4 changes: 2 additions & 2 deletions shared/modules/selectors/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ describe('Selectors', () => {
expect(getSmartTransactionsEnabled(state)).toBe(false);
});

it('returns false if feature flag is enabled, is a HW and is Ethereum network', () => {
it('returns true if feature flag is enabled, is a HW and is Ethereum network', () => {
const state = createSwapsMockStore();
const newState = {
...state,
Expand All @@ -150,7 +150,7 @@ describe('Selectors', () => {
},
},
};
expect(getSmartTransactionsEnabled(newState)).toBe(false);
expect(getSmartTransactionsEnabled(newState)).toBe(true);
});

it('returns false if feature flag is enabled, not a HW and is Polygon network', () => {
Expand Down
1 change: 1 addition & 0 deletions shared/modules/selectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './smart-transactions';
export * from './feature-flags';
export * from './token-auto-detect';
export * from './nft-auto-detect';
export * from './account';
8 changes: 0 additions & 8 deletions test/e2e/playwright/mmi/specs/navigation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ const supportContactUs =
const mmiHomePage = 'https://metamask.io/institutions/';
const privacyAndNotice = 'https://consensys.io/privacy-notice';
const openSeaTermsOfUse = 'https://opensea.io/securityproviderterms';
const metamaskAttributions =
'https://raw.githubusercontent.com/MetaMask/metamask-extension/develop/attribution.txt';
const termsOfUse = 'https://consensys.io/terms-of-use';
const learnMoreArticles = 'https://support.metamask.io/';

Expand Down Expand Up @@ -159,12 +157,6 @@ test.describe('MMI Navigation', () => {
privacyAndNotice,
);
await checkLinkURL(context, mainMenuPage.page, 'Terms of use', termsOfUse);
await checkLinkURL(
context,
mainMenuPage.page,
'Attributions',
metamaskAttributions,
);
await checkLinkURL(
context,
mainMenuPage.page,
Expand Down
51 changes: 34 additions & 17 deletions test/e2e/webdriver/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -1072,29 +1072,46 @@ class Driver {
const windowHandles = await this.driver.getAllWindowHandles();
for (const handle of windowHandles) {
await this.driver.switchTo().window(handle);
const screenshot = await this.driver.takeScreenshot();
await fs.writeFile(
`${filepathBase}-screenshot-${windowHandles.indexOf(handle) + 1}.png`,
screenshot,
{
encoding: 'base64',
},
);
const windowTitle = await this.driver.getTitle();
if (windowTitle !== 'MetaMask Offscreen Page') {
const screenshot = await this.driver.takeScreenshot();
await fs.writeFile(
`${filepathBase}-screenshot-${
windowHandles.indexOf(handle) + 1
}.png`,
screenshot,
{
encoding: 'base64',
},
);
}
}
} catch (e) {
console.error('Failed to take screenshot', e);
}
const htmlSource = await this.driver.getPageSource();
await fs.writeFile(`${filepathBase}-dom.html`, htmlSource);
const uiState = await this.driver.executeScript(
() =>
window.stateHooks?.getCleanAppState &&
window.stateHooks.getCleanAppState(),
);
await fs.writeFile(
`${filepathBase}-state.json`,
JSON.stringify(uiState, null, 2),
);

// We want to take a state snapshot of the app if possible, this is useful for debugging
try {
const windowHandles = await this.driver.getAllWindowHandles();
for (const handle of windowHandles) {
await this.driver.switchTo().window(handle);
const uiState = await this.driver.executeScript(
() =>
window.stateHooks?.getCleanAppState &&
window.stateHooks.getCleanAppState(),
);
if (uiState) {
await fs.writeFile(
`${filepathBase}-state-${windowHandles.indexOf(handle) + 1}.json`,
JSON.stringify(uiState, null, 2),
);
}
}
} catch (e) {
console.error('Failed to take state', e);
}
}

async checkBrowserForLavamoatLogs() {
Expand Down
1 change: 1 addition & 0 deletions test/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ process.env.NOTIFICATIONS_SERVICE_URL =
process.env.PUSH_NOTIFICATIONS_SERVICE_URL =
'https://mock-test-push-notifications-api.metamask.io';
process.env.PORTFOLIO_URL = 'https://portfolio.test';
process.env.METAMASK_VERSION = 'MOCK_VERSION';
process.env.ENABLE_CONFIRMATION_REDESIGN = 'true';
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ Step,Test Steps,Test Data,Expected Result,Notes
9,Click on the link for the 'Privacy policy',,Privacy policy 'https://consensys.io/privacy-policy' page is loaded,Critical because it's the only way to access privacy policy
10,Click on the link for the 'Terms of use',,Terms of use page 'https://consensys.io/terms-of-use' is loaded,
11,Click on the link for the 'Visit our support center',,Support page 'https://support.metamask.io' is loaded,
12,Click on the link for the 'Attributions',,Attributions 'https://raw.githubusercontent.com/MetaMask/metamask-extension/develop/attribution.txt' page is loaded,
12,Click on the link for the 'Attributions',,Attributions 'https://raw.githubusercontent.com/MetaMask/metamask-extension/{CURRENT_METAMASK_VERSION}/attribution.txt' page is loaded,
13,Click on the link for the 'Visit our website',,Visit our website 'https://metamask.io/' page is loaded,
14,Click on the link for the 'Contact us',,Contact us 'https://support.metamask.io' code page is loaded,
2 changes: 1 addition & 1 deletion ui/components/app/assets/nfts/nft-details/nft-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ export default function NftDetails({ nft }: { nft: Nft }) {
color={IconColor.iconMuted}
onClick={() => {
global.platform.openTab({
url: lastSale?.orderSource as string,
url: getBoughtForLink() as string,
});
}}
iconName={IconName.Export}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@ import MetafoxLogo from '../../ui/metafox-logo';
import { PickerNetwork } from '../../component-library';
import { DEFAULT_ROUTE } from '../../../helpers/constants/routes';
import { getTestNetworkBackgroundColor } from '../../../selectors';
import {
MultichainProviderConfig,
ProviderConfigWithImageUrl,
} from '../../../../shared/constants/multichain/networks';
import { MultichainNetwork } from '../../../selectors/multichain';

type AppHeaderLockedContentProps = {
currentNetwork: ProviderConfigWithImageUrl | MultichainProviderConfig;
currentNetwork: MultichainNetwork;
networkOpenCallback: () => void;
};

Expand All @@ -36,7 +33,7 @@ export const AppHeaderLockedContent = ({
}}
aria-label={`${t('networkMenu')} ${currentNetwork?.nickname}`}
label={currentNetwork?.nickname ?? ''}
src={currentNetwork?.rpcPrefs?.imageUrl}
src={currentNetwork?.network?.rpcPrefs?.imageUrl}
onClick={(e: React.MouseEvent<HTMLElement>) => {
e.stopPropagation();
e.preventDefault();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,13 @@ import { MetaMetricsContext } from '../../../contexts/metametrics';
import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard';
import { MINUTE } from '../../../../shared/constants/time';
import { NotificationsTagCounter } from '../notifications-tag-counter';
import {
MultichainProviderConfig,
ProviderConfigWithImageUrl,
} from '../../../../shared/constants/multichain/networks';
import { CONNECTIONS } from '../../../helpers/constants/routes';
import { MultichainNetwork } from '../../../selectors/multichain';

type AppHeaderUnlockedContentProps = {
popupStatus: boolean;
isEvmNetwork: boolean;
currentNetwork: ProviderConfigWithImageUrl | MultichainProviderConfig;
currentNetwork: MultichainNetwork;
networkOpenCallback: () => void;
disableNetworkPicker: boolean;
disableAccountPicker: boolean;
Expand Down Expand Up @@ -135,7 +132,7 @@ export const AppHeaderUnlockedContent = ({
className="multichain-app-header__contents--avatar-network"
ref={menuRef}
as="button"
src={currentNetwork?.rpcPrefs?.imageUrl ?? ''}
src={currentNetwork?.network?.rpcPrefs?.imageUrl ?? ''}
label={currentNetwork?.nickname ?? ''}
aria-label={`${t('networkMenu')} ${currentNetwork?.nickname}`}
labelProps={{
Expand All @@ -162,7 +159,7 @@ export const AppHeaderUnlockedContent = ({
margin={2}
aria-label={`${t('networkMenu')} ${currentNetwork?.nickname}`}
label={currentNetwork?.nickname ?? ''}
src={currentNetwork?.rpcPrefs?.imageUrl}
src={currentNetwork?.network?.rpcPrefs?.imageUrl}
onClick={(e: React.MouseEvent<HTMLElement>) => {
e.stopPropagation();
e.preventDefault();
Expand Down
13 changes: 4 additions & 9 deletions ui/components/multichain/app-header/app-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,8 @@ export const AppHeader = ({ location }) => {
const menuRef = useRef(null);
const isUnlocked = useSelector(getIsUnlocked);

const {
chainId,
// Used for network icon / dropdown
network: currentNetwork,
// Used for network icon / dropdown
isEvmNetwork,
} = useSelector(getMultichainNetwork);
const multichainNetwork = useSelector(getMultichainNetwork);
const { chainId, isEvmNetwork } = multichainNetwork;

const dispatch = useDispatch();

Expand Down Expand Up @@ -149,15 +144,15 @@ export const AppHeader = ({ location }) => {
<AppHeaderUnlockedContent
popupStatus={popupStatus}
isEvmNetwork={isEvmNetwork}
currentNetwork={currentNetwork}
currentNetwork={multichainNetwork}
networkOpenCallback={networkOpenCallback}
disableNetworkPicker={disableNetworkPicker}
disableAccountPicker={disableAccountPicker}
menuRef={menuRef}
/>
) : (
<AppHeaderLockedContent
currentNetwork={currentNetwork}
currentNetwork={multichainNetwork}
networkOpenCallback={networkOpenCallback}
/>
)}
Expand Down
58 changes: 56 additions & 2 deletions ui/components/multichain/app-header/app-header.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,29 @@ jest.mock('react-router-dom', () => ({

const render = ({
stateChanges = {},
provider = {},
networkConfigurations = {},
location = {},
isUnlocked = true,
} = {}) => {
const store = configureStore({
...mockState,
metamask: {
...mockState.metamask,
isUnlocked,
providerConfig: {
...mockState.metamask.providerConfig,
...(provider ?? {}),
},
networkConfigurations: {
...mockState.metamask.networkConfigurations,
...(networkConfigurations ?? {}),
},
isUnlocked: isUnlocked ?? true,
},
activeTab: {
origin: 'https://remix.ethereum.org',
},
...stateChanges,
...(stateChanges ?? {}),
});
return renderWithProvider(<AppHeader location={location} />, store);
};
Expand Down Expand Up @@ -175,4 +185,48 @@ describe('App Header', () => {
expect(connectionPickerButton).not.toBeInTheDocument();
});
});

describe('network picker', () => {
it('shows custom rpc if it has the same chainId as a default network', () => {
const mockProviderConfig = {
id: 'custom-rpc-localhost',
type: 'rpc',
ticker: 'ETH',
chainId: '0x1',
rpcUrl: 'https://localhost:8545',
nickname: 'Localhost',
};
const mockNetworkConfigurations = {
[mockProviderConfig.id]: mockProviderConfig,
};

const { getByText } = render({
provider: mockProviderConfig,
networkConfigurations: mockNetworkConfigurations,
isUnlocked: true,
});
expect(getByText(mockProviderConfig.nickname)).toBeInTheDocument();
});

it("shows rpc url as nickname if there isn't a nickname set", () => {
const mockProviderConfig = {
id: 'custom-rpc-localhost',
type: 'rpc',
ticker: 'ETH',
chainId: '0x1',
rpcUrl: 'https://localhost:8545',
nickname: null,
};
const mockNetworkConfigurations = {
[mockProviderConfig.id]: mockProviderConfig,
};

const { getByText } = render({
provider: mockProviderConfig,
networkConfigurations: mockNetworkConfigurations,
isUnlocked: true,
});
expect(getByText(mockProviderConfig.rpcUrl)).toBeInTheDocument();
});
});
});
Loading

0 comments on commit da6a204

Please sign in to comment.