Files
explore/ui/address/contract/ContractDetailsDeployedByteCode.tsx

104 lines
3.4 KiB
TypeScript

import React from 'react';
import type { Address } from 'types/api/address';
import config from 'configs/app';
import hexToUtf8 from 'lib/hexToUtf8';
import type { SelectOption } from '@luxfi/ui/select';
import { createListCollection, Select } from '@luxfi/ui/select';
import { Skeleton } from '@luxfi/ui/skeleton';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import RawDataSnippet from 'ui/shared/RawDataSnippet';
import ContractDetailsVerificationButton from './ContractDetailsVerificationButton';
const OPTIONS = [
{ label: 'Hex', value: 'Hex' as const },
{ label: 'UTF-8', value: 'UTF-8' as const },
];
const collection = createListCollection<SelectOption>({
items: OPTIONS,
});
export type DataType = (typeof OPTIONS)[number]['value'];
interface Props {
bytecode: string;
isLoading: boolean;
addressData: Address;
showVerificationButton?: boolean;
}
const ContractDetailsDeployedByteCode = ({ bytecode, isLoading: isLoadingProp, addressData, showVerificationButton }: Props) => {
const [ isLoading, setIsLoading ] = React.useState(isLoadingProp);
const [ showSelect, setShowSelect ] = React.useState(false);
const [ selectedDataType, setSelectedDataType ] = React.useState<Array<DataType>>([ 'Hex' ]);
React.useEffect(() => {
if (!isLoadingProp) {
if (config.UI.views.address.decodedBytecodeEnabled && !addressData.is_verified) {
// we don't want to decode the whole bytecode here
// the "scilla_version" should appear somewhere in the beginning of the bytecode
// but there could be some comments of arbitrary length before it
// adjust the value if needed
const SYMBOLS_TO_CHECK = 500;
const decodedBytecode = hexToUtf8(bytecode.slice(0, SYMBOLS_TO_CHECK * 2 + 2));
const isScillaSourceCode = decodedBytecode.includes('scilla_version 0');
if (isScillaSourceCode) {
setShowSelect(true);
setSelectedDataType([ 'UTF-8' ]);
}
}
}
setIsLoading(isLoadingProp);
}, [ isLoadingProp, bytecode, addressData.is_verified ]);
const handleSelectValueChange = React.useCallback(({ value }: { value: Array<string> }) => {
setSelectedDataType(value as Array<DataType>);
}, []);
const content = selectedDataType[0] === 'UTF-8' ? hexToUtf8(bytecode) : bytecode;
const beforeSlot = (
<div className="flex items-center flex-wrap mb-3 gap-x-3 gap-y-1">
<Skeleton fontWeight={ 500 } loading={ isLoading }>Deployed bytecode</Skeleton>
<div className="flex items-center grow">
{ showSelect && (
<Select
collection={ collection }
placeholder="Select type"
value={ selectedDataType }
onValueChange={ handleSelectValueChange }
w="100px"
loading={ isLoading }
/>
) }
{ showVerificationButton && (
<ContractDetailsVerificationButton
isLoading={ isLoading }
addressHash={ addressData.hash }
ml="auto"
mr={ 3 }
/>
) }
<CopyToClipboard text={ content } isLoading={ isLoading } ml={ showVerificationButton ? 0 : 'auto' }/>
</div>
</div>
);
return (
<RawDataSnippet
data={ content }
beforeSlot={ beforeSlot }
textareaMaxHeight="300px"
isLoading={ isLoading }
showCopy={ false }
/>
);
};
export default React.memo(ContractDetailsDeployedByteCode);