From f7aacab664dbafbf0b45dbf1b2b0e61d7c2b0753 Mon Sep 17 00:00:00 2001 From: isstuev Date: Wed, 29 Nov 2023 11:49:31 +0100 Subject: [PATCH 1/7] remove token info from instance --- mocks/tokens/tokenInstance.ts | 2 - stubs/token.ts | 1 - types/api/token.ts | 1 - ui/pages/Token.tsx | 2 +- ui/pages/TokenInstance.tsx | 42 +++++++++++++------- ui/token/TokenInventory.pw.tsx | 6 +++ ui/token/TokenInventory.tsx | 15 +++++-- ui/token/TokenInventoryItem.tsx | 10 ++--- ui/tokenInstance/TokenInstanceDetails.pw.tsx | 9 +++-- ui/tokenInstance/TokenInstanceDetails.tsx | 13 +++--- 10 files changed, 63 insertions(+), 38 deletions(-) diff --git a/mocks/tokens/tokenInstance.ts b/mocks/tokens/tokenInstance.ts index b28361868f..4173c0a609 100644 --- a/mocks/tokens/tokenInstance.ts +++ b/mocks/tokens/tokenInstance.ts @@ -2,7 +2,6 @@ import type { TokenInstance } from 'types/api/token'; import * as addressMock from '../address/address'; -import { tokenInfoERC721a } from './tokenInfo'; export const base: TokenInstance = { animation_url: null, @@ -74,7 +73,6 @@ export const base: TokenInstance = { name: 'GENESIS #188848, 22a5f8bbb1602995. Blockchain pixel PFP NFT + "on music video" trait inspired by God', }, owner: addressMock.withName, - token: tokenInfoERC721a, }; export const withRichMetadata: TokenInstance = { diff --git a/stubs/token.ts b/stubs/token.ts index 30b8b487bf..e60e004bad 100644 --- a/stubs/token.ts +++ b/stubs/token.ts @@ -108,6 +108,5 @@ export const TOKEN_INSTANCE: TokenInstance = { name: 'GENESIS #188882, 8a77ca1bcaa4036f. Blockchain pixel PFP NFT + "on music video" trait inspired by God', }, owner: ADDRESS_PARAMS, - token: TOKEN_INFO_ERC_1155, holder_address_hash: ADDRESS_HASH, }; diff --git a/types/api/token.ts b/types/api/token.ts index ebc5198d92..681dde2075 100644 --- a/types/api/token.ts +++ b/types/api/token.ts @@ -61,7 +61,6 @@ export interface TokenInstance { external_app_url: string | null; metadata: Record | null; owner: AddressParam | null; - token: TokenInfo; } export interface TokenInstanceTransfersCount { diff --git a/ui/pages/Token.tsx b/ui/pages/Token.tsx index a2e3dd8c58..18e9f2dd05 100644 --- a/ui/pages/Token.tsx +++ b/ui/pages/Token.tsx @@ -174,7 +174,7 @@ const TokenPageContent = () => { const tabs: Array = [ (tokenQuery.data?.type === 'ERC-1155' || tokenQuery.data?.type === 'ERC-721') ? - { id: 'inventory', title: 'Inventory', component: } : + { id: 'inventory', title: 'Inventory', component: } : undefined, { id: 'token_transfers', title: 'Token transfers', component: }, { id: 'holders', title: 'Holders', component: }, diff --git a/ui/pages/TokenInstance.tsx b/ui/pages/TokenInstance.tsx index 63fadd075b..38e938e504 100644 --- a/ui/pages/TokenInstance.tsx +++ b/ui/pages/TokenInstance.tsx @@ -10,7 +10,7 @@ import { useAppContext } from 'lib/contexts/app'; import useIsMobile from 'lib/hooks/useIsMobile'; import * as metadata from 'lib/metadata'; import * as regexp from 'lib/regexp'; -import { TOKEN_INSTANCE } from 'stubs/token'; +import { TOKEN_INSTANCE, TOKEN_INFO_ERC_1155 } from 'stubs/token'; import * as tokenStubs from 'stubs/token'; import { generateListStub } from 'stubs/utils'; import AddressQrCode from 'ui/address/details/AddressQrCode'; @@ -43,6 +43,14 @@ const TokenInstanceContent = () => { const scrollRef = React.useRef(null); + const tokenQuery = useApiQuery('token', { + pathParams: { hash }, + queryOptions: { + enabled: Boolean(hash && id), + placeholderData: TOKEN_INFO_ERC_1155, + }, + }); + const tokenInstanceQuery = useApiQuery('token_instance', { pathParams: { hash, id }, queryOptions: { @@ -58,14 +66,18 @@ const TokenInstanceContent = () => { options: { enabled: Boolean(hash && id && (!tab || tab === 'token_transfers') && !tokenInstanceQuery.isPlaceholderData && tokenInstanceQuery.data), placeholderData: generateListStub<'token_instance_transfers'>( - tokenInstanceQuery.data?.token.type === 'ERC-1155' ? tokenStubs.TOKEN_TRANSFER_ERC_1155 : tokenStubs.TOKEN_TRANSFER_ERC_721, + tokenQuery.data?.type === 'ERC-1155' ? tokenStubs.TOKEN_TRANSFER_ERC_1155 : tokenStubs.TOKEN_TRANSFER_ERC_721, 10, { next_page_params: null }, ), }, }); - const shouldFetchHolders = !tokenInstanceQuery.isPlaceholderData && tokenInstanceQuery.data && !tokenInstanceQuery.data.is_unique; + const shouldFetchHolders = + !tokenQuery.isPlaceholderData && + !tokenInstanceQuery.isPlaceholderData && + tokenInstanceQuery.data && + !tokenInstanceQuery.data.is_unique; const holdersQuery = useQueryWithPages({ resourceName: 'token_instance_holders', @@ -74,18 +86,18 @@ const TokenInstanceContent = () => { options: { enabled: Boolean(hash && tab === 'holders' && shouldFetchHolders), placeholderData: generateListStub<'token_instance_holders'>( - tokenInstanceQuery.data?.token.type === 'ERC-1155' ? tokenStubs.TOKEN_HOLDER_ERC_1155 : tokenStubs.TOKEN_HOLDER_ERC_20, 10, { next_page_params: null }), + tokenQuery.data?.type === 'ERC-1155' ? tokenStubs.TOKEN_HOLDER_ERC_1155 : tokenStubs.TOKEN_HOLDER_ERC_20, 10, { next_page_params: null }), }, }); React.useEffect(() => { - if (tokenInstanceQuery.data && !tokenInstanceQuery.isPlaceholderData) { + if (tokenInstanceQuery.data && !tokenInstanceQuery.isPlaceholderData && tokenQuery.data && !tokenQuery.isPlaceholderData) { metadata.update( - { pathname: '/token/[hash]/instance/[id]', query: { hash: tokenInstanceQuery.data.token.address, id: tokenInstanceQuery.data.id } }, - { symbol: tokenInstanceQuery.data.token.symbol ?? '' }, + { pathname: '/token/[hash]/instance/[id]', query: { hash: tokenQuery.data.address, id: tokenInstanceQuery.data.id } }, + { symbol: tokenQuery.data.symbol ?? '' }, ); } - }, [ tokenInstanceQuery.data, tokenInstanceQuery.isPlaceholderData ]); + }, [ tokenInstanceQuery.data, tokenInstanceQuery.isPlaceholderData, tokenQuery.data, tokenQuery.isPlaceholderData ]); const backLink = React.useMemo(() => { const hasGoBackLink = appProps.referrer && appProps.referrer.includes(`/token/${ hash }`) && !appProps.referrer.includes('instance'); @@ -104,10 +116,10 @@ const TokenInstanceContent = () => { { id: 'token_transfers', title: 'Token transfers', - component: , + component: , }, shouldFetchHolders ? - { id: 'holders', title: 'Holders', component: } : + { id: 'holders', title: 'Holders', component: } : undefined, { id: 'metadata', title: 'Metadata', component: ( { throw Error('Token instance fetch failed', { cause: tokenInstanceQuery.error }); } - const tokenTag = { tokenInstanceQuery.data?.token.type }; + const tokenTag = { tokenQuery.data?.type }; const address = { hash: hash || '', @@ -131,7 +143,7 @@ const TokenInstanceContent = () => { watchlist_address_id: null, }; - const isLoading = tokenInstanceQuery.isPlaceholderData; + const isLoading = tokenInstanceQuery.isPlaceholderData || tokenQuery.isPlaceholderData; const appLink = (() => { if (!tokenInstanceQuery.data?.external_app_url) { @@ -168,7 +180,7 @@ const TokenInstanceContent = () => { const titleSecondRow = ( { w="auto" maxW="700px" /> - { !isLoading && tokenInstanceQuery.data && } + { !isLoading && tokenInstanceQuery.data && } { appLink } @@ -197,7 +209,7 @@ const TokenInstanceContent = () => { isLoading={ isLoading } /> - + { /* should stay before tabs to scroll up with pagination */ } diff --git a/ui/token/TokenInventory.pw.tsx b/ui/token/TokenInventory.pw.tsx index 053ad772b8..d7b75dee28 100644 --- a/ui/token/TokenInventory.pw.tsx +++ b/ui/token/TokenInventory.pw.tsx @@ -2,6 +2,7 @@ import { Box } from '@chakra-ui/react'; import { test, expect } from '@playwright/experimental-ct-react'; import React from 'react'; +import { tokenInfoERC721a } from 'mocks/tokens/tokenInfo'; import { base as tokenInstanse } from 'mocks/tokens/tokenInstance'; import TestApp from 'playwright/TestApp'; @@ -23,6 +24,11 @@ test('base view +@mobile', async({ mount }) => { // @ts-ignore: pagination: { page: 1, isVisible: true }, }} + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore: + tokenQuery={{ + data: tokenInfoERC721a, + }} /> , ); diff --git a/ui/token/TokenInventory.tsx b/ui/token/TokenInventory.tsx index 36c17612bf..2a99a5e828 100644 --- a/ui/token/TokenInventory.tsx +++ b/ui/token/TokenInventory.tsx @@ -1,6 +1,10 @@ import { Grid } from '@chakra-ui/react'; +import type { UseQueryResult } from '@tanstack/react-query'; import React from 'react'; +import type { TokenInfo } from 'types/api/token'; + +import type { ResourceError } from 'lib/api/resources'; import useIsMobile from 'lib/hooks/useIsMobile'; import ActionBar from 'ui/shared/ActionBar'; import DataListDisplay from 'ui/shared/DataListDisplay'; @@ -11,9 +15,10 @@ import TokenInventoryItem from './TokenInventoryItem'; type Props = { inventoryQuery: QueryWithPagesResult<'token_inventory'>; + tokenQuery: UseQueryResult>; } -const TokenInventory = ({ inventoryQuery }: Props) => { +const TokenInventory = ({ inventoryQuery, tokenQuery }: Props) => { const isMobile = useIsMobile(); const actionBar = isMobile && inventoryQuery.pagination.isVisible && ( @@ -23,8 +28,9 @@ const TokenInventory = ({ inventoryQuery }: Props) => { ); const items = inventoryQuery.data?.items; + const token = tokenQuery.data; - const content = items ? ( + const content = items && token ? ( { > { items.map((item, index) => ( )) } diff --git a/ui/token/TokenInventoryItem.tsx b/ui/token/TokenInventoryItem.tsx index d816cc3f54..72f650d2b8 100644 --- a/ui/token/TokenInventoryItem.tsx +++ b/ui/token/TokenInventoryItem.tsx @@ -1,7 +1,7 @@ import { Box, Flex, Text, Link, useColorModeValue, Skeleton } from '@chakra-ui/react'; import React from 'react'; -import type { TokenInstance } from 'types/api/token'; +import type { TokenInfo, TokenInstance } from 'types/api/token'; import { route } from 'nextjs-routes'; @@ -11,9 +11,9 @@ import LinkInternal from 'ui/shared/LinkInternal'; import NftMedia from 'ui/shared/nft/NftMedia'; import TruncatedTextTooltip from 'ui/shared/TruncatedTextTooltip'; -type Props = { item: TokenInstance; isLoading: boolean }; +type Props = { item: TokenInstance; token: TokenInfo; isLoading: boolean }; -const NFTItem = ({ item, isLoading }: Props) => { +const TokenInventoryItem = ({ item, token, isLoading }: Props) => { const isMobile = useIsMobile(); @@ -25,7 +25,7 @@ const NFTItem = ({ item, isLoading }: Props) => { /> ); - const url = route({ pathname: '/token/[hash]/instance/[id]', query: { hash: item.token.address, id: item.id } }); + const url = route({ pathname: '/token/[hash]/instance/[id]', query: { hash: token.address, id: item.id } }); return ( { ); }; -export default NFTItem; +export default TokenInventoryItem; diff --git a/ui/tokenInstance/TokenInstanceDetails.pw.tsx b/ui/tokenInstance/TokenInstanceDetails.pw.tsx index 11ae3e3a0b..d4d31085e4 100644 --- a/ui/tokenInstance/TokenInstanceDetails.pw.tsx +++ b/ui/tokenInstance/TokenInstanceDetails.pw.tsx @@ -2,6 +2,7 @@ import { test, expect } from '@playwright/experimental-ct-react'; import React from 'react'; import * as addressMock from 'mocks/address/address'; +import { tokenInfoERC721a } from 'mocks/tokens/tokenInfo'; import * as tokenInstanceMock from 'mocks/tokens/tokenInstance'; import TestApp from 'playwright/TestApp'; import buildApiUrl from 'playwright/utils/buildApiUrl'; @@ -9,10 +10,12 @@ import * as configs from 'playwright/utils/configs'; import TokenInstanceDetails from './TokenInstanceDetails'; -const API_URL_ADDRESS = buildApiUrl('address', { hash: tokenInstanceMock.base.token.address }); +const hash = tokenInfoERC721a.address; + +const API_URL_ADDRESS = buildApiUrl('address', { hash }); const API_URL_TOKEN_TRANSFERS_COUNT = buildApiUrl('token_instance_transfers_count', { id: tokenInstanceMock.unique.id, - hash: tokenInstanceMock.unique.token.address, + hash, }); test('base view +@dark-mode +@mobile', async({ mount, page }) => { @@ -31,7 +34,7 @@ test('base view +@dark-mode +@mobile', async({ mount, page }) => { const component = await mount( - + , ); diff --git a/ui/tokenInstance/TokenInstanceDetails.tsx b/ui/tokenInstance/TokenInstanceDetails.tsx index aae2b1302c..6896f1cc4c 100644 --- a/ui/tokenInstance/TokenInstanceDetails.tsx +++ b/ui/tokenInstance/TokenInstanceDetails.tsx @@ -1,7 +1,7 @@ import { Flex, Grid, Skeleton } from '@chakra-ui/react'; import React from 'react'; -import type { TokenInstance } from 'types/api/token'; +import type { TokenInfo, TokenInstance } from 'types/api/token'; import CopyToClipboard from 'ui/shared/CopyToClipboard'; import DetailsInfoItem from 'ui/shared/DetailsInfoItem'; @@ -18,11 +18,12 @@ import TokenInstanceTransfersCount from './details/TokenInstanceTransfersCount'; interface Props { data?: TokenInstance; + token?: TokenInfo; isLoading?: boolean; scrollRef?: React.RefObject; } -const TokenInstanceDetails = ({ data, scrollRef, isLoading }: Props) => { +const TokenInstanceDetails = ({ data, token, scrollRef, isLoading }: Props) => { const handleCounterItemClick = React.useCallback(() => { window.setTimeout(() => { // cannot do scroll instantly, have to wait a little @@ -30,7 +31,7 @@ const TokenInstanceDetails = ({ data, scrollRef, isLoading }: Props) => { }, 500); }, [ scrollRef ]); - if (!data) { + if (!data || !token) { return null; } @@ -56,7 +57,7 @@ const TokenInstanceDetails = ({ data, scrollRef, isLoading }: Props) => { /> ) } - + { - - + + Date: Thu, 30 Nov 2023 23:48:40 +0100 Subject: [PATCH 2/7] soliditycheck report --- icons/score/score-not-ok.svg | 4 + icons/score/score-ok.svg | 3 + lib/api/resources.ts | 7 +- mocks/contract/solidityscanReport.ts | 21 +++ stubs/contract.ts | 24 ++- types/api/contract.ts | 22 +++ ui/address/SolidityscanReport.pw.tsx | 27 +++ ui/address/SolidityscanReport.tsx | 159 ++++++++++++++++++ ...olor-mode_base-view-dark-mode-mobile-1.png | Bin 0 -> 29953 bytes ...x_default_base-view-dark-mode-mobile-1.png | Bin 0 -> 30805 bytes ...sx_mobile_base-view-dark-mode-mobile-1.png | Bin 0 -> 26301 bytes ui/pages/Address.tsx | 7 +- 12 files changed, 270 insertions(+), 4 deletions(-) create mode 100644 icons/score/score-not-ok.svg create mode 100644 icons/score/score-ok.svg create mode 100644 mocks/contract/solidityscanReport.ts create mode 100644 ui/address/SolidityscanReport.pw.tsx create mode 100644 ui/address/SolidityscanReport.tsx create mode 100644 ui/address/__screenshots__/SolidityscanReport.pw.tsx_dark-color-mode_base-view-dark-mode-mobile-1.png create mode 100644 ui/address/__screenshots__/SolidityscanReport.pw.tsx_default_base-view-dark-mode-mobile-1.png create mode 100644 ui/address/__screenshots__/SolidityscanReport.pw.tsx_mobile_base-view-dark-mode-mobile-1.png diff --git a/icons/score/score-not-ok.svg b/icons/score/score-not-ok.svg new file mode 100644 index 0000000000..9b4533f6ac --- /dev/null +++ b/icons/score/score-not-ok.svg @@ -0,0 +1,4 @@ + + + + diff --git a/icons/score/score-ok.svg b/icons/score/score-ok.svg new file mode 100644 index 0000000000..dbe11836fd --- /dev/null +++ b/icons/score/score-ok.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/api/resources.ts b/lib/api/resources.ts index bf1fc70c56..d317d6d5ac 100644 --- a/lib/api/resources.ts +++ b/lib/api/resources.ts @@ -31,7 +31,7 @@ import type { AddressesResponse } from 'types/api/addresses'; import type { BlocksResponse, BlockTransactionsResponse, Block, BlockFilters, BlockWithdrawalsResponse } from 'types/api/block'; import type { ChartMarketResponse, ChartTransactionResponse } from 'types/api/charts'; import type { BackendVersionConfig } from 'types/api/configs'; -import type { SmartContract, SmartContractReadMethod, SmartContractWriteMethod, SmartContractVerificationConfig } from 'types/api/contract'; +import type { SmartContract, SmartContractReadMethod, SmartContractWriteMethod, SmartContractVerificationConfig, SolidityscanReport } from 'types/api/contract'; import type { VerifiedContractsResponse, VerifiedContractsFilters, VerifiedContractsCounters } from 'types/api/contracts'; import type { IndexingStatus } from 'types/api/indexingStatus'; import type { InternalTransactionsResponse } from 'types/api/internalTransaction'; @@ -343,6 +343,10 @@ export const RESOURCES = { path: '/api/v2/smart-contracts/:hash/verification/via/:method', pathParams: [ 'hash' as const, 'method' as const ], }, + contract_solidityscan_report: { + path: '/api/v2/smart-contracts/:hash/solidityscan-report', + pathParams: [ 'hash' as const ], + }, verified_contracts: { path: '/api/v2/smart-contracts', @@ -659,6 +663,7 @@ Q extends 'contract_methods_read' ? Array : Q extends 'contract_methods_read_proxy' ? Array : Q extends 'contract_methods_write' ? Array : Q extends 'contract_methods_write_proxy' ? Array : +Q extends 'contract_solidityscan_report' ? SolidityscanReport : Q extends 'verified_contracts' ? VerifiedContractsResponse : Q extends 'verified_contracts_counters' ? VerifiedContractsCounters : Q extends 'visualize_sol2uml' ? VisualizedContract : diff --git a/mocks/contract/solidityscanReport.ts b/mocks/contract/solidityscanReport.ts new file mode 100644 index 0000000000..e8f7a777ac --- /dev/null +++ b/mocks/contract/solidityscanReport.ts @@ -0,0 +1,21 @@ +export const solidityscanReport = { + scan_report: { + scan_status: 'scan_done', + scan_summary: { + issue_severity_distribution: { + critical: 0, + gas: 1, + high: 0, + informational: 0, + low: 2, + medium: 0, + }, + lines_analyzed_count: 18, + scan_time_taken: 1, + score: '3.61', + score_v2: '72.22', + threat_score: '94.74', + }, + scanner_reference_url: 'https://solidityscan.com/quickscan/0xc1EF7811FF2ebFB74F80ed7423f2AdAA37454be2/blockscout/eth-goerli?ref=blockscout', + }, +}; diff --git a/stubs/contract.ts b/stubs/contract.ts index 12bba6c130..36d7b13ed2 100644 --- a/stubs/contract.ts +++ b/stubs/contract.ts @@ -1,4 +1,4 @@ -import type { SmartContract } from 'types/api/contract'; +import type { SmartContract, SolidityscanReport } from 'types/api/contract'; import type { VerifiedContract } from 'types/api/contracts'; import { ADDRESS_PARAMS } from './addressParams'; @@ -53,3 +53,25 @@ export const VERIFIED_CONTRACT_INFO: VerifiedContract = { tx_count: 565058, verified_at: '2023-04-10T13:16:33.884921Z', }; + +export const SOLIDITYSCAN_REPORT: SolidityscanReport = { + scan_report: { + scan_status: 'scan_done', + scan_summary: { + issue_severity_distribution: { + critical: 0, + gas: 1, + high: 0, + informational: 0, + low: 2, + medium: 0, + }, + lines_analyzed_count: 18, + scan_time_taken: 1, + score: '3.61', + score_v2: '72.22', + threat_score: '94.74', + }, + scanner_reference_url: 'https://solidityscan.com/quickscan/0xc1EF7811FF2ebFB74F80ed7423f2AdAA37454be2/blockscout/eth-goerli?ref=blockscout', + }, +}; diff --git a/types/api/contract.ts b/types/api/contract.ts index d8ff3a0b3c..d8451ce974 100644 --- a/types/api/contract.ts +++ b/types/api/contract.ts @@ -156,3 +156,25 @@ export interface SmartContractVerificationError { constructor_arguments?: Array; name?: Array; } + +export type SolidityscanReport = { + scan_report: { + scan_status: string; + scan_summary: { + issue_severity_distribution: { + critical: number; + gas: number; + high: number; + informational: number; + low: number; + medium: number; + }; + lines_analyzed_count: number; + scan_time_taken: number; + score: string; + score_v2: string; + threat_score: string; + }; + scanner_reference_url: string; + }; +} diff --git a/ui/address/SolidityscanReport.pw.tsx b/ui/address/SolidityscanReport.pw.tsx new file mode 100644 index 0000000000..d724dd52f1 --- /dev/null +++ b/ui/address/SolidityscanReport.pw.tsx @@ -0,0 +1,27 @@ +import { test, expect } from '@playwright/experimental-ct-react'; +import React from 'react'; + +import { solidityscanReport as solidityscanReportMock } from 'mocks/contract/solidityscanReport'; +import TestApp from 'playwright/TestApp'; +import buildApiUrl from 'playwright/utils/buildApiUrl'; + +import SolidityscanReport from './SolidityscanReport'; + +const addressHash = 'hash'; +const REPORT_API_URL = buildApiUrl('contract_solidityscan_report', { hash: addressHash }); + +test('base view +@dark-mode +@mobile', async({ mount, page }) => { + await page.route(REPORT_API_URL, (route) => route.fulfill({ + status: 200, + body: JSON.stringify(solidityscanReportMock), + })); + + const component = await mount( + + + , + ); + await component.getByLabel('SolidityScan score').click(); + + await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 400, height: 500 } }); +}); diff --git a/ui/address/SolidityscanReport.tsx b/ui/address/SolidityscanReport.tsx new file mode 100644 index 0000000000..a4d037733c --- /dev/null +++ b/ui/address/SolidityscanReport.tsx @@ -0,0 +1,159 @@ +import { + Box, + Flex, + Text, + Grid, + Button, + Icon, + chakra, + Popover, + PopoverTrigger, + PopoverBody, + PopoverContent, + useDisclosure, + Skeleton, + Center, + useColorModeValue, +} from '@chakra-ui/react'; +import React from 'react'; + +import { SolidityscanReport } from 'types/api/contract'; + +import scoreNotOkIcon from 'icons/score/score-not-ok.svg'; +import scoreOkIcon from 'icons/score/score-ok.svg'; +import useApiQuery from 'lib/api/useApiQuery'; +import { SOLIDITYSCAN_REPORT } from 'stubs/contract'; +import LinkExternal from 'ui/shared/LinkExternal'; + +type DistributionItem = { + id: keyof SolidityscanReport['scan_report']['scan_summary']['issue_severity_distribution']; + name: string; + color: string; +} + +const DISTRIBUTION_ITEMS: Array = [ + { id: 'critical', name: 'Critical', color: '#891F11' }, + { id: 'high', name: 'High', color: '#EC672C' }, + { id: 'medium', name: 'Medium', color: '#FBE74D' }, + { id: 'low', name: 'Low', color: '#68C88E' }, + { id: 'informational', name: 'Informational', color: '#A3AEBE' }, + { id: 'gas', name: 'Gas', color: '#A47585' }, +]; + +interface Props { + className?: string; + hash: string; +} + +const SolidityscanReport = ({ className, hash }: Props) => { + const { isOpen, onToggle, onClose } = useDisclosure(); + + const { data, isPlaceholderData, isError } = useApiQuery('contract_solidityscan_report', { + pathParams: { hash }, + queryOptions: { + enabled: Boolean(hash), + placeholderData: SOLIDITYSCAN_REPORT, + }, + }); + + const score = Number(data?.scan_report.scan_summary.score_v2); + + const bgBar = useColorModeValue('blackAlpha.50', 'whiteAlpha.50'); + const chartGrayColor = useColorModeValue('gray.100', 'gray.700'); + const yetAnotherGrayColor = useColorModeValue('gray.400', 'gray.500'); + const popoverBgColor = useColorModeValue('white', 'gray.900'); + + if (isError || !score) { + return null; + } + + let scoreColor; + let scoreLevel; + if (score >= 80) { + scoreColor = 'green.600'; + scoreLevel = 'GREAT'; + } else if (score >= 30) { + scoreColor = 'orange.600'; + scoreLevel = 'AVERAGE'; + } else { + scoreColor = 'red.600'; + scoreLevel = 'LOW'; + } + + const vulnerabilities = data?.scan_report.scan_summary.issue_severity_distribution; + const vulnerabilitiesCounts = vulnerabilities ? Object.values(vulnerabilities) : []; + const vulnerabilitiesCount = vulnerabilitiesCounts.reduce((acc, val) => acc + val, 0); + + return ( + + + + + + + + + Contract analyzed for 140+ vulnerability patterns by SolidityScan + + +
+ +
+
+ + + { score } + / 100 + + Security score is { scoreLevel } + +
+ { vulnerabilities && vulnerabilitiesCount && ( + + Vulnerabilities distribution + + { DISTRIBUTION_ITEMS.map(item => ( + <> + + + { item.name } + 0 ? 'text' : yetAnotherGrayColor }>{ vulnerabilities[item.id] } + + + + + + )) } + + + ) } + View full report +
+
+
+ ); +}; + +export default chakra(SolidityscanReport); diff --git a/ui/address/__screenshots__/SolidityscanReport.pw.tsx_dark-color-mode_base-view-dark-mode-mobile-1.png b/ui/address/__screenshots__/SolidityscanReport.pw.tsx_dark-color-mode_base-view-dark-mode-mobile-1.png new file mode 100644 index 0000000000000000000000000000000000000000..1bf68f172ec489ae21a67f1982d4284903977727 GIT binary patch literal 29953 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≧P!G80(2nQl58>b0#c@7*{B<$XC%J)7jvBywl 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 literal 0 HcmV?d00001 diff --git a/ui/address/__screenshots__/SolidityscanReport.pw.tsx_mobile_base-view-dark-mode-mobile-1.png b/ui/address/__screenshots__/SolidityscanReport.pw.tsx_mobile_base-view-dark-mode-mobile-1.png new file mode 100644 index 0000000000000000000000000000000000000000..91d66893865376b70f66605ff8b0a266d97e7a06 GIT binary patch literal 26301 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 literal 0 HcmV?d00001 diff --git a/ui/pages/Address.tsx b/ui/pages/Address.tsx index be89c410b0..d1e427f990 100644 --- a/ui/pages/Address.tsx +++ b/ui/pages/Address.tsx @@ -1,4 +1,4 @@ -import { Box, Flex, Icon } from '@chakra-ui/react'; +import { Box, Flex, HStack, Icon } from '@chakra-ui/react'; import { useRouter } from 'next/router'; import React from 'react'; @@ -25,6 +25,7 @@ import AddressTxs from 'ui/address/AddressTxs'; import AddressWithdrawals from 'ui/address/AddressWithdrawals'; import AddressFavoriteButton from 'ui/address/details/AddressFavoriteButton'; import AddressQrCode from 'ui/address/details/AddressQrCode'; +import SolidityscanReport from 'ui/address/SolidityscanReport'; import AccountActionsMenu from 'ui/shared/AccountActionsMenu/AccountActionsMenu'; import TextAd from 'ui/shared/ad/TextAd'; import AddressAddToWallet from 'ui/shared/address/AddressAddToWallet'; @@ -194,7 +195,9 @@ const AddressPageContent = () => { ) } - + + + ); From 7b5333d8da05720b560f11dac6f2183c74912d73 Mon Sep 17 00:00:00 2001 From: isstuev Date: Fri, 1 Dec 2023 00:06:18 +0100 Subject: [PATCH 3/7] variables --- configs/app/ui/views/address.ts | 1 + configs/envs/.env.eth_goerli | 1 + deploy/tools/envs-validator/schema.ts | 1 + deploy/values/review/values.yaml.gotmpl | 1 + docs/ENVS.md | 1 + ui/pages/Address.tsx | 2 +- 6 files changed, 6 insertions(+), 1 deletion(-) diff --git a/configs/app/ui/views/address.ts b/configs/app/ui/views/address.ts index 56789ffad5..c2f0f4fb52 100644 --- a/configs/app/ui/views/address.ts +++ b/configs/app/ui/views/address.ts @@ -27,6 +27,7 @@ const hiddenViews = (() => { const config = Object.freeze({ identiconType, hiddenViews, + solidityscanEnabled: getEnvValue('NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED') === 'true', }); export default config; diff --git a/configs/envs/.env.eth_goerli b/configs/envs/.env.eth_goerli index bea2e6654e..da1fac4d97 100644 --- a/configs/envs/.env.eth_goerli +++ b/configs/envs/.env.eth_goerli @@ -47,6 +47,7 @@ NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com NEXT_PUBLIC_WEB3_WALLETS=['token_pocket','metamask'] +NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED='true' #meta NEXT_PUBLIC_OG_IMAGE_URL=https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/eth-goerli.png?raw=true diff --git a/deploy/tools/envs-validator/schema.ts b/deploy/tools/envs-validator/schema.ts index 7940f55a48..85966c74ed 100644 --- a/deploy/tools/envs-validator/schema.ts +++ b/deploy/tools/envs-validator/schema.ts @@ -392,6 +392,7 @@ const schema = yup .transform(replaceQuotes) .json() .of(yup.string().oneOf(ADDRESS_VIEWS_IDS)), + NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED: yup.boolean(), NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS: yup .array() .transform(replaceQuotes) diff --git a/deploy/values/review/values.yaml.gotmpl b/deploy/values/review/values.yaml.gotmpl index b720f05d2b..0b3906e247 100644 --- a/deploy/values/review/values.yaml.gotmpl +++ b/deploy/values/review/values.yaml.gotmpl @@ -67,6 +67,7 @@ frontend: NEXT_PUBLIC_WEB3_WALLETS: "['token_pocket','coinbase','metamask']" NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE: gradient_avatar NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS: "['top_accounts']" + NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED: true NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS: "['value','fee_currency','gas_price','gas_fees','burnt_fees']" NEXT_PUBLIC_VIEWS_TX_ADDITIONAL_FIELDS: "['fee_per_gas']" NEXT_PUBLIC_USE_NEXT_JS_PROXY: true diff --git a/docs/ENVS.md b/docs/ENVS.md index b405ff8178..55ba4a38f2 100644 --- a/docs/ENVS.md +++ b/docs/ENVS.md @@ -197,6 +197,7 @@ Settings for meta tags and OG tags | --- | --- | --- | --- | --- | --- | | NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE | `"github" \| "jazzicon" \| "gradient_avatar" \| "blockie"` | Style of address identicon appearance. Choose between [GitHub](https://github.blog/2013-08-14-identicons/), [Metamask Jazzicon](https://metamask.github.io/jazzicon/), [Gradient Avatar](https://github.com/varld/gradient-avatar) and [Ethereum Blocky](https://mycryptohq.github.io/ethereum-blockies-base64/) | - | `jazzicon` | `gradient_avatar` | | NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS | `Array` | Address views that should not be displayed. See below the list of the possible id values. | - | - | `'["top_accounts"]'` | +| NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED | `boolean` | Set to `true` if SolidityScan reports are supperted | - | - | `true` | ##### Address views list | Id | Description | diff --git a/ui/pages/Address.tsx b/ui/pages/Address.tsx index d1e427f990..d3b4a05550 100644 --- a/ui/pages/Address.tsx +++ b/ui/pages/Address.tsx @@ -196,7 +196,7 @@ const AddressPageContent = () => { - + { config.UI.views.address.solidityscanEnabled && } ); From 20bd18975fef7d3b6abc0aba595ef9621c385a45 Mon Sep 17 00:00:00 2001 From: isstuev Date: Fri, 1 Dec 2023 00:35:36 +0100 Subject: [PATCH 4/7] fix condition --- ui/pages/Address.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/pages/Address.tsx b/ui/pages/Address.tsx index d3b4a05550..51c58d493e 100644 --- a/ui/pages/Address.tsx +++ b/ui/pages/Address.tsx @@ -196,7 +196,7 @@ const AddressPageContent = () => { - { config.UI.views.address.solidityscanEnabled && } + { addressQuery.data?.is_contract && config.UI.views.address.solidityscanEnabled && } ); From 9c45f200821a2f6c29d7d2a11dc1f6af00aca452 Mon Sep 17 00:00:00 2001 From: isstuev Date: Fri, 1 Dec 2023 00:41:56 +0100 Subject: [PATCH 5/7] goerli review --- deploy/values/review/values.yaml.gotmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/values/review/values.yaml.gotmpl b/deploy/values/review/values.yaml.gotmpl index 0b3906e247..dbfd815a82 100644 --- a/deploy/values/review/values.yaml.gotmpl +++ b/deploy/values/review/values.yaml.gotmpl @@ -51,8 +51,8 @@ frontend: NEXT_PUBLIC_FEATURED_NETWORKS: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-goerli.json NEXT_PUBLIC_NETWORK_LOGO: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/goerli.svg NEXT_PUBLIC_NETWORK_ICON: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/goerli.svg - NEXT_PUBLIC_API_HOST: etc.blockscout.com - NEXT_PUBLIC_STATS_API_HOST: https://stats-etc.k8s.blockscout.com/ + NEXT_PUBLIC_API_HOST: eth-goerli.blockscout.com + NEXT_PUBLIC_STATS_API_HOST: https://stats-goerli.k8s-dev.blockscout.com/ NEXT_PUBLIC_VISUALIZE_API_HOST: http://visualizer-svc.visualizer-testing.svc.cluster.local/ NEXT_PUBLIC_CONTRACT_INFO_API_HOST: https://contracts-info-test.k8s-dev.blockscout.com NEXT_PUBLIC_ADMIN_SERVICE_API_HOST: https://admin-rs-test.k8s-dev.blockscout.com From b0ddaca411801b55e6deadd642d131068bcf9c30 Mon Sep 17 00:00:00 2001 From: isstuev Date: Fri, 1 Dec 2023 17:24:04 +0100 Subject: [PATCH 6/7] change border color, add tests --- mocks/contract/solidityscanReport.ts | 46 ++++++++++++++++- ui/address/SolidityscanReport.pw.tsx | 47 ++++++++++++++++-- ui/address/SolidityscanReport.tsx | 3 +- ...mode_average-report-dark-mode-mobile-1.png | Bin 0 -> 1677 bytes ...mode_average-report-dark-mode-mobile-2.png | Bin 0 -> 29952 bytes ...olor-mode_base-view-dark-mode-mobile-1.png | Bin 29953 -> 0 bytes ...ault_average-report-dark-mode-mobile-1.png | Bin 0 -> 1785 bytes ...ault_average-report-dark-mode-mobile-2.png | Bin 0 -> 30812 bytes ...x_default_base-view-dark-mode-mobile-1.png | Bin 30805 -> 0 bytes ...anReport.pw.tsx_default_great-report-1.png | Bin 0 -> 1758 bytes ...anReport.pw.tsx_default_great-report-2.png | Bin 0 -> 20599 bytes ...scanReport.pw.tsx_default_low-report-1.png | Bin 0 -> 1558 bytes ...scanReport.pw.tsx_default_low-report-2.png | Bin 0 -> 30084 bytes ...bile_average-report-dark-mode-mobile-1.png | Bin 0 -> 1782 bytes ...ile_average-report-dark-mode-mobile-2.png} | Bin 15 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 ui/address/__screenshots__/SolidityscanReport.pw.tsx_dark-color-mode_average-report-dark-mode-mobile-1.png create mode 100644 ui/address/__screenshots__/SolidityscanReport.pw.tsx_dark-color-mode_average-report-dark-mode-mobile-2.png delete mode 100644 ui/address/__screenshots__/SolidityscanReport.pw.tsx_dark-color-mode_base-view-dark-mode-mobile-1.png create mode 100644 ui/address/__screenshots__/SolidityscanReport.pw.tsx_default_average-report-dark-mode-mobile-1.png create mode 100644 ui/address/__screenshots__/SolidityscanReport.pw.tsx_default_average-report-dark-mode-mobile-2.png delete mode 100644 ui/address/__screenshots__/SolidityscanReport.pw.tsx_default_base-view-dark-mode-mobile-1.png create mode 100644 ui/address/__screenshots__/SolidityscanReport.pw.tsx_default_great-report-1.png create mode 100644 ui/address/__screenshots__/SolidityscanReport.pw.tsx_default_great-report-2.png create mode 100644 ui/address/__screenshots__/SolidityscanReport.pw.tsx_default_low-report-1.png create mode 100644 ui/address/__screenshots__/SolidityscanReport.pw.tsx_default_low-report-2.png create mode 100644 ui/address/__screenshots__/SolidityscanReport.pw.tsx_mobile_average-report-dark-mode-mobile-1.png rename ui/address/__screenshots__/{SolidityscanReport.pw.tsx_mobile_base-view-dark-mode-mobile-1.png => SolidityscanReport.pw.tsx_mobile_average-report-dark-mode-mobile-2.png} (100%) diff --git a/mocks/contract/solidityscanReport.ts b/mocks/contract/solidityscanReport.ts index e8f7a777ac..000adabf7f 100644 --- a/mocks/contract/solidityscanReport.ts +++ b/mocks/contract/solidityscanReport.ts @@ -1,4 +1,4 @@ -export const solidityscanReport = { +export const solidityscanReportAverage = { scan_report: { scan_status: 'scan_done', scan_summary: { @@ -19,3 +19,47 @@ export const solidityscanReport = { scanner_reference_url: 'https://solidityscan.com/quickscan/0xc1EF7811FF2ebFB74F80ed7423f2AdAA37454be2/blockscout/eth-goerli?ref=blockscout', }, }; + +export const solidityscanReportGreat = { + scan_report: { + scan_status: 'scan_done', + scan_summary: { + issue_severity_distribution: { + critical: 0, + gas: 0, + high: 0, + informational: 0, + low: 0, + medium: 0, + }, + lines_analyzed_count: 18, + scan_time_taken: 1, + score: '3.61', + score_v2: '100', + threat_score: '94.74', + }, + scanner_reference_url: 'https://solidityscan.com/quickscan/0xc1EF7811FF2ebFB74F80ed7423f2AdAA37454be2/blockscout/eth-goerli?ref=blockscout', + }, +}; + +export const solidityscanReportLow = { + scan_report: { + scan_status: 'scan_done', + scan_summary: { + issue_severity_distribution: { + critical: 2, + gas: 1, + high: 3, + informational: 0, + low: 2, + medium: 10, + }, + lines_analyzed_count: 18, + scan_time_taken: 1, + score: '3.61', + score_v2: '22.22', + threat_score: '94.74', + }, + scanner_reference_url: 'https://solidityscan.com/quickscan/0xc1EF7811FF2ebFB74F80ed7423f2AdAA37454be2/blockscout/eth-goerli?ref=blockscout', + }, +}; diff --git a/ui/address/SolidityscanReport.pw.tsx b/ui/address/SolidityscanReport.pw.tsx index d724dd52f1..fd41c7a860 100644 --- a/ui/address/SolidityscanReport.pw.tsx +++ b/ui/address/SolidityscanReport.pw.tsx @@ -1,7 +1,7 @@ import { test, expect } from '@playwright/experimental-ct-react'; import React from 'react'; -import { solidityscanReport as solidityscanReportMock } from 'mocks/contract/solidityscanReport'; +import * as solidityscanReportMock from 'mocks/contract/solidityscanReport'; import TestApp from 'playwright/TestApp'; import buildApiUrl from 'playwright/utils/buildApiUrl'; @@ -10,10 +10,10 @@ import SolidityscanReport from './SolidityscanReport'; const addressHash = 'hash'; const REPORT_API_URL = buildApiUrl('contract_solidityscan_report', { hash: addressHash }); -test('base view +@dark-mode +@mobile', async({ mount, page }) => { +test('average report +@dark-mode +@mobile', async({ mount, page }) => { await page.route(REPORT_API_URL, (route) => route.fulfill({ status: 200, - body: JSON.stringify(solidityscanReportMock), + body: JSON.stringify(solidityscanReportMock.solidityscanReportAverage), })); const component = await mount( @@ -21,6 +21,47 @@ test('base view +@dark-mode +@mobile', async({ mount, page }) => { , ); + + await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 100, height: 50 } }); + + await component.getByLabel('SolidityScan score').click(); + + await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 400, height: 500 } }); +}); + +test('great report', async({ mount, page }) => { + await page.route(REPORT_API_URL, (route) => route.fulfill({ + status: 200, + body: JSON.stringify(solidityscanReportMock.solidityscanReportGreat), + })); + + const component = await mount( + + + , + ); + + await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 100, height: 50 } }); + + await component.getByLabel('SolidityScan score').click(); + + await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 400, height: 500 } }); +}); + +test('low report', async({ mount, page }) => { + await page.route(REPORT_API_URL, (route) => route.fulfill({ + status: 200, + body: JSON.stringify(solidityscanReportMock.solidityscanReportLow), + })); + + const component = await mount( + + + , + ); + + await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 100, height: 50 } }); + await component.getByLabel('SolidityScan score').click(); await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 400, height: 500 } }); diff --git a/ui/address/SolidityscanReport.tsx b/ui/address/SolidityscanReport.tsx index a4d037733c..5cdb32e30a 100644 --- a/ui/address/SolidityscanReport.tsx +++ b/ui/address/SolidityscanReport.tsx @@ -91,6 +91,7 @@ const SolidityscanReport = ({ className, hash }: Props) => {