Commit 0dd6087f authored by tom goriunov's avatar tom goriunov Committed by GitHub

Remove `proxy_type` field from SmartContract model (#2671)

* remove `proxy_type` field from SmartContract model

* fix ts
parent c9894eb8
......@@ -43,7 +43,6 @@ export const verified: SmartContract = {
file_path: '',
additional_sources: [],
verified_twin_address_hash: null,
proxy_type: null,
};
export const certified: SmartContract = {
......@@ -85,7 +84,6 @@ export const withProxyAddress: SmartContract = {
...verified,
is_verified: false,
verified_twin_address_hash: '0xa62744bee8646e237441cdbfdedd3458861748a8',
proxy_type: 'eip1967',
};
export const selfDestructed: SmartContract = {
......@@ -146,7 +144,6 @@ export const nonVerified: SmartContract = {
additional_sources: [],
external_libraries: null,
verified_twin_address_hash: null,
proxy_type: null,
language: null,
license_type: null,
};
......@@ -69,7 +69,6 @@ export interface SmartContract {
};
verified_twin_address_hash: string | null;
verified_twin_filecoin_robust_address?: string | null;
proxy_type: SmartContractProxyType | null;
language: string | null;
license_type: SmartContractLicenseType | null;
certified?: boolean;
......
......@@ -6,7 +6,7 @@ import type { Channel } from 'phoenix';
import React from 'react';
import type { SocketMessage } from 'lib/socket/types';
import type { Address as AddressInfo } from 'types/api/address';
import type { Address } from 'types/api/address';
import type { AddressImplementation } from 'types/api/addressParams';
import type { SmartContract } from 'types/api/contract';
......@@ -27,30 +27,29 @@ const TAB_LIST_PROPS = { flexWrap: 'wrap', rowGap: 2 };
const LEFT_SLOT_PROPS = { w: { base: '100%', lg: 'auto' } };
type Props = {
addressHash: string;
addressData: Address;
channel: Channel | undefined;
mainContractQuery: UseQueryResult<SmartContract, ResourceError>;
};
const ContractDetails = ({ addressHash, channel, mainContractQuery }: Props) => {
const ContractDetails = ({ addressData, channel, mainContractQuery }: Props) => {
const router = useRouter();
const sourceAddress = getQueryParamString(router.query.source_address);
const queryClient = useQueryClient();
const addressInfo = queryClient.getQueryData<AddressInfo>(getResourceKey('address', { pathParams: { hash: addressHash } }));
const sourceItems: Array<AddressImplementation> = React.useMemo(() => {
const currentAddressDefaultName = addressInfo?.proxy_type === 'eip7702' ? 'Current address' : 'Current contract';
const currentAddressItem = { address: addressHash, name: addressInfo?.name || currentAddressDefaultName };
if (!addressInfo || !addressInfo.implementations || addressInfo.implementations.length === 0) {
const currentAddressDefaultName = addressData?.proxy_type === 'eip7702' ? 'Current address' : 'Current contract';
const currentAddressItem = { address: addressData.hash, name: addressData?.name || currentAddressDefaultName };
if (!addressData || !addressData.implementations || addressData.implementations.length === 0) {
return [ currentAddressItem ];
}
return [
currentAddressItem,
...(addressInfo?.implementations.filter((item) => item.address !== addressHash && item.name) || []),
...(addressData?.implementations.filter((item) => item.address !== addressData.hash && item.name) || []),
];
}, [ addressInfo, addressHash ]);
}, [ addressData ]);
const [ selectedItem, setSelectedItem ] = React.useState(sourceItems.find((item) => item.address === sourceAddress) || sourceItems[0]);
......@@ -59,21 +58,21 @@ const ContractDetails = ({ addressHash, channel, mainContractQuery }: Props) =>
queryOptions: {
enabled: Boolean(selectedItem?.address && !mainContractQuery.isPlaceholderData),
refetchOnMount: false,
placeholderData: addressInfo?.is_verified ? stubs.CONTRACT_CODE_VERIFIED : stubs.CONTRACT_CODE_UNVERIFIED,
placeholderData: addressData?.is_verified ? stubs.CONTRACT_CODE_VERIFIED : stubs.CONTRACT_CODE_UNVERIFIED,
},
});
const { data, isPlaceholderData, isError } = contractQuery;
const tabs = useContractDetailsTabs({ data, isLoading: isPlaceholderData, addressHash, sourceAddress: selectedItem.address });
const tabs = useContractDetailsTabs({ data, isLoading: isPlaceholderData, addressData, sourceAddress: selectedItem.address });
const handleContractWasVerifiedMessage: SocketMessage.SmartContractWasVerified['handler'] = React.useCallback(() => {
queryClient.refetchQueries({
queryKey: getResourceKey('address', { pathParams: { hash: addressHash } }),
queryKey: getResourceKey('address', { pathParams: { hash: addressData.hash } }),
});
queryClient.refetchQueries({
queryKey: getResourceKey('contract', { pathParams: { hash: addressHash } }),
queryKey: getResourceKey('contract', { pathParams: { hash: addressData.hash } }),
});
}, [ addressHash, queryClient ]);
}, [ addressData.hash, queryClient ]);
useSocketMessage({
channel,
......@@ -101,14 +100,14 @@ const ContractDetails = ({ addressHash, channel, mainContractQuery }: Props) =>
<ContractDetailsAlerts
data={ mainContractQuery.data }
isLoading={ mainContractQuery.isPlaceholderData }
addressHash={ addressHash }
addressData={ addressData }
channel={ channel }
/>
{ mainContractQuery.data?.is_verified && (
<ContractDetailsInfo
data={ mainContractQuery.data }
isLoading={ mainContractQuery.isPlaceholderData }
addressHash={ addressHash }
addressHash={ addressData.hash }
/>
) }
{ tabs.length > 1 ? (
......
......@@ -5,16 +5,16 @@ import { test, expect } from 'playwright/lib';
import ContractDetailsAlertProxyPattern from './ContractDetailsAlertProxyPattern';
test('proxy type with link +@mobile', async({ render }) => {
const component = await render(<ContractDetailsAlertProxyPattern type="eip1167"/>);
const component = await render(<ContractDetailsAlertProxyPattern type="eip1167" isLoading={ false }/>);
await expect(component).toHaveScreenshot();
});
test('proxy type with link but without description', async({ render }) => {
const component = await render(<ContractDetailsAlertProxyPattern type="master_copy"/>);
const component = await render(<ContractDetailsAlertProxyPattern type="master_copy" isLoading={ false }/>);
await expect(component).toHaveScreenshot();
});
test('proxy type without link', async({ render }) => {
const component = await render(<ContractDetailsAlertProxyPattern type="basic_implementation"/>);
const component = await render(<ContractDetailsAlertProxyPattern type="basic_implementation" isLoading={ false }/>);
await expect(component).toHaveScreenshot();
});
......@@ -7,6 +7,7 @@ import { Link } from 'toolkit/chakra/link';
interface Props {
type: NonNullable<SmartContractProxyType>;
isLoading: boolean;
}
const PROXY_TYPES: Partial<Record<NonNullable<SmartContractProxyType>, {
......@@ -62,7 +63,7 @@ const PROXY_TYPES: Partial<Record<NonNullable<SmartContractProxyType>, {
},
};
const ContractCodeProxyPattern = ({ type }: Props) => {
const ContractCodeProxyPattern = ({ type, isLoading }: Props) => {
const proxyInfo = PROXY_TYPES[type];
if (!proxyInfo || type === 'unknown') {
......@@ -70,7 +71,7 @@ const ContractCodeProxyPattern = ({ type }: Props) => {
}
return (
<Alert status="warning" whiteSpace="pre-wrap">
<Alert status="warning" whiteSpace="pre-wrap" loading={ isLoading }>
{ proxyInfo.link ? (
<>
This proxy smart-contract is detected via <Link href={ proxyInfo.link } external>{ proxyInfo.name }</Link>
......
......@@ -15,7 +15,7 @@ test('verified with changed byte code socket', async({ render, createSocket }) =
const props = {
data: contractMock.verified,
isLoading: false,
addressHash: addressMock.contract.hash,
addressData: addressMock.contract,
};
const component = await render(<ContractDetailsAlerts { ...props }/>, undefined, { withSocket: true });
const socket = await createSocket();
......@@ -29,7 +29,7 @@ test('verified via sourcify', async({ render }) => {
const props = {
data: contractMock.verifiedViaSourcify,
isLoading: false,
addressHash: addressMock.contract.hash,
addressData: addressMock.contract,
};
const component = await render(<ContractDetailsAlerts { ...props }/>, undefined, { withSocket: true });
......@@ -40,7 +40,7 @@ test('verified via eth bytecode db', async({ render }) => {
const props = {
data: contractMock.verifiedViaEthBytecodeDb,
isLoading: false,
addressHash: addressMock.contract.hash,
addressData: addressMock.contract,
};
const component = await render(<ContractDetailsAlerts { ...props }/>, undefined, { withSocket: true });
......@@ -51,7 +51,7 @@ test('with twin address alert +@mobile', async({ render }) => {
const props = {
data: contractMock.withTwinAddress,
isLoading: false,
addressHash: addressMock.contract.hash,
addressData: addressMock.contract,
};
const component = await render(<ContractDetailsAlerts { ...props }/>, undefined, { withSocket: true });
......
......@@ -7,7 +7,7 @@ import ContractDetailsAlerts from './ContractDetailsAlerts';
const ContractDetailsAlertsPwStory = (props: Props) => {
const channel = useSocketChannel({
topic: `addresses:${ props.addressHash.toLowerCase() }`,
topic: `addresses:${ props.addressData.hash.toLowerCase() }`,
isDisabled: false,
});
......
......@@ -3,6 +3,7 @@ import type { Channel } from 'phoenix';
import React from 'react';
import type { SocketMessage } from 'lib/socket/types';
import type { Address } from 'types/api/address';
import type { SmartContract } from 'types/api/contract';
import { route } from 'nextjs-routes';
......@@ -10,7 +11,6 @@ import { route } from 'nextjs-routes';
import useSocketMessage from 'lib/socket/useSocketMessage';
import { Alert } from 'toolkit/chakra/alert';
import { Link } from 'toolkit/chakra/link';
import { Skeleton } from 'toolkit/chakra/skeleton';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import ContractDetailsVerificationButton from '../ContractDetailsVerificationButton';
......@@ -20,11 +20,11 @@ import ContractDetailsAlertVerificationSource from './ContractDetailsAlertVerifi
export interface Props {
data: SmartContract | undefined;
isLoading: boolean;
addressHash: string;
addressData: Address;
channel?: Channel;
}
const ContractDetailsAlerts = ({ data, isLoading, addressHash, channel }: Props) => {
const ContractDetailsAlerts = ({ data, isLoading, addressData, channel }: Props) => {
const [ isChangedBytecodeSocket, setIsChangedBytecodeSocket ] = React.useState<boolean>();
const handleChangedBytecodeMessage: SocketMessage.AddressChangedBytecode['handler'] = React.useCallback(() => {
......@@ -48,20 +48,18 @@ const ContractDetailsAlerts = ({ data, isLoading, addressHash, channel }: Props)
</Box>
) }
{ data?.is_verified && (
<Skeleton loading={ isLoading }>
<Alert status="success" descriptionProps={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 3, columnGap: 5 }}>
<Alert status="success" loading={ isLoading } descriptionProps={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 3, columnGap: 5 }}>
<span>Contract Source Code Verified ({ data.is_partially_verified ? 'Partial' : 'Exact' } Match)</span>
{
data.is_partially_verified ? (
<ContractDetailsVerificationButton
isLoading={ isLoading }
addressHash={ addressHash }
addressHash={ addressData.hash }
isPartiallyVerified
/>
) : null
}
</Alert>
</Skeleton>
) }
<ContractDetailsAlertVerificationSource data={ data }/>
{ (data?.is_changed_bytecode || isChangedBytecodeSocket) && (
......@@ -69,7 +67,7 @@ const ContractDetailsAlerts = ({ data, isLoading, addressHash, channel }: Props)
Warning! Contract bytecode has been changed and does not match the verified one. Therefore, interaction with this smart contract may be risky.
</Alert>
) }
{ !data?.is_verified && data?.verified_twin_address_hash && (!data?.proxy_type || data.proxy_type === 'unknown') && (
{ !data?.is_verified && data?.verified_twin_address_hash && (!addressData.proxy_type || addressData.proxy_type === 'unknown') && (
<Alert status="warning" whiteSpace="pre-wrap">
<span>Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB </span>
<AddressEntity
......@@ -79,13 +77,13 @@ const ContractDetailsAlerts = ({ data, isLoading, addressHash, channel }: Props)
fontWeight="500"
/>
<chakra.span mt={ 1 }>All functions displayed below are from ABI of that contract. In order to verify current contract, proceed with </chakra.span>
<Link href={ route({ pathname: '/address/[hash]/contract-verification', query: { hash: addressHash } }) }>
<Link href={ route({ pathname: '/address/[hash]/contract-verification', query: { hash: addressData.hash } }) }>
Verify & Publish
</Link>
<span> page</span>
</Alert>
) }
{ data?.proxy_type && <ContractDetailsAlertProxyPattern type={ data.proxy_type }/> }
{ addressData.proxy_type && <ContractDetailsAlertProxyPattern type={ addressData.proxy_type } isLoading={ isLoading }/> }
</Flex>
);
};
......
import { Flex } from '@chakra-ui/react';
import React from 'react';
import type { Address } from 'types/api/address';
import type { SmartContract } from 'types/api/contract';
import { Alert } from 'toolkit/chakra/alert';
......@@ -21,19 +22,19 @@ interface Tab {
interface Props {
data: SmartContract | undefined;
isLoading: boolean;
addressHash: string;
addressData: Address;
sourceAddress: string;
}
export default function useContractDetailsTabs({ data, isLoading, addressHash, sourceAddress }: Props): Array<Tab> {
export default function useContractDetailsTabs({ data, isLoading, addressData, sourceAddress }: Props): Array<Tab> {
const canBeVerified = !data?.is_self_destructed && !data?.is_verified && data?.proxy_type !== 'eip7702';
const canBeVerified = !data?.is_self_destructed && !data?.is_verified && addressData?.proxy_type !== 'eip7702';
return React.useMemo(() => {
const verificationButton = (
<ContractDetailsVerificationButton
isLoading={ isLoading }
addressHash={ addressHash }
addressHash={ addressData.hash }
isPartiallyVerified={ Boolean(data?.is_partially_verified) }
/>
);
......@@ -117,5 +118,5 @@ export default function useContractDetailsTabs({ data, isLoading, addressHash, s
),
} : undefined,
].filter(Boolean);
}, [ isLoading, addressHash, data, sourceAddress, canBeVerified ]);
}, [ isLoading, addressData, data, sourceAddress, canBeVerified ]);
}
......@@ -74,10 +74,10 @@ export default function useContractTabs(data: Address | undefined, isPlaceholder
return React.useMemo(() => {
return {
tabs: [
data?.hash && {
data && {
id: 'contract_code' as const,
title: 'Code',
component: <ContractDetails mainContractQuery={ contractQuery } channel={ channel } addressHash={ data.hash }/>,
component: <ContractDetails mainContractQuery={ contractQuery } channel={ channel } addressData={ data }/>,
subTabs: CONTRACT_DETAILS_TAB_IDS as unknown as Array<string>,
},
contractQuery.data?.abi && {
......@@ -92,7 +92,7 @@ export default function useContractTabs(data: Address | undefined, isPlaceholder
<ContractMethodsProxy
implementations={ verifiedImplementations }
isLoading={ contractQuery.isPlaceholderData }
proxyType={ contractQuery.data?.proxy_type }
proxyType={ data?.proxy_type }
/>
),
},
......@@ -112,7 +112,7 @@ export default function useContractTabs(data: Address | undefined, isPlaceholder
isLoading: contractQuery.isPlaceholderData,
};
}, [
data?.hash,
data,
contractQuery,
channel,
verifiedImplementations,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment