Skip to content
Merged
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
32 changes: 23 additions & 9 deletions src/entries/popup/pages/messages/DappScanStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,17 @@ import { motion } from 'framer-motion';
import { DAppStatus } from '~/core/graphql/__generated__/metadata';
import { i18n } from '~/core/languages';
import { Box, Inline, Stack, Symbol, Text } from '~/design-system';
import { SymbolName } from '~/design-system/styles/designTokens';

export function ThisDappIsLikelyMalicious() {
export function MaliciousRequestWarning({
symbol,
title,
description,
}: {
symbol: SymbolName;
title: string;
description: string;
}) {
return (
<Box
as={motion.div}
Expand All @@ -21,24 +30,29 @@ export function ThisDappIsLikelyMalicious() {
borderRadius="20px"
borderWidth="2px"
>
<Symbol
symbol="exclamationmark.octagon.fill"
size={20}
weight="heavy"
color="red"
/>
<Symbol symbol={symbol} size={20} weight="heavy" color="red" />
<Stack space="8px">
<Text size="14pt" weight="bold">
{i18n.t('approve_request.malicious_warning.title')}
{title}
</Text>
<Text color="labelTertiary" size="12pt" weight="semibold">
{i18n.t('approve_request.malicious_warning.message')}
{description}
</Text>
</Stack>
</Box>
);
}

export function ThisDappIsLikelyMalicious() {
return (
<MaliciousRequestWarning
symbol="exclamationmark.octagon.fill"
title={i18n.t('approve_request.malicious_warning.title')}
description={i18n.t('approve_request.malicious_warning.message')}
/>
);
}

const VerifiedBadge = ({ size = 17 }: { size?: number }) => (
<Symbol size={size} symbol="checkmark.seal.fill" weight="bold" color="blue" />
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,48 +28,45 @@ export const RequestAccountsInfo = ({
paddingHorizontal="50px"
paddingTop="64px"
background="surfacePrimaryElevatedSecondary"
display="flex"
flexDirection="column"
alignItems="center"
gap="26px"
>
<Box width="full">
<Inline alignHorizontal="center" alignVertical="center">
<DappIcon appLogo={appLogo} size="60px" />
</Inline>
</Box>
<Stack space="32px">
<Box width="full">
<Inline alignHorizontal="center" alignVertical="center">
<DappIcon appLogo={appLogo} size="60px" />
</Inline>
</Box>
<Stack space="32px">
<Text
size="20pt"
weight="semibold"
color="labelSecondary"
align="center"
>
<TextInline color="label">{appName}</TextInline>{' '}
{i18n.t('approve_request.wallet_info_title')}
</Text>
<Text
size="20pt"
weight="semibold"
color="labelSecondary"
align="center"
>
<TextInline color="label">{appName}</TextInline>{' '}
{i18n.t('approve_request.wallet_info_title')}
</Text>

<DappHostName hostName={appHostName} dappStatus={dappStatus} />
</Stack>
<DappHostName hostName={appHostName} dappStatus={dappStatus} />
</Stack>

<Box style={{ width: '186px' }} marginVertical="-4px">
<Separator color="separatorTertiary" />
</Box>
<Box style={{ width: '186px' }} marginVertical="-4px">
<Separator color="separatorTertiary" />
</Box>

{isScamDapp ? (
<Bleed horizontal="30px">
<ThisDappIsLikelyMalicious />
</Bleed>
) : (
<Text
align="center"
color="labelTertiary"
size="14pt"
weight="regular"
>
{i18n.t('approve_request.wallet_info_description', {
appName,
})}
</Text>
)}
</Stack>
{isScamDapp ? (
<Bleed horizontal="30px">
<ThisDappIsLikelyMalicious />
</Bleed>
) : (
<Text align="center" color="labelTertiary" size="14pt" weight="regular">
{i18n.t('approve_request.wallet_info_description', {
appName,
})}
</Text>
)}
</Box>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { ROUTES } from '~/entries/popup/urls';

import {
DappHostName,
ThisDappIsLikelyMalicious,
MaliciousRequestWarning,
getDappStatusBadge,
} from '../DappScanStatus';
import { SimulationOverview } from '../Simulation';
Expand Down Expand Up @@ -292,26 +292,39 @@ function TransactionInfo({
const tabLabel = (tab: string) => i18n.t(tab, { scope: 'simulation.tabs' });

return (
<Tabs
tabs={[tabLabel('overview'), tabLabel('details'), tabLabel('data')]}
expanded={expanded}
onExpand={onExpand}
>
<TabContent value={tabLabel('overview')}>
<Overview
simulation={simulation}
status={status === 'error' && isRefetching ? 'loading' : status}
error={error}
metadata={dappMetadata}
<>
<Tabs
tabs={[tabLabel('overview'), tabLabel('details'), tabLabel('data')]}
expanded={expanded}
onExpand={onExpand}
>
<TabContent value={tabLabel('overview')}>
<Overview
simulation={simulation}
status={status === 'error' && isRefetching ? 'loading' : status}
error={error}
metadata={dappMetadata}
/>
</TabContent>
<TabContent value={tabLabel('details')}>
<TransactionDetails
session={activeSession!}
simulation={simulation}
/>
</TabContent>
<TabContent value={tabLabel('data')}>
<TransactionData data={txData} expanded={expanded} />
</TabContent>
</Tabs>

{!expanded && simulation && simulation.scanning.result !== 'OK' && (
<MaliciousRequestWarning
title={i18n.t('approve_request.malicious_transaction_warning.title')}
description={simulation.scanning.description}
symbol="exclamationmark.octagon.fill"
/>
</TabContent>
<TabContent value={tabLabel('details')}>
<TransactionDetails session={activeSession!} simulation={simulation} />
</TabContent>
<TabContent value={tabLabel('data')}>
<TransactionData data={txData} expanded={expanded} />
</TabContent>
</Tabs>
)}
</>
);
}

Expand Down Expand Up @@ -553,8 +566,6 @@ export function SendTransactionInfo({
/>
)
)}

{!expanded && isScamDapp && <ThisDappIsLikelyMalicious />}
</Box>
);
}
11 changes: 8 additions & 3 deletions src/entries/popup/pages/messages/Simulation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { formatNumber } from '~/core/utils/formatNumber';
import { Inline, Stack, Symbol, Text } from '~/design-system';
import { TextColor } from '~/design-system/styles/designTokens';

import { CoinIcon } from '../../components/CoinIcon/CoinIcon';
import { CoinIcon, NFTIcon } from '../../components/CoinIcon/CoinIcon';
import { Spinner } from '../../components/Spinner/Spinner';

import {
Expand Down Expand Up @@ -53,7 +53,11 @@ function SimulatedChangeRow({
</Text>
</Inline>
<Inline space="6px" alignVertical="center">
<CoinIcon asset={asset} size={14} />
{asset?.type === 'nft' ? (
<NFTIcon asset={asset} size={16} />
) : (
<CoinIcon asset={asset} size={14} />
)}
<Text size="14pt" weight="bold" color={color}>
{quantity === 'UNLIMITED'
? i18n.t('approvals.unlimited')
Expand All @@ -74,6 +78,7 @@ export function SimulationOverview({
status: 'loading' | 'error' | 'success';
error: SimulationError | null;
}) {
const isMalicious = simulation?.scanning.result !== 'OK';
return (
<>
{status === 'loading' && (
Expand Down Expand Up @@ -146,7 +151,7 @@ export function SimulationOverview({
size={14}
symbol="checkmark.seal.fill"
weight="bold"
color="blue"
color={isMalicious ? 'red' : 'blue'}
/>
}
label={i18n.t('simulation.approved')}
Expand Down
28 changes: 25 additions & 3 deletions src/entries/popup/pages/messages/useSimulateTransaction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Address } from 'wagmi';

import { metadataPostClient } from '~/core/graphql';
import { Transaction } from '~/core/graphql/__generated__/metadata';
import { i18n } from '~/core/languages';
import { createQueryKey } from '~/core/react-query';
import { currentCurrencyStore } from '~/core/state';
import { AddressOrEth, ParsedAsset } from '~/core/types/assets';
Expand Down Expand Up @@ -42,6 +43,20 @@ const parseSimulationAsset = (asset: SimulationAsset, chainId: ChainId) => {
});
};

const parseScanningDescription = (description: Lowercase<string>) => {
const t = (tab: string) =>
i18n.t(tab, { scope: 'approve_request.malicious_transaction_warning' });

if (description.includes('losing trade, mint price is too high'))
return t('minting_is_a_losing_trade');

if (description.includes('malicious address')) return t('malicious_address');

if (description.includes('malicious entity')) return t('malicious_entity');

return t('you_can_lose_everything');
};

export const useSimulateTransaction = ({
chainId,
transaction,
Expand All @@ -64,12 +79,18 @@ export const useSimulateTransaction = ({
domain,
})) as TransactionSimulationResponse;

const { simulation, error } = response.simulateTransactions[0];
const { simulation, error, scanning } = response.simulateTransactions[0];

if (error) throw error.type;

return {
chainId,
scanning: {
result: scanning.result,
description: parseScanningDescription(
scanning.description.toLowerCase() as Lowercase<string>,
),
},
in: simulation.in.map(({ asset, quantity }) => ({
quantity,
asset: parseSimulationAsset(asset, chainId),
Expand Down Expand Up @@ -102,6 +123,7 @@ export type TransactionSimulation = {
quantityAllowed: 'UNLIMITED' | (string & {});
quantityAtRisk: string;
}[];
scanning: TransactionSimulationResponse['simulateTransactions'][0]['scanning'];
meta: SimulationMeta;
hasChanges: boolean;
chainId: ChainId;
Expand Down Expand Up @@ -149,8 +171,8 @@ type TransactionSimulationResponse = {
simulateTransactions: [
{
scanning: {
result: 'OK';
description: '';
result: 'OK' | 'WARNING' | 'MALICIOUS';
description: string;
};
error: {
message: string;
Expand Down
8 changes: 7 additions & 1 deletion static/json/languages/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,13 @@
"title": "This app is likely malicious",
"message": "Signing messages or transactions from this app could result in losing your assets"
},
"malicious_transaction_warning": {
"title": "This transaction looks suspicious",
"malicious_address": "A malicious address is involved in this transaction. Signing may result in losses",
"malicious_entity": "A malicious entity is involved in this transaction. Signing may result in losses",
"minting_is_a_losing_trade": "A scam contract is involved in this transaction. Minting is a losing trade",
"you_can_lose_everything": "Signing this transaction could result in losing access to everything in your wallet"
},
"dangerous_request": "Dangerous Request",
"message_signing_request": "Message Signing Request",
"message": "Message",
Expand Down Expand Up @@ -1518,4 +1525,3 @@
"not_found": "We couldn't find this asset on the selected network. Please choose the right network below"
}
}