From f6ed30db54829483b345f3ad04c14abc00e70caf Mon Sep 17 00:00:00 2001 From: Kristof Csillag Date: Wed, 28 Jun 2023 13:11:23 +0200 Subject: [PATCH 1/8] Rename some components for clarity --- src/app/components/Account/ShowMoreTokensLink.tsx | 2 +- src/app/components/Account/index.tsx | 2 +- .../{TokensCard.tsx => AccountTokensCard.tsx} | 4 ++-- ...nsactionsCard.tsx => AccountTransactionsCard.tsx} | 2 +- src/app/pages/AccountDetailsPage/index.tsx | 2 +- src/routes.tsx | 12 ++++++------ 6 files changed, 12 insertions(+), 12 deletions(-) rename src/app/pages/AccountDetailsPage/{TokensCard.tsx => AccountTokensCard.tsx} (96%) rename src/app/pages/AccountDetailsPage/{TransactionsCard.tsx => AccountTransactionsCard.tsx} (97%) diff --git a/src/app/components/Account/ShowMoreTokensLink.tsx b/src/app/components/Account/ShowMoreTokensLink.tsx index cfb1cc83f1..eae2d93b9b 100644 --- a/src/app/components/Account/ShowMoreTokensLink.tsx +++ b/src/app/components/Account/ShowMoreTokensLink.tsx @@ -5,7 +5,7 @@ import { styled } from '@mui/material/styles' import { COLORS } from '../../../styles/theme/colors' import { EvmTokenType, RuntimeAccount, type Token } from '../../../oasis-indexer/api' import { RouteUtils } from '../../utils/route-utils' -import { accountTokenContainerId } from '../../pages/AccountDetailsPage/TokensCard' +import { accountTokenContainerId } from '../../pages/AccountDetailsPage/AccountTokensCard' export const StyledLink = styled(RouterLink)(({ theme }) => ({ color: COLORS.brandDark, diff --git a/src/app/components/Account/index.tsx b/src/app/components/Account/index.tsx index 2123d4d1ef..6e756562d2 100644 --- a/src/app/components/Account/index.tsx +++ b/src/app/components/Account/index.tsx @@ -14,7 +14,7 @@ import { type RuntimeAccount } from '../../../oasis-indexer/api' import { TokenPills } from './TokenPills' import { AccountLink } from './AccountLink' import { RouteUtils } from '../../utils/route-utils' -import { accountTransactionsContainerId } from '../../pages/AccountDetailsPage/TransactionsCard' +import { accountTransactionsContainerId } from '../../pages/AccountDetailsPage/AccountTransactionsCard' import Link from '@mui/material/Link' import { DashboardLink } from '../../pages/DashboardPage/DashboardLink' import { getNameForTicker, Ticker } from '../../../types/ticker' diff --git a/src/app/pages/AccountDetailsPage/TokensCard.tsx b/src/app/pages/AccountDetailsPage/AccountTokensCard.tsx similarity index 96% rename from src/app/pages/AccountDetailsPage/TokensCard.tsx rename to src/app/pages/AccountDetailsPage/AccountTokensCard.tsx index 0b7120d692..5b199d9eb1 100644 --- a/src/app/pages/AccountDetailsPage/TokensCard.tsx +++ b/src/app/pages/AccountDetailsPage/AccountTokensCard.tsx @@ -16,13 +16,13 @@ import { ScrollingDiv } from '../../components/PageLayout/ScrollingDiv' import { useRequiredScopeParam } from '../../hooks/useScopeParam' import { useAccount } from './hook' -type TokensCardProps = { +type AccountTokensCardProps = { type: EvmTokenType } export const accountTokenContainerId = 'tokens' -export const TokensCard: FC = ({ type }) => { +export const AccountTokensCard: FC = ({ type }) => { const scope = useRequiredScopeParam() const address = useLoaderData() as string const { t } = useTranslation() diff --git a/src/app/pages/AccountDetailsPage/TransactionsCard.tsx b/src/app/pages/AccountDetailsPage/AccountTransactionsCard.tsx similarity index 97% rename from src/app/pages/AccountDetailsPage/TransactionsCard.tsx rename to src/app/pages/AccountDetailsPage/AccountTransactionsCard.tsx index 58f33ced99..6a4cfc4b20 100644 --- a/src/app/pages/AccountDetailsPage/TransactionsCard.tsx +++ b/src/app/pages/AccountDetailsPage/AccountTransactionsCard.tsx @@ -14,7 +14,7 @@ import { useLoaderData } from 'react-router-dom' export const accountTransactionsContainerId = 'transactions' -export const TransactionsCard: FC = () => { +export const AccountTransactionsCard: FC = () => { const { t } = useTranslation() const scope = useRequiredScopeParam() const address = useLoaderData() as string diff --git a/src/app/pages/AccountDetailsPage/index.tsx b/src/app/pages/AccountDetailsPage/index.tsx index fdd34f9169..84497d0833 100644 --- a/src/app/pages/AccountDetailsPage/index.tsx +++ b/src/app/pages/AccountDetailsPage/index.tsx @@ -9,7 +9,7 @@ import { TokenPriceInfo, useTokenPrice } from '../../../coin-gecko/api' import { Ticker } from '../../../types/ticker' import { EvmTokenType, RuntimeAccount } from '../../../oasis-indexer/api' -import { accountTokenContainerId } from './TokensCard' +import { accountTokenContainerId } from './AccountTokensCard' import { useAccount } from './hook' import { useRequiredScopeParam } from '../../hooks/useScopeParam' import { showEmptyAccountDetails } from '../../../config' diff --git a/src/routes.tsx b/src/routes.tsx index 3ed25d45d6..7312b5275d 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -6,8 +6,8 @@ import { TransactionDetailPage } from './app/pages/TransactionDetailPage' import { DashboardPage } from './app/pages/DashboardPage' import { BlockDetailPage } from './app/pages/BlockDetailPage' import { AccountDetailsPage } from './app/pages/AccountDetailsPage' -import { TransactionsCard } from './app/pages/AccountDetailsPage/TransactionsCard' -import { TokensCard } from './app/pages/AccountDetailsPage/TokensCard' +import { AccountTransactionsCard } from './app/pages/AccountDetailsPage/AccountTransactionsCard' +import { AccountTokensCard } from './app/pages/AccountDetailsPage/AccountTokensCard' import { SearchResultsPage } from './app/pages/SearchResultsPage' import { addressParamLoader, @@ -78,12 +78,12 @@ export const routes: RouteObject[] = [ children: [ { path: '', - element: , + element: , loader: addressParamLoader, }, { path: 'tokens/erc-20', - element: , + element: , loader: addressParamLoader, }, ], @@ -108,12 +108,12 @@ export const routes: RouteObject[] = [ children: [ { path: '', - element: , + element: , loader: addressParamLoader, }, { path: 'tokens/erc-20', - element: , + element: , loader: addressParamLoader, }, ], From dc6958def13252ca96a28e619780d58745027f6e Mon Sep 17 00:00:00 2001 From: Kristof Csillag Date: Wed, 28 Jun 2023 13:12:47 +0200 Subject: [PATCH 2/8] Rename some hooks for clarity --- .../pages/AccountDetailsPage/AccountTransactionsCard.tsx | 8 +++----- src/app/pages/AccountDetailsPage/hook.ts | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/app/pages/AccountDetailsPage/AccountTransactionsCard.tsx b/src/app/pages/AccountDetailsPage/AccountTransactionsCard.tsx index 6a4cfc4b20..5bd8fe9121 100644 --- a/src/app/pages/AccountDetailsPage/AccountTransactionsCard.tsx +++ b/src/app/pages/AccountDetailsPage/AccountTransactionsCard.tsx @@ -8,7 +8,7 @@ import { NUMBER_OF_ITEMS_ON_SEPARATE_PAGE } from '../../config' import { ErrorBoundary } from '../../components/ErrorBoundary' import { ScrollingDiv } from '../../components/PageLayout/ScrollingDiv' import { CardEmptyState } from './CardEmptyState' -import { useTransactions } from './hook' +import { useAccountTransactions } from './hook' import { useRequiredScopeParam } from '../../hooks/useScopeParam' import { useLoaderData } from 'react-router-dom' @@ -19,10 +19,8 @@ export const AccountTransactionsCard: FC = () => { const scope = useRequiredScopeParam() const address = useLoaderData() as string - const { isLoading, isFetched, transactions, pagination, totalCount, isTotalCountClipped } = useTransactions( - scope, - address, - ) + const { isLoading, isFetched, transactions, pagination, totalCount, isTotalCountClipped } = + useAccountTransactions(scope, address) return ( diff --git a/src/app/pages/AccountDetailsPage/hook.ts b/src/app/pages/AccountDetailsPage/hook.ts index 4430e74b9b..1787bd5116 100644 --- a/src/app/pages/AccountDetailsPage/hook.ts +++ b/src/app/pages/AccountDetailsPage/hook.ts @@ -17,7 +17,7 @@ export const useAccount = (scope: SearchScope, address: string) => { return { account, isLoading, isError } } -export const useTransactions = (scope: SearchScope, address: string) => { +export const useAccountTransactions = (scope: SearchScope, address: string) => { const { network, layer } = scope const pagination = useSearchParamsPagination('page') const offset = (pagination.selectedPage - 1) * NUMBER_OF_ITEMS_ON_SEPARATE_PAGE From c2bd5e7ab539384cb2cd16cf674394eb37c63bca Mon Sep 17 00:00:00 2001 From: Kristof Csillag Date: Wed, 28 Jun 2023 13:22:58 +0200 Subject: [PATCH 3/8] Rename ERC-20 card to tokens --- src/app/pages/AccountDetailsPage/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/pages/AccountDetailsPage/index.tsx b/src/app/pages/AccountDetailsPage/index.tsx index 84497d0833..5ec84c6791 100644 --- a/src/app/pages/AccountDetailsPage/index.tsx +++ b/src/app/pages/AccountDetailsPage/index.tsx @@ -50,7 +50,7 @@ export const AccountDetailsPage: FC = () => { )} From 08655a97f1962b2137e44b9a370518d472debab8 Mon Sep 17 00:00:00 2001 From: Kristof Csillag Date: Wed, 28 Jun 2023 13:25:37 +0200 Subject: [PATCH 4/8] Update title on tokens card --- src/app/pages/AccountDetailsPage/AccountTokensCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/pages/AccountDetailsPage/AccountTokensCard.tsx b/src/app/pages/AccountDetailsPage/AccountTokensCard.tsx index 5b199d9eb1..78f9dcdd1d 100644 --- a/src/app/pages/AccountDetailsPage/AccountTokensCard.tsx +++ b/src/app/pages/AccountDetailsPage/AccountTokensCard.tsx @@ -28,7 +28,7 @@ export const AccountTokensCard: FC = ({ type }) => { const { t } = useTranslation() const locationHash = useLocation().hash.replace('#', '') const tokenLabel = t(`account.${type}` as any) - const tokenListLabel = t('account.tokensListTitle', { token: tokenLabel }) + const tokenListLabel = t('tokens.title') // TODO: re-enable when we want multiple token types again t('account.tokensListTitle', { token: tokenLabel }) const tableColumns: TableColProps[] = [ { key: 'name', content: t('common.name') }, { key: 'contract', content: t('common.smartContract') }, From 37efab7ff558cb3b64dbef6d91dedc89a8bcc32c Mon Sep 17 00:00:00 2001 From: Csillag Kristof Date: Thu, 29 Jun 2023 13:13:25 +0200 Subject: [PATCH 5/8] Use simple strings instead of JSX expressions, if possible --- src/app/components/LongDataDisplay/index.tsx | 7 +------ src/app/components/ParaTimePicker/LayerMenu.tsx | 2 +- src/app/components/RoundedBalance/__tests__/index.test.tsx | 2 +- src/app/components/Select/index.tsx | 2 +- src/app/components/TransactionStatusIcon/index.tsx | 2 +- src/app/components/Transactions/LogEvent.tsx | 2 +- src/app/pages/SearchResultsPage/NoResults.tsx | 2 +- .../SearchResultsPage/__tests__/SearchResultsList.test.tsx | 4 ++-- src/app/pages/SearchResultsPage/notifications.tsx | 2 +- src/app/pages/TransactionDetailPage/index.tsx | 2 +- 10 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/app/components/LongDataDisplay/index.tsx b/src/app/components/LongDataDisplay/index.tsx index 646d4a37bd..3f4ab14b08 100644 --- a/src/app/components/LongDataDisplay/index.tsx +++ b/src/app/components/LongDataDisplay/index.tsx @@ -27,12 +27,7 @@ export const LongDataDisplay: FC<{ data: string; threshold: number; fontWeight?: } return (
- setShowData(true)} - collapsedSize={'3em'} - > + setShowData(true)} collapsedSize="3em"> = ({ divider, lay const labels = getLayerLabels(t) return ( - + {/* Div is needed because we need an element with enabled pointer-events to make Tooltip work */}
diff --git a/src/app/components/RoundedBalance/__tests__/index.test.tsx b/src/app/components/RoundedBalance/__tests__/index.test.tsx index bd37208522..2c30229540 100644 --- a/src/app/components/RoundedBalance/__tests__/index.test.tsx +++ b/src/app/components/RoundedBalance/__tests__/index.test.tsx @@ -41,7 +41,7 @@ describe('RoundedBalance', () => { describe('RoundedRoseBalance', () => { it('should render value with ROSE ticker symbol', () => { - render() + render() expect(screen.getByText('0.00223… ROSE')).toBeInTheDocument() }) diff --git a/src/app/components/Select/index.tsx b/src/app/components/Select/index.tsx index b9abd39757..083baf43f4 100644 --- a/src/app/components/Select/index.tsx +++ b/src/app/components/Select/index.tsx @@ -85,7 +85,7 @@ const TertiaryButton = forwardRef( const { t } = useTranslation() return ( - + {children ? children : t('select.placeholder')} {ownerState.open ? : } diff --git a/src/app/components/TransactionStatusIcon/index.tsx b/src/app/components/TransactionStatusIcon/index.tsx index bb4ac9c93b..3291e0b42e 100644 --- a/src/app/components/TransactionStatusIcon/index.tsx +++ b/src/app/components/TransactionStatusIcon/index.tsx @@ -24,7 +24,7 @@ const statusFgColor: Record = { } const statusIcon: Record = { - unknown: , + unknown: , success: , failure: , } diff --git a/src/app/components/Transactions/LogEvent.tsx b/src/app/components/Transactions/LogEvent.tsx index 08d71f41fc..d8325a34f6 100644 --- a/src/app/components/Transactions/LogEvent.tsx +++ b/src/app/components/Transactions/LogEvent.tsx @@ -184,7 +184,7 @@ export const TransactionLogEvent: FC<{ return ( <> - {!isFirst && } + {!isFirst && } {decoded && ( <> diff --git a/src/app/pages/SearchResultsPage/NoResults.tsx b/src/app/pages/SearchResultsPage/NoResults.tsx index ffda1fe0a1..c59ee8a82b 100644 --- a/src/app/pages/SearchResultsPage/NoResults.tsx +++ b/src/app/pages/SearchResultsPage/NoResults.tsx @@ -36,7 +36,7 @@ export const NoResults: FC<{ i18nKey="search.noResults.description" components={{ OptionalBreak: , - HomeLink: , + HomeLink: , }} />

diff --git a/src/app/pages/SearchResultsPage/__tests__/SearchResultsList.test.tsx b/src/app/pages/SearchResultsPage/__tests__/SearchResultsList.test.tsx index f592977ebb..3ad8e96bb7 100644 --- a/src/app/pages/SearchResultsPage/__tests__/SearchResultsList.test.tsx +++ b/src/app/pages/SearchResultsPage/__tests__/SearchResultsList.test.tsx @@ -36,7 +36,7 @@ describe('SearchResultsView', () => { hasUsedCoinGecko: false, }, }} - title={'test search'} + title="test search" networkForTheme={Network.mainnet} />, ) @@ -59,7 +59,7 @@ describe('SearchResultsView', () => { renderWithProviders( void }> = ({ them - + ) diff --git a/src/app/pages/TransactionDetailPage/index.tsx b/src/app/pages/TransactionDetailPage/index.tsx index 78606f443e..a8c5d85b90 100644 --- a/src/app/pages/TransactionDetailPage/index.tsx +++ b/src/app/pages/TransactionDetailPage/index.tsx @@ -114,7 +114,7 @@ export const TransactionDetailPage: FC = () => { return ( {warningMultipleTransactionsSameHash && ( - {t('transaction.warningMultipleTransactionsSameHash')} + {t('transaction.warningMultipleTransactionsSameHash')} )} Date: Wed, 28 Jun 2023 17:18:01 +0200 Subject: [PATCH 6/8] CopyToClipboard: support displaying a button with label (As an alternative to the icon.) --- src/app/components/CopyToClipboard/index.tsx | 24 ++++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/app/components/CopyToClipboard/index.tsx b/src/app/components/CopyToClipboard/index.tsx index d101fb2399..343ef15d0d 100644 --- a/src/app/components/CopyToClipboard/index.tsx +++ b/src/app/components/CopyToClipboard/index.tsx @@ -5,14 +5,16 @@ import ContentCopyIcon from '@mui/icons-material/ContentCopy' import { COLORS } from '../../../styles/theme/colors' import ButtonBase from '@mui/material/ButtonBase' import { styled } from '@mui/material/styles' +import Button from '@mui/material/Button' const clipboardTooltipDuration = 2000 type CopyToClipboardProps = { value: string + label?: string } -const StyledButton = styled(ButtonBase)(({ theme }) => ({ +const StyledIconButton = styled(ButtonBase)(({ theme }) => ({ display: 'inline-flex', alignItems: 'center', border: 0, @@ -24,7 +26,7 @@ const StyledButton = styled(ButtonBase)(({ theme }) => ({ marginLeft: theme.spacing(4), })) -export const CopyToClipboard: FC = ({ value }) => { +export const CopyToClipboard: FC = ({ value, label }) => { const { t } = useTranslation() const timeout = useRef(undefined) const ariaLabel = t('clipboard.label') @@ -51,9 +53,21 @@ export const CopyToClipboard: FC = ({ value }) => { return ( - - - + {label ? ( + + ) : ( + + + + )} ) } From dc16c6bc368e00df624068da23541751d2bd48e4 Mon Sep 17 00:00:00 2001 From: Kristof Csillag Date: Wed, 28 Jun 2023 17:18:36 +0200 Subject: [PATCH 7/8] Add component to display long data with scrolling --- .../components/ScrollingDataDisplay/index.tsx | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/app/components/ScrollingDataDisplay/index.tsx diff --git a/src/app/components/ScrollingDataDisplay/index.tsx b/src/app/components/ScrollingDataDisplay/index.tsx new file mode 100644 index 0000000000..bf79690e51 --- /dev/null +++ b/src/app/components/ScrollingDataDisplay/index.tsx @@ -0,0 +1,44 @@ +import { FC } from 'react' +import Typography from '@mui/material/Typography' +import Box from '@mui/material/Box' +import { COLORS } from '../../../styles/theme/colors' + +export const ScrollingDataDisplay: FC<{ data: string; fontWeight?: number }> = ({ + data, + fontWeight = 700, +}) => { + return ( + + + + {data} + + + + ) +} From 9e2a2174abcd94cc02c64cd584d979954d03ec10 Mon Sep 17 00:00:00 2001 From: Kristof Csillag Date: Wed, 28 Jun 2023 17:19:01 +0200 Subject: [PATCH 8/8] Display contract bytecode --- .changelog/616.feature.md | 1 + .../components/ScrollingDataDisplay/index.tsx | 2 +- .../AccountDetailsPage/AccountTokensCard.tsx | 2 +- .../AccountDetailsPage/ContractCodeCard.tsx | 75 +++++++++++++++++++ src/app/pages/AccountDetailsPage/hook.ts | 6 +- src/app/pages/AccountDetailsPage/index.tsx | 6 +- src/locales/en/translation.json | 7 ++ src/routes.tsx | 6 ++ 8 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 .changelog/616.feature.md create mode 100644 src/app/pages/AccountDetailsPage/ContractCodeCard.tsx diff --git a/.changelog/616.feature.md b/.changelog/616.feature.md new file mode 100644 index 0000000000..5b96e8c537 --- /dev/null +++ b/.changelog/616.feature.md @@ -0,0 +1 @@ +For contracts, display bytecode diff --git a/src/app/components/ScrollingDataDisplay/index.tsx b/src/app/components/ScrollingDataDisplay/index.tsx index bf79690e51..83092ec189 100644 --- a/src/app/components/ScrollingDataDisplay/index.tsx +++ b/src/app/components/ScrollingDataDisplay/index.tsx @@ -11,7 +11,7 @@ export const ScrollingDataDisplay: FC<{ data: string; fontWeight?: number }> = ( = ({ type }) => { const { t } = useTranslation() const locationHash = useLocation().hash.replace('#', '') const tokenLabel = t(`account.${type}` as any) - const tokenListLabel = t('tokens.title') // TODO: re-enable when we want multiple token types again t('account.tokensListTitle', { token: tokenLabel }) + const tokenListLabel = t('common.tokens') // TODO: re-enable when we want multiple token types again t('account.tokensListTitle', { token: tokenLabel }) const tableColumns: TableColProps[] = [ { key: 'name', content: t('common.name') }, { key: 'contract', content: t('common.smartContract') }, diff --git a/src/app/pages/AccountDetailsPage/ContractCodeCard.tsx b/src/app/pages/AccountDetailsPage/ContractCodeCard.tsx new file mode 100644 index 0000000000..1b4c55511e --- /dev/null +++ b/src/app/pages/AccountDetailsPage/ContractCodeCard.tsx @@ -0,0 +1,75 @@ +import { FC } from 'react' +import { useTranslation } from 'react-i18next' +import Card from '@mui/material/Card' +import CardContent from '@mui/material/CardContent' +import { ScrollingDiv } from '../../components/PageLayout/ScrollingDiv' +import { useAccount } from './hook' +import { useRequiredScopeParam } from '../../hooks/useScopeParam' +import { useLoaderData } from 'react-router-dom' +import { CardEmptyState } from './CardEmptyState' +import Typography from '@mui/material/Typography' +import { ScrollingDataDisplay } from '../../components/ScrollingDataDisplay' +import Box from '@mui/material/Box' +import { CopyToClipboard } from '../../components/CopyToClipboard' +import { useScreenSize } from '../../hooks/useScreensize' + +export const contractCodeContainerId = 'code' + +const CodeDisplay: FC<{ code: string | undefined; label: string; extraTopPadding?: boolean }> = ({ + code, + label, + extraTopPadding, +}) => { + const { t } = useTranslation() + const { isMobile } = useScreenSize() + return code === undefined ? null : ( + <> + + + {label} + + + + + + + ) +} + +export const ContractCodeCard: FC = () => { + const { t } = useTranslation() + const scope = useRequiredScopeParam() + const address = useLoaderData() as string + + const { isFetched, account } = useAccount(scope, address) + const contract = account?.evm_contract + const noCode = isFetched && !contract?.creation_bytecode && !contract?.runtime_bytecode + return ( + + + {noCode && } + {contract && (contract.creation_bytecode || contract.runtime_bytecode) && ( + + + + + )} + + + ) +} diff --git a/src/app/pages/AccountDetailsPage/hook.ts b/src/app/pages/AccountDetailsPage/hook.ts index 1787bd5116..5ec45d215d 100644 --- a/src/app/pages/AccountDetailsPage/hook.ts +++ b/src/app/pages/AccountDetailsPage/hook.ts @@ -12,9 +12,9 @@ export const useAccount = (scope: SearchScope, address: string) => { } const query = useGetRuntimeAccountsAddress(network, layer, address!) const account = query.data?.data - const isLoading = query.isLoading - const isError = query.isError - return { account, isLoading, isError } + const { isLoading, isError, isFetched } = query + + return { account, isLoading, isError, isFetched } } export const useAccountTransactions = (scope: SearchScope, address: string) => { diff --git a/src/app/pages/AccountDetailsPage/index.tsx b/src/app/pages/AccountDetailsPage/index.tsx index 5ec84c6791..e58fcf91c3 100644 --- a/src/app/pages/AccountDetailsPage/index.tsx +++ b/src/app/pages/AccountDetailsPage/index.tsx @@ -14,6 +14,7 @@ import { useAccount } from './hook' import { useRequiredScopeParam } from '../../hooks/useScopeParam' import { showEmptyAccountDetails } from '../../../config' import { CardEmptyState } from './CardEmptyState' +import { contractCodeContainerId } from './ContractCodeCard' export const AccountDetailsPage: FC = () => { const { t } = useTranslation() @@ -29,6 +30,8 @@ export const AccountDetailsPage: FC = () => { const erc20Link = useHref(`tokens/erc-20#${accountTokenContainerId}`) const showTxs = showEmptyAccountDetails || showErc20 || !!account?.stats.num_txns const txLink = useHref('') + const showCode = isContract + const codeLink = useHref(`code#${contractCodeContainerId}`) const showDetails = showTxs || showErc20 @@ -50,7 +53,8 @@ export const AccountDetailsPage: FC = () => { )} diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 9655b47cb1..9ef5d4fef1 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -37,6 +37,7 @@ "block": "Block", "bytes": "{{value, number}}", "cancel": "Cancel", + "copy": "Copy", "createdAt": "Created at", "data": "Data", "emerald": "Emerald", @@ -92,6 +93,12 @@ "valuePair": "{{value, number}}" }, "contract": { + "code": "Code", + "copyButton": "Copy {{subject}}", + "creationByteCode": "Creation ByteCode", + "noCode": "There is no bytecode on record for this account. (Are you sure this is a contract?)", + "title": "Contract", + "runtimeByteCode": "Runtime ByteCode", "title": "Contract", "verification": { "title": "Verification", diff --git a/src/routes.tsx b/src/routes.tsx index 7312b5275d..d36d02fc85 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -20,6 +20,7 @@ import { RoutingErrorPage } from './app/pages/RoutingErrorPage' import { ThemeByNetwork, withDefaultTheme } from './app/components/ThemeByNetwork' import { useRequiredScopeParam } from './app/hooks/useScopeParam' import { TokensPage } from './app/pages/TokensPage' +import { ContractCodeCard } from './app/pages/AccountDetailsPage/ContractCodeCard' const NetworkSpecificPart = () => ( @@ -86,6 +87,11 @@ export const routes: RouteObject[] = [ element: , loader: addressParamLoader, }, + { + path: 'code', + element: , + loader: addressParamLoader, + }, ], }, {