Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New BlockaidBannerAlert component #20051

Merged
merged 7 commits into from
Jul 24, 2023
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
24 changes: 24 additions & 0 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions shared/constants/security-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,42 @@ export const SECURITY_PROVIDER_CONFIG: Readonly<SecurityProviderConfig> = {
},
};

/** The reason, also referred to as the attack type, provided in the PPOM Response */
export enum BlockaidReason {
/** Approval for a malicious spender */
approvalFarming = 'approval_farming',
/** Malicious signature on Blur order */
blurFarming = 'blur_farming',
/** A known malicous site invoked that transaction */
maliciousDomain = 'malicious_domain',
/** Malicious signature on a Permit order */
permitFarming = 'permit_farming',
/** Direct theft of native assets (ETH/MATIC/AVAX/ etc …) */
rawNativeTokenTransfer = 'raw_native_token_transfer',
/** Malicious raw signature from the user */
rawSignatureFarming = 'raw_signature_farming',
/** Malicious signature on a Seaport order */
seaportFarming = 'seaport_farming',
/** setApprovalForAll for a malicious operator */
setApprovalForAll = 'set_approval_for_all',
/** Malicious signature on other type of trade order (Zero-X / Rarible / etc..) */
tradeOrderFarming = 'trade_order_farming',
/** Direct theft of assets using transfer */
transferFarming = 'transfer_farming',
/** Direct theft of assets using transferFrom */
transferFromFarming = 'transfer_from_farming',
/** Malicious trade that results in the victim being rained */
unfairTrade = 'unfair_trade',

other = 'other',
}

export enum BlockaidResultType {
Malicious = 'Malicious',
Warning = 'Warning',
Benign = 'Benign',
}

/**
* @typedef {object} SecurityProviderMessageSeverity
* @property {0} NOT_MALICIOUS - Indicates message is not malicious
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Blockaid Banner Alert should render 'danger' UI when ppomResponse.resultType is 'Malicious 1`] = `
<div
class="box mm-banner-base mm-banner-alert mm-banner-alert--severity-danger box--margin-top-4 box--margin-right-4 box--margin-left-4 box--padding-3 box--padding-left-2 box--display-flex box--gap-2 box--flex-direction-row box--background-color-error-muted box--rounded-sm"
>
<span
class="box mm-icon mm-icon--size-lg box--display-inline-block box--flex-direction-row box--color-error-default"
style="mask-image: url('./images/icons/danger.svg');"
/>
<div>
<h5
class="mm-box mm-text mm-banner-base__title mm-text--body-lg-medium mm-box--color-text-default"
data-testid="mm-banner-base-title"
>
This is a deceptive request
</h5>
<p
class="mm-box mm-text mm-text--body-md mm-box--margin-top-2 mm-box--color-text-default"
>
If you approve this request, a third party known for scams might take all your assets.
</p>
<p
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-2 mm-box--align-items-center mm-box--color-text-alternative"
>
<span
class="box disclosure__summary--icon mm-icon mm-icon--size-sm box--margin-inline-end-1 box--display-inline-block box--flex-direction-row box--color-primary-default"
style="mask-image: url('./images/icons/security-tick.svg');"
/>
<span>

Security advice by
<a
class="mm-box mm-text mm-button-base mm-button-link mm-button-link--size-inherit mm-text--body-md-medium mm-box--padding-right-0 mm-box--padding-left-0 mm-box--display-inline-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-primary-default mm-box--background-color-transparent"
href="https://blockaid.io/"
rel="noopener noreferrer"
target="_blank"
>
Blockaid
</a>


</span>
</p>
</div>
</div>
`;

exports[`Blockaid Banner Alert should render 'warning' UI when ppomResponse.resultType is 'Warning 1`] = `
<div
class="box mm-banner-base mm-banner-alert mm-banner-alert--severity-warning box--margin-top-4 box--margin-right-4 box--margin-left-4 box--padding-3 box--padding-left-2 box--display-flex box--gap-2 box--flex-direction-row box--background-color-warning-muted box--rounded-sm"
>
<span
class="box mm-icon mm-icon--size-lg box--display-inline-block box--flex-direction-row box--color-warning-default"
style="mask-image: url('./images/icons/warning.svg');"
/>
<div>
<h5
class="mm-box mm-text mm-banner-base__title mm-text--body-lg-medium mm-box--color-text-default"
data-testid="mm-banner-base-title"
>
This is a deceptive request
</h5>
<p
class="mm-box mm-text mm-text--body-md mm-box--margin-top-2 mm-box--color-text-default"
>
If you approve this request, a third party known for scams might take all your assets.
</p>
<p
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-2 mm-box--align-items-center mm-box--color-text-alternative"
>
<span
class="box disclosure__summary--icon mm-icon mm-icon--size-sm box--margin-inline-end-1 box--display-inline-block box--flex-direction-row box--color-primary-default"
style="mask-image: url('./images/icons/security-tick.svg');"
/>
<span>

Security advice by
<a
class="mm-box mm-text mm-button-base mm-button-link mm-button-link--size-inherit mm-text--body-md-medium mm-box--padding-right-0 mm-box--padding-left-0 mm-box--display-inline-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-primary-default mm-box--background-color-transparent"
href="https://blockaid.io/"
rel="noopener noreferrer"
target="_blank"
>
Blockaid
</a>


</span>
</p>
</div>
</div>
`;

exports[`Blockaid Banner Alert should render details when provided 1`] = `
<div>
<div
class="box mm-banner-base mm-banner-alert mm-banner-alert--severity-warning box--margin-top-4 box--margin-right-4 box--margin-left-4 box--padding-3 box--padding-left-2 box--display-flex box--gap-2 box--flex-direction-row box--background-color-warning-muted box--rounded-sm"
>
<span
class="box mm-icon mm-icon--size-lg box--display-inline-block box--flex-direction-row box--color-warning-default"
style="mask-image: url('./images/icons/warning.svg');"
/>
<div>
<h5
class="mm-box mm-text mm-banner-base__title mm-text--body-lg-medium mm-box--color-text-default"
data-testid="mm-banner-base-title"
>
This is a deceptive request
</h5>
<p
class="mm-box mm-text mm-text--body-md mm-box--margin-top-2 mm-box--color-text-default"
>
If you approve this request, a third party known for scams might take all your assets.
</p>
<div
class="disclosure"
>
<details>
<summary
class="disclosure__summary is-arrow"
>
<p
class="mm-box mm-text mm-text--body-md mm-box--color-primary-default"
>
See details
</p>
<span
class="box disclosure__summary--icon mm-icon mm-icon--size-sm box--margin-inline-start-2 box--display-inline-block box--flex-direction-row box--color-primary-default"
style="mask-image: url('./images/icons/arrow-up.svg');"
/>
</summary>
<div
class="disclosure__content normal"
>
<ul
class="mm-box mm-text mm-text--body-md mm-box--color-text-default"
>
<li>
Operator is an EOA
</li>
<li>
Operator is untrusted according to previous activity
</li>
</ul>
</div>
<div
class="disclosure__footer"
/>
</details>
</div>
<p
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-2 mm-box--align-items-center mm-box--color-text-alternative"
>
<span
class="box disclosure__summary--icon mm-icon mm-icon--size-sm box--margin-inline-end-1 box--display-inline-block box--flex-direction-row box--color-primary-default"
style="mask-image: url('./images/icons/security-tick.svg');"
/>
<span>

Security advice by
<a
class="mm-box mm-text mm-button-base mm-button-link mm-button-link--size-inherit mm-text--body-md-medium mm-box--padding-right-0 mm-box--padding-left-0 mm-box--display-inline-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-primary-default mm-box--background-color-transparent"
href="https://blockaid.io/"
rel="noopener noreferrer"
target="_blank"
>
Blockaid
</a>


</span>
</p>
</div>
</div>
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { captureException } from '@sentry/browser';

import { Text } from '../../../component-library';
import { Severity } from '../../../../helpers/constants/design-system';
import { I18nContext } from '../../../../contexts/i18n';

import {
BlockaidReason,
BlockaidResultType,
SecurityProvider,
} from '../../../../../shared/constants/security-provider';
import SecurityProviderBannerAlert from '../security-provider-banner-alert';

/** Reason to description translation key mapping. Grouped by translations. */
const REASON_TO_DESCRIPTION_TKEY = Object.freeze({
[BlockaidReason.approvalFarming]: 'blockaidDescriptionApproveFarming',
[BlockaidReason.permitFarming]: 'blockaidDescriptionApproveFarming',
[BlockaidReason.setApprovalForAll]: 'blockaidDescriptionApproveFarming',

[BlockaidReason.blurFarming]: 'blockaidDescriptionBlurFarming',

[BlockaidReason.seaportFarming]: 'blockaidDescriptionSeaportFarming',

[BlockaidReason.maliciousDomain]: 'blockaidDescriptionMaliciousDomain',

[BlockaidReason.rawSignatureFarming]: 'blockaidDescriptionMightLoseAssets',
[BlockaidReason.tradeOrderFarming]: 'blockaidDescriptionMightLoseAssets',
[BlockaidReason.unfairTrade]: 'blockaidDescriptionMightLoseAssets',

[BlockaidReason.rawNativeTokenTransfer]: 'blockaidDescriptionTransferFarming',
[BlockaidReason.transferFarming]: 'blockaidDescriptionTransferFarming',
[BlockaidReason.transferFromFarming]: 'blockaidDescriptionTransferFarming',

[BlockaidReason.other]: 'blockaidDescriptionMightLoseAssets',
});

/** List of suspicious reason(s). Other reasons will be deemed as deceptive. */
const SUSPCIOUS_REASON = [BlockaidReason.rawSignatureFarming];

function BlockaidBannerAlert({
ppomResponse: { reason, resultType, features },
}) {
const t = useContext(I18nContext);

if (resultType === BlockaidResultType.Benign) {
return null;
}

if (!REASON_TO_DESCRIPTION_TKEY[reason]) {
captureException(`BlockaidBannerAlert: Unidentified reason '${reason}'`);
}

const description = t(REASON_TO_DESCRIPTION_TKEY[reason] || 'other');

const details = Boolean(features?.length) && (
<Text as="ul">
{features.map((feature, i) => (
<li key={`blockaid-detail-${i}`}>• {feature}</li>
))}
</Text>
);

const severity =
resultType === BlockaidResultType.Malicious
? Severity.Danger
: Severity.Warning;

const title =
SUSPCIOUS_REASON.indexOf(reason) > -1
? t('blockaidTitleSuspicious')
: t('blockaidTitleDeceptive');

return (
<SecurityProviderBannerAlert
description={description}
details={details}
provider={SecurityProvider.Blockaid}
severity={severity}
title={title}
/>
);
}

BlockaidBannerAlert.propTypes = {
ppomResponse: PropTypes.object,
};

export default BlockaidBannerAlert;
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import {
BlockaidReason,
BlockaidResultType,
} from '../../../../../shared/constants/security-provider';
import BlockaidBannerAlert from '.';

const mockFeatures = [
'Operator is an EOA',
'Operator is untrusted according to previous activity',
];

export default {
title: 'Components/App/SecurityProviderBannerAlert/BlockaidBannerAlert',
argTypes: {
features: {
control: 'array',
description:
'ppomResponse.features value which is a list displayed as SecurityProviderBannerAlert details',
},
reason: {
control: 'select',
options: Object.values(BlockaidReason),
description: 'ppomResponse.reason value',
},
resultType: {
control: 'select',
options: Object.values(BlockaidResultType),
description: 'ppomResponse.resultType value',
},
},
args: {
features: mockFeatures,
reason: BlockaidReason.setApprovalForAll,
resultType: BlockaidResultType.Warning,
},
};

export const DefaultStory = (args) => (
<BlockaidBannerAlert ppomResponse={args} />
);
DefaultStory.storyName = 'Default';
Loading