Skip to content

Commit

Permalink
Merge branch 'develop' into 1061/report-false-positive-blockaid
Browse files Browse the repository at this point in the history
  • Loading branch information
blackdevelopa authored Oct 4, 2023
2 parents 05294a5 + 2e1ab26 commit 260bb19
Show file tree
Hide file tree
Showing 16 changed files with 199 additions and 14 deletions.
6 changes: 6 additions & 0 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -2395,6 +2395,7 @@ export default class MetamaskController extends EventEmitter {
assetsContractController,
backup,
approvalController,
phishingController,
} = this;

return {
Expand Down Expand Up @@ -2822,6 +2823,11 @@ export default class MetamaskController extends EventEmitter {
dismissNotifications: this.dismissNotifications.bind(this),
markNotificationsAsRead: this.markNotificationsAsRead.bind(this),
updateCaveat: this.updateCaveat.bind(this),
getPhishingResult: async (website) => {
await phishingController.maybeUpdateState();

return phishingController.test(website);
},
///: END:ONLY_INCLUDE_IN
///: BEGIN:ONLY_INCLUDE_IN(keyring-snaps)
updateSnapRegistry: this.preferencesController.updateSnapRegistry.bind(
Expand Down
35 changes: 34 additions & 1 deletion test/data/mock-state.json
Original file line number Diff line number Diff line change
Expand Up @@ -1407,7 +1407,40 @@
"requestState": { "test": "value" }
}
},
"pendingApprovalCount": 1
"pendingApprovalCount": 1,
"database": {
"verifiedSnaps": {
"npm:@metamask/test-snap-bip44": {
"id": "npm:@metamask/test-snap-bip44",
"metadata": {
"name": "BIP-44",
"author": {
"name": "Consensys",
"website": "https://consensys.io/"
},
"website": "https://snaps.consensys.io/",
"summary": "An example Snap that signs messages using BLS.",
"description": "An example Snap that signs messages using BLS.",
"audits": [
{
"auditor": "Consensys Diligence",
"report": "https://consensys.io/diligence/audits/"
}
],
"category": "interoperability",
"support": {
"contact": "https://github.com/MetaMask"
},
"sourceCode": "https://github.com/MetaMask/test-snaps"
},
"versions": {
"5.1.2": {
"checksum": "L1k+dT9Q+y3KfIqzaH09MpDZVPS9ZowEh9w01ZMTWMU="
}
}
}
}
}
},
"send": {
"amountMode": "INPUT",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getSnapPrefix } from '@metamask/snaps-utils';
import classnames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
AlignItems,
Expand All @@ -15,6 +15,7 @@ import {
FlexDirection,
FontWeight,
JustifyContent,
OverflowWrap,
TextColor,
TextVariant,
} from '../../../../helpers/constants/design-system';
Expand All @@ -25,8 +26,15 @@ import {
} from '../../../../helpers/utils/util';
import { useI18nContext } from '../../../../hooks/useI18nContext';
import { useOriginMetadata } from '../../../../hooks/useOriginMetadata';
import { getTargetSubjectMetadata } from '../../../../selectors';
import { disableSnap, enableSnap } from '../../../../store/actions';
import {
getSnapRegistryData,
getTargetSubjectMetadata,
} from '../../../../selectors';
import {
disableSnap,
enableSnap,
getPhishingResult,
} from '../../../../store/actions';
import { Box, ButtonLink, Text } from '../../../component-library';
import ToggleButton from '../../../ui/toggle-button';
import Tooltip from '../../../ui/tooltip/tooltip';
Expand All @@ -53,6 +61,24 @@ const SnapAuthorshipExpanded = ({ snapId, className, snap }) => {
const subjectMetadata = useSelector((state) =>
getTargetSubjectMetadata(state, snapId),
);
const snapRegistryData = useSelector((state) =>
getSnapRegistryData(state, snapId),
);
const { website = undefined } = snapRegistryData?.metadata ?? {};
const [safeWebsite, setSafeWebsite] = useState(null);

useEffect(() => {
const performPhishingCheck = async () => {
const phishingResult = await getPhishingResult(website);

if (!phishingResult.result) {
setSafeWebsite(website);
}
};
if (website) {
performPhishingCheck();
}
}, [website]);

const friendlyName = snapId && getSnapName(snapId, subjectMetadata);

Expand Down Expand Up @@ -134,6 +160,33 @@ const SnapAuthorshipExpanded = ({ snapId, className, snap }) => {
</Box>
</Box>
<Box padding={4} width={BlockSize.Full}>
{safeWebsite && (
<Box
display={Display.Flex}
flexDirection={FlexDirection.Row}
justifyContent={JustifyContent.spaceBetween}
width={BlockSize.Full}
marginBottom={4}
>
<Text variant={TextVariant.bodyMd} fontWeight={FontWeight.Medium}>
{t('snapDetailWebsite')}
</Text>
<Box
paddingLeft={8}
display={Display.Flex}
flexDirection={FlexDirection.Column}
alignItems={AlignItems.flexEnd}
>
<ButtonLink
href={installOrigin.origin}
target="_blank"
overflowWrap={OverflowWrap.Anywhere}
>
{safeWebsite}
</ButtonLink>
</Box>
</Box>
)}
{installOrigin && installInfo && (
<Box
display={Display.Flex}
Expand All @@ -149,9 +202,7 @@ const SnapAuthorshipExpanded = ({ snapId, className, snap }) => {
flexDirection={FlexDirection.Column}
alignItems={AlignItems.flexEnd}
>
<ButtonLink href={installOrigin.origin} target="_blank">
{installOrigin.host}
</ButtonLink>
<Text>{installOrigin.host}</Text>
<Text color={Color.textMuted}>
{t('installedOn', [
formatDate(installInfo.date, 'dd MMM yyyy'),
Expand Down
1 change: 1 addition & 0 deletions ui/pages/keyring-snaps/index.scss
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
@import "./snap-account-detail-page/snap-account-detail-page";
@import "./new-snap-account-page/new-snap-account-page";
@import "./snap-card/snap-card";
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Snap } from '@metamask/snaps-utils';
import React, { useState, useEffect } from 'react';
import { shallowEqual, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
import semver from 'semver';
import { Box, Text } from '../../../components/component-library';
import {
AlignItems,
Expand Down Expand Up @@ -116,11 +117,16 @@ export default function NewSnapAccountPage() {

const isInstalled = Boolean(foundSnap);

const updateAvailable = Boolean(
foundSnap?.version && semver.gt(snap.version, foundSnap.version),
);

return (
<SnapCard
{...snap}
key={index}
isInstalled={isInstalled}
updateAvailable={updateAvailable}
onClickFunc={() => {
history.push(`/add-snap-account/${snap.id}`);
}}
Expand Down
2 changes: 1 addition & 1 deletion ui/pages/keyring-snaps/snap-account-detail-page/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export const SnapDetailHeader = ({
<Box>
{isInstalled && updateAvailable && (
<Button
variant={ButtonVariant.Primary}
variant={ButtonVariant.Secondary}
marginRight={1}
onClick={() => {
setShowConfigPopoverType(ConfigureSnapPopupType.INSTALL);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ exports[`SnapCard should render 1`] = `
Secure your account with MetaMask Mobile
</h3>
<div
class="mm-box mm-box--display-flex mm-box--justify-content-space-between"
class="mm-box mm-box--margin-top-2 mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between mm-box--align-items-center"
>
<span
class="mm-box mm-icon mm-icon--size-md mm-box--margin-left-auto mm-box--display-inline-block mm-box--color-icon-alternative"
class="mm-box mm-icon mm-icon--size-xs mm-box--margin-left-auto mm-box--display-inline-block mm-box--color-icon-alternative"
data-testid="to-snap-detail"
style="mask-image: url('./images/icons/arrow-2-right.svg');"
/>
Expand Down
7 changes: 7 additions & 0 deletions ui/pages/keyring-snaps/snap-card/snap-card.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.configure-button {
&:hover {
& > * {
color: var(--color-primary-inverse);
}
}
}
9 changes: 9 additions & 0 deletions ui/pages/keyring-snaps/snap-card/snap-card.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,13 @@ describe('SnapCard', () => {
).toBeInTheDocument();
});
});

it('should show `Update Available` tag', () => {
const { getByText } = renderComponent({
...snap,
isInstalled: true,
updateAvailable: true,
});
expect(getByText(messages.snapUpdateAvailable.message)).toBeInTheDocument();
});
});
27 changes: 25 additions & 2 deletions ui/pages/keyring-snaps/snap-card/snap-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Icon,
IconName,
Text,
IconSize,
} from '../../../components/component-library';
import {
AlignItems,
Expand All @@ -31,13 +32,14 @@ export default function SnapCard({
snapTitle,
snapSlug,
isInstalled,
updateAvailable,
website,
id,
onClickFunc,
}: Pick<
SnapCardProps,
'iconUrl' | 'snapTitle' | 'snapSlug' | 'isInstalled' | 'website' | 'id'
> & { onClickFunc: () => void }) {
> & { onClickFunc: () => void; updateAvailable: boolean }) {
const t = useI18nContext();
const history = useHistory();
const [showConfigPopover, setShowConfigPopover] = useState(false);
Expand Down Expand Up @@ -90,11 +92,20 @@ export default function SnapCard({
</Box>
{isInstalled ? (
<Button
className="configure-button"
data-testid="configure-snap-button"
variant={ButtonVariant.Secondary}
onClick={() => setShowConfigPopover(true)}
>
{t('snapConfigure')}
<Icon
as="span"
marginLeft={2}
name={IconName.Arrow2UpRight}
style={{
verticalAlign: 'middle',
}}
/>
</Button>
) : (
<Button
Expand All @@ -119,11 +130,23 @@ export default function SnapCard({
{snapSlug}
</Text>

<Box display={Display.Flex} justifyContent={JustifyContent.spaceBetween}>
<Box
display={Display.Flex}
flexDirection={FlexDirection.Row}
justifyContent={JustifyContent.spaceBetween}
alignItems={AlignItems.center}
marginTop={2}
>
{updateAvailable && (
<Text color={TextColor.textAlternative}>
{t('snapUpdateAvailable')}
</Text>
)}
<Icon
data-testid="to-snap-detail"
name={IconName.Arrow2Right}
color={IconColor.iconAlternative}
size={IconSize.Xs}
onClick={onClickFunc}
marginLeft="auto"
/>
Expand Down
6 changes: 5 additions & 1 deletion ui/pages/settings/snaps/snaps-list-tab/snap-list-tab.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,11 @@ const SnapListTab = () => {
>
<ButtonLink
size={Size.auto}
href="https://metamask.io/snaps/"
href={
snapsList.length > 0
? 'https://snaps.metamask.io/'
: 'https://metamask.io/snaps/'
}
target="_blank"
endIconName={IconName.Export}
>
Expand Down
1 change: 0 additions & 1 deletion ui/pages/settings/snaps/view-snap/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@

&__subject-name {
font-size: 14px;
color: var(--color-primary-default);
}
}
}
12 changes: 12 additions & 0 deletions ui/pages/settings/snaps/view-snap/view-snap.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { waitFor, screen } from '@testing-library/react';
import { renderWithProvider } from '../../../../../test/lib/render-helpers';
import mockState from '../../../../../test/data/mock-state.json';
import ViewSnap from './view-snap';
Expand All @@ -12,6 +13,11 @@ jest.mock('../../../../store/actions.ts', () => {
removeSnap: jest.fn(),
removePermissionsFor: jest.fn(),
updateCaveat: jest.fn(),
getPhishingResult: jest.fn().mockImplementation(() => {
return {
result: false,
};
}),
};
});

Expand Down Expand Up @@ -45,6 +51,12 @@ describe('ViewSnap', () => {
expect(
getByText('An example Snap that signs messages using BLS.'),
).toBeDefined();
// Snap website
await waitFor(() => {
const websiteElement = screen.queryByText('https://snaps.consensys.io/');
expect(websiteElement).toBeDefined();
expect(getByText('https://snaps.consensys.io/')).toBeDefined();
});
// Snap version info
expect(getByText('5.1.2')).toBeDefined();
// Enable Snap
Expand Down
12 changes: 12 additions & 0 deletions ui/selectors/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,18 @@ export function getTargetSubjectMetadata(state, origin) {
return metadata;
}

/**
* Retrieve registry data for requested Snap.
*
* @param state - Redux state object.
* @param snapId - ID of a Snap.
* @returns Object containing metadata stored in Snaps registry for requested Snap.
*/
export function getSnapRegistryData(state, snapId) {
const snapsRegistryData = state.metamask.database.verifiedSnaps;
return snapsRegistryData ? snapsRegistryData[snapId] : null;
}

export function getRpcPrefsForCurrentProvider(state) {
const { rpcPrefs } = getProviderConfig(state);
return rpcPrefs || {};
Expand Down
Loading

0 comments on commit 260bb19

Please sign in to comment.