Commit f32bcfe6 authored by tom's avatar tom

contract code

parent 2a01b94b
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
"apps": "/apps", "apps": "/apps",
"app_index": "/apps/:id", "app_index": "/apps/:id",
"search_results": "/search-results", "search_results": "/search-results",
"other": "/search-results",
"auth": "/auth/auth0", "auth": "/auth/auth0",
"stats": "/stats" "stats": "/stats",
"visualize_sol2uml": "/visualize/sol2uml"
} }
...@@ -94,9 +94,9 @@ export const ROUTES = { ...@@ -94,9 +94,9 @@ export const ROUTES = {
pattern: PATHS.search_results, pattern: PATHS.search_results,
}, },
// ??? what URL will be here // VISUALIZE
other: { visualize_sol2uml: {
pattern: PATHS.other, pattern: PATHS.visualize_sol2uml,
}, },
// AUTH // AUTH
......
...@@ -10,4 +10,6 @@ export interface SmartContract { ...@@ -10,4 +10,6 @@ export interface SmartContract {
name: string | null; name: string | null;
verified_at: string | null; verified_at: string | null;
is_verified: boolean | null; is_verified: boolean | null;
source_code: string | null;
can_be_visualized_via_sol2uml: boolean | null;
} }
import { Flex, Skeleton, Button, Grid, GridItem, Text } from '@chakra-ui/react'; import { Flex, Skeleton, Button, Grid, GridItem, Text } from '@chakra-ui/react';
import dynamic from 'next/dynamic';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
...@@ -7,10 +8,15 @@ import link from 'lib/link/link'; ...@@ -7,10 +8,15 @@ import link from 'lib/link/link';
import DataFetchAlert from 'ui/shared/DataFetchAlert'; import DataFetchAlert from 'ui/shared/DataFetchAlert';
import RawDataSnippet from 'ui/shared/RawDataSnippet'; import RawDataSnippet from 'ui/shared/RawDataSnippet';
const DynamicContractSourceCode = dynamic(
() => import('./ContractSourceCode'),
{ ssr: false },
);
const InfoItem = ({ label, value }: { label: string; value: string }) => ( const InfoItem = ({ label, value }: { label: string; value: string }) => (
<GridItem display="flex" columnGap={ 6 }> <GridItem display="flex" columnGap={ 6 }>
<Text w="170px" fontWeight={ 500 }>{ label }</Text> <Text w="170px" flexShrink={ 0 } fontWeight={ 500 }>{ label }</Text>
<Text>{ value }</Text> <Text wordBreak="break-all">{ value }</Text>
</GridItem> </GridItem>
); );
...@@ -60,16 +66,23 @@ const ContractCode = () => { ...@@ -60,16 +66,23 @@ const ContractCode = () => {
return ( return (
<> <>
{ data.is_verified && ( { data.is_verified && (
<Grid templateColumns="1fr 1fr" rowGap={ 4 } columnGap={ 6 } mb={ 8 }> <Grid templateColumns={{ base: '1fr', lg: '1fr 1fr' }} rowGap={ 4 } columnGap={ 6 } mb={ 8 }>
{ data.name && <InfoItem label="Contract name" value={ data.name }/> } { data.name && <InfoItem label="Contract name" value={ data.name }/> }
{ data.compiler_version && <InfoItem label="Compiler version" value={ data.compiler_version }/> } { data.compiler_version && <InfoItem label="Compiler version" value={ data.compiler_version }/> }
{ data.evm_version && <InfoItem label="EVM version" value={ data.evm_version }/> } { data.evm_version && <InfoItem label="EVM version" value={ data.evm_version }/> }
{ data.optimization_enabled && <InfoItem label="Optimization enabled" value={ data.optimization_enabled ? 'true' : 'false' }/> } { typeof data.optimization_enabled === 'boolean' && <InfoItem label="Optimization enabled" value={ data.optimization_enabled ? 'true' : 'false' }/> }
{ data.optimization_runs && <InfoItem label="Optimization runs" value={ String(data.optimization_runs) }/> } { data.optimization_runs && <InfoItem label="Optimization runs" value={ String(data.optimization_runs) }/> }
{ data.verified_at && <InfoItem label="Verified at" value={ data.verified_at }/> } { data.verified_at && <InfoItem label="Verified at" value={ data.verified_at }/> }
</Grid> </Grid>
) } ) }
<Flex flexDir="column" rowGap={ 6 }> <Flex flexDir="column" rowGap={ 6 }>
{ data.source_code && (
<DynamicContractSourceCode
data={ data.source_code }
hasSol2Yml={ Boolean(data.can_be_visualized_via_sol2uml) }
address={ router.query.id?.toString() }
/>
) }
{ data.abi && ( { data.abi && (
<RawDataSnippet <RawDataSnippet
data={ JSON.stringify(data.abi) } data={ JSON.stringify(data.abi) }
......
import { Box, Flex, Link, Text, Tooltip } from '@chakra-ui/react';
import React from 'react';
import link from 'lib/link/link';
import CodeEditor from 'ui/shared/CodeEditor';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
interface Props {
data: string;
hasSol2Yml: boolean;
address?: string;
}
const ContractSourceCode = ({ data, hasSol2Yml, address }: Props) => {
return (
<Box>
<Flex justifyContent="space-between" alignItems="center" mb={ 3 }>
<Text fontWeight={ 500 }>Contract source code</Text>
{ hasSol2Yml && address && (
<Tooltip label="Visualize contract code using Sol2Uml JS library">
<Link
href={ link('visualize_sol2uml', undefined, { address }) }
ml="auto"
mr={ 3 }
>
View Sol2uml
</Link>
</Tooltip>
) }
<CopyToClipboard text={ data }/>
</Flex>
<CodeEditor value={ data } id="source_code"/>
</Box>
);
};
export default React.memo(ContractSourceCode);
import { chakra, useColorModeValue } from '@chakra-ui/react';
import React from 'react';
import AceEditor from 'react-ace';
import 'ace-builds/src-noconflict/mode-javascript';
import 'ace-builds/src-noconflict/theme-tomorrow';
import 'ace-builds/src-noconflict/theme-tomorrow_night';
import 'ace-builds/src-noconflict/ext-language_tools';
interface Props {
id: string;
value: string;
className?: string;
}
const CodeEditorBase = chakra(({ id, value, className }: Props) => {
const theme = useColorModeValue('tomorrow', 'tomorrow_night');
return (
<AceEditor
className={ className }
mode="javascript" // TODO need to find mode for solidity
theme={ theme }
value={ value }
name={ id }
editorProps={{ $blockScrolling: true }}
readOnly
width="100%"
showPrintMargin={ false }
maxLines={ 25 }
/>
);
});
const CodeEditor = ({ id, value }: Props) => {
// see theme/components/Textarea.ts variantFilledInactive
const bgColor = useColorModeValue('#f5f5f6', '#1a1b1b');
const gutterBgColor = useColorModeValue('gray.100', '#25282c');
return (
<CodeEditorBase
id={ id }
value={ value }
bgColor={ bgColor }
borderRadius="md"
overflow="hidden"
sx={{
'.ace_gutter': {
backgroundColor: gutterBgColor,
},
}}
/>
);
};
export default React.memo(CodeEditor);
...@@ -3864,6 +3864,11 @@ abort-controller@^3.0.0: ...@@ -3864,6 +3864,11 @@ abort-controller@^3.0.0:
dependencies: dependencies:
event-target-shim "^5.0.0" event-target-shim "^5.0.0"
ace-builds@^1.14.0, ace-builds@^1.4.14:
version "1.14.0"
resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.14.0.tgz#85a6733b4fa17b0abc3dbfe38cd8d823cad79716"
integrity sha512-3q8LvawomApRCt4cC0OzxVjDsZ609lDbm8l0Xl9uqG06dKEq4RT0YXLUyk7J2SxmqIp5YXzZNw767Dr8GKUruw==
acorn-globals@^7.0.0: acorn-globals@^7.0.0:
version "7.0.1" version "7.0.1"
resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-7.0.1.tgz#0dbf05c44fa7c94332914c02066d5beff62c40c3" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-7.0.1.tgz#0dbf05c44fa7c94332914c02066d5beff62c40c3"
...@@ -5012,6 +5017,11 @@ detect-node-es@^1.1.0: ...@@ -5012,6 +5017,11 @@ detect-node-es@^1.1.0:
resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493"
integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==
diff-match-patch@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37"
integrity sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==
diff-sequences@^29.3.1: diff-sequences@^29.3.1:
version "29.3.1" version "29.3.1"
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.3.1.tgz#104b5b95fe725932421a9c6e5b4bef84c3f2249e" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.3.1.tgz#104b5b95fe725932421a9c6e5b4bef84c3f2249e"
...@@ -7244,6 +7254,16 @@ lodash.debounce@^4.0.8: ...@@ -7244,6 +7254,16 @@ lodash.debounce@^4.0.8:
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
lodash.get@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
lodash.memoize@4.x: lodash.memoize@4.x:
version "4.1.2" version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
...@@ -8035,6 +8055,17 @@ quick-format-unescaped@^4.0.3: ...@@ -8035,6 +8055,17 @@ quick-format-unescaped@^4.0.3:
resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7"
integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==
react-ace@^10.1.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-10.1.0.tgz#d348eac2b16475231779070b6cd16768deed565f"
integrity sha512-VkvUjZNhdYTuKOKQpMIZi7uzZZVgzCjM7cLYu6F64V0mejY8a2XTyPUIMszC6A4trbeMIHbK5fYFcT/wkP/8VA==
dependencies:
ace-builds "^1.4.14"
diff-match-patch "^1.0.5"
lodash.get "^4.4.2"
lodash.isequal "^4.5.0"
prop-types "^15.7.2"
react-clientside-effect@^1.2.6: react-clientside-effect@^1.2.6:
version "1.2.6" version "1.2.6"
resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz#29f9b14e944a376b03fb650eed2a754dd128ea3a" resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz#29f9b14e944a376b03fb650eed2a754dd128ea3a"
......
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