Skip to content

Commit

Permalink
add certified conract label
Browse files Browse the repository at this point in the history
  • Loading branch information
isstuev committed May 20, 2024
1 parent ddb2a4a commit 0372c41
Show file tree
Hide file tree
Showing 25 changed files with 98 additions and 24 deletions.
2 changes: 1 addition & 1 deletion configs/envs/.env.eth_sepolia
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ NEXT_PUBLIC_NETWORK_RPC_URL=https://eth-sepolia.public.blastapi.io
NEXT_PUBLIC_IS_TESTNET=true

# api configuration
NEXT_PUBLIC_API_HOST=eth-sepolia.blockscout.com
NEXT_PUBLIC_API_HOST=eth-sepolia.k8s-dev.blockscout.com
NEXT_PUBLIC_API_BASE_PATH=/

# ui config
Expand Down
File renamed without changes
5 changes: 5 additions & 0 deletions mocks/contract/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ export const verified: SmartContract = {
minimal_proxy_address_hash: null,
};

export const certified: SmartContract = {
...verified,
certified: true,
};

export const withMultiplePaths: SmartContract = {
...verified,
file_path: './simple_storage.sol',
Expand Down
1 change: 1 addition & 0 deletions mocks/contracts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const contract2: VerifiedContract = {
watchlist_names: [],
ens_domain_name: null,
},
certified: true,
coin_balance: '9078234570352343999',
compiler_version: 'v0.3.1+commit.0463ea4c',
has_constructor_args: true,
Expand Down
2 changes: 1 addition & 1 deletion public/icons/name.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
| "brands/safe"
| "brands/solidity_scan"
| "burger"
| "certified"
| "check"
| "clock-light"
| "clock"
Expand Down Expand Up @@ -146,7 +147,6 @@
| "user_op_slim"
| "user_op"
| "validator"
| "verified_token"
| "verified"
| "verify-contract"
| "wallet"
Expand Down
1 change: 1 addition & 0 deletions types/api/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export interface SmartContract {
minimal_proxy_address_hash: string | null;
language: string | null;
license_type: SmartContractLicenseType | null;
certified?: boolean;
}

export type SmartContractDecodedConstructorArg = [
Expand Down
1 change: 1 addition & 0 deletions types/api/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { SmartContractLicenseType } from './contract';

export interface VerifiedContract {
address: AddressParam;
certified?: boolean;
coin_balance: string;
compiler_version: string;
language: 'vyper' | 'yul' | 'solidity';
Expand Down
7 changes: 7 additions & 0 deletions ui/address/contract/ContractCode.pw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ test('with proxy address alert +@mobile', async({ render, mockApiResponse }) =>
await expect(component.getByRole('alert')).toHaveScreenshot();
});

test('with certified icon +@mobile', async({ render, mockApiResponse, page }) => {
await mockApiResponse('contract', contractMock.certified, { pathParams: { hash: addressMock.contract.hash } });
await render(<ContractCode/>, { hooksConfig });

await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 1200, height: 120 } });
});

test('non verified', async({ render, mockApiResponse }) => {
await mockApiResponse('contract', contractMock.nonVerified, { pathParams: { hash: addressMock.contract.hash } });
const component = await render(<ContractCode/>, { hooksConfig }, { withSocket: true });
Expand Down
10 changes: 9 additions & 1 deletion ui/address/contract/ContractCode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { getResourceKey } from 'lib/api/useApiQuery';
import { CONTRACT_LICENSES } from 'lib/contracts/licenses';
import dayjs from 'lib/date/dayjs';
import useSocketMessage from 'lib/socket/useSocketMessage';
import ContractCertifiedLabel from 'ui/shared/ContractCertifiedLabel';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import Hint from 'ui/shared/Hint';
Expand Down Expand Up @@ -195,6 +196,13 @@ const ContractCode = ({ addressHash, contractQuery, channel }: Props) => {
return null;
})();

const contractNameWithCertifiedIcon = data?.is_verified ? (
<Flex alignItems="center">
{ data.name }
{ data.certified && <ContractCertifiedLabel iconSize={ 5 } boxSize={ 5 } ml={ 2 }/> }
</Flex>
) : null;

return (
<>
<Flex flexDir="column" rowGap={ 2 } mb={ 6 } _empty={{ display: 'none' }}>
Expand Down Expand Up @@ -248,7 +256,7 @@ const ContractCode = ({ addressHash, contractQuery, channel }: Props) => {
</Flex>
{ data?.is_verified && (
<Grid templateColumns={{ base: '1fr', lg: '1fr 1fr' }} rowGap={ 4 } columnGap={ 6 } mb={ 8 }>
{ data.name && <InfoItem label="Contract name" content={ data.name } isLoading={ isPlaceholderData }/> }
{ data.name && <InfoItem label="Contract name" content={ contractNameWithCertifiedIcon } isLoading={ isPlaceholderData }/> }
{ data.compiler_version && <InfoItem label="Compiler version" content={ data.compiler_version } isLoading={ isPlaceholderData }/> }
{ data.evm_version && <InfoItem label="EVM version" content={ data.evm_version } textTransform="capitalize" isLoading={ isPlaceholderData }/> }
{ licenseLink && (
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 25 additions & 2 deletions ui/pages/VerifiedContracts.pw.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { test, expect } from '@playwright/experimental-ct-react';
import { test, expect, devices } from '@playwright/experimental-ct-react';
import React from 'react';

import * as textAdMock from 'mocks/ad/textAd';
Expand All @@ -25,7 +25,7 @@ test.beforeEach(async({ page }) => {
});
});

test('base view +@mobile', async({ mount, page }) => {
test('base view', async({ mount, page }) => {
await page.route(VERIFIED_CONTRACTS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(verifiedContractsMock.baseResponse),
Expand All @@ -43,3 +43,26 @@ test('base view +@mobile', async({ mount, page }) => {

await expect(component).toHaveScreenshot();
});

test.describe('mobile', () => {
test.use({ viewport: devices['iPhone 13 Pro'].viewport });
test('base view', async({ mount, page }) => {

await page.route(VERIFIED_CONTRACTS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(verifiedContractsMock.baseResponse),
}));
await page.route(VERIFIED_CONTRACTS_COUNTERS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(verifiedContractsCountersMock),
}));

const component = await mount(
<TestApp>
<VerifiedContracts/>
</TestApp>,
);

await expect(component).toHaveScreenshot();
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
2 changes: 1 addition & 1 deletion ui/searchResults/SearchResultListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
textOverflow="ellipsis"
/>
</LinkInternal>
{ data.is_verified_via_admin_panel && <IconSvg name="verified_token" boxSize={ 4 } ml={ 1 } color="green.500"/> }
{ data.is_verified_via_admin_panel && <IconSvg name="certified" boxSize={ 4 } ml={ 1 } color="green.500"/> }
</Flex>
);
}
Expand Down
2 changes: 1 addition & 1 deletion ui/searchResults/SearchResultTableItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
dangerouslySetInnerHTML={{ __html: highlightText(name, searchTerm) }}
/>
</LinkInternal>
{ data.is_verified_via_admin_panel && <IconSvg name="verified_token" boxSize={ 4 } ml={ 1 } color="green.500"/> }
{ data.is_verified_via_admin_panel && <IconSvg name="certified" boxSize={ 4 } ml={ 1 } color="green.500"/> }
</Flex>
</Td>
<Td fontSize="sm" verticalAlign="middle">
Expand Down
21 changes: 21 additions & 0 deletions ui/shared/ContractCertifiedLabel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Box, Tooltip, chakra } from '@chakra-ui/react';
import React from 'react';

import IconSvg from './IconSvg';

type Props = {
iconSize: number;
className?: string;
}

const ContractCertifiedLabel = ({ iconSize, className }: Props) => {
return (
<Tooltip label="This contract has been certified by the chain developers">
<Box className={ className }>
<IconSvg name="certified" color="green.500" boxSize={ iconSize } cursor="pointer"/>
</Box>
</Tooltip>
);
};

export default chakra(ContractCertifiedLabel);
2 changes: 1 addition & 1 deletion ui/shared/Page/specs/DefaultView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const DefaultView = () => {

const contentAfter = (
<>
<IconSvg name="verified_token" color="green.500" boxSize={ 6 } cursor="pointer"/>
<IconSvg name="certified" color="green.500" boxSize={ 6 } cursor="pointer"/>
<EntityTags
tags={ [
{ slug: 'example', name: 'Example label', tagType: 'custom' },
Expand Down
2 changes: 1 addition & 1 deletion ui/shared/Page/specs/LongNameAndManyTags.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const LongNameAndManyTags = () => {

const contentAfter = (
<>
<IconSvg name="verified_token" color="green.500" boxSize={ 6 } cursor="pointer" flexShrink={ 0 }/>
<IconSvg name="certified" color="green.500" boxSize={ 6 } cursor="pointer" flexShrink={ 0 }/>
<EntityTags
tags={ [
{ slug: 'example', name: 'Example with long name', tagType: 'custom' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface Props {

const SearchBarSuggestToken = ({ data, isMobile, searchTerm }: Props) => {
const icon = <TokenEntity.Icon token={{ ...data, type: data.token_type }}/>;
const verifiedIcon = <IconSvg name="verified_token" boxSize={ 4 } color="green.500" ml={ 1 }/>;
const verifiedIcon = <IconSvg name="certified" boxSize={ 4 } color="green.500" ml={ 1 }/>;
const name = (
<Text
fontWeight={ 700 }
Expand Down
2 changes: 1 addition & 1 deletion ui/token/TokenPageTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ const TokenPageTitle = ({ tokenQuery, addressQuery, hash }: Props) => {
{ verifiedInfoQuery.data?.tokenAddress && (
<Tooltip label={ `Information on this token has been verified by ${ config.chain.name }` }>
<Box boxSize={ 6 }>
<IconSvg name="verified_token" color="green.500" boxSize={ 6 } cursor="pointer"/>
<IconSvg name="certified" color="green.500" boxSize={ 6 } cursor="pointer"/>
</Box>
</Tooltip>
) }
Expand Down
16 changes: 10 additions & 6 deletions ui/verifiedContracts/VerifiedContractsListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import config from 'configs/app';
import { CONTRACT_LICENSES } from 'lib/contracts/licenses';
import dayjs from 'lib/date/dayjs';
import { currencyUnits } from 'lib/units';
import ContractCertifiedLabel from 'ui/shared/ContractCertifiedLabel';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import HashStringShorten from 'ui/shared/HashStringShorten';
Expand Down Expand Up @@ -36,12 +37,15 @@ const VerifiedContractsListItem = ({ data, isLoading }: Props) => {
return (
<ListItemMobile rowGap={ 3 }>
<Flex w="100%">
<AddressEntity
isLoading={ isLoading }
address={ data.address }
query={{ tab: 'contract' }}
noCopy
/>
<Flex alignItems="center" overflow="hidden">
<AddressEntity
isLoading={ isLoading }
address={ data.address }
query={{ tab: 'contract' }}
noCopy
/>
{ data.certified && <ContractCertifiedLabel iconSize={ 5 } boxSize={ 5 } mx={ 2 }/> }
</Flex>
<Skeleton isLoaded={ !isLoading } color="text_secondary" ml="auto">
<HashStringShorten hash={ data.address.hash } isTooltipDisabled/>
</Skeleton>
Expand Down
17 changes: 10 additions & 7 deletions ui/verifiedContracts/VerifiedContractsTableItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { VerifiedContract } from 'types/api/contracts';
import config from 'configs/app';
import { CONTRACT_LICENSES } from 'lib/contracts/licenses';
import dayjs from 'lib/date/dayjs';
import ContractCertifiedLabel from 'ui/shared/ContractCertifiedLabel';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import HashStringShorten from 'ui/shared/HashStringShorten';
Expand Down Expand Up @@ -34,13 +35,15 @@ const VerifiedContractsTableItem = ({ data, isLoading }: Props) => {
return (
<Tr>
<Td>
<AddressEntity
address={ data.address }
isLoading={ isLoading }
query={{ tab: 'contract' }}
noCopy
mt={ 1 }
/>
<Flex alignItems="center" mt={ 1 }>
<AddressEntity
address={ data.address }
isLoading={ isLoading }
query={{ tab: 'contract' }}
noCopy
/>
{ data.certified && <ContractCertifiedLabel iconSize={ 5 } boxSize={ 5 } ml={ 2 }/> }
</Flex>
<Flex alignItems="center" ml={ 7 }>
<Skeleton isLoaded={ !isLoading } color="text_secondary" my={ 1 }>
<HashStringShorten hash={ data.address.hash } isTooltipDisabled/>
Expand Down

0 comments on commit 0372c41

Please sign in to comment.