From afe285b577632f08bf49c8548ff650a6a88757e2 Mon Sep 17 00:00:00 2001 From: Keith Date: Tue, 16 Aug 2022 14:10:40 +0800 Subject: [PATCH 01/10] feat: add title in interaction of contract 1. add 'pure and view' title in read contract tab 2. add 'call staic' title in read contract tab 3. add 'non-payable and payable' title in write contract tab Ref: https://github.com/Magickbase/godwoken_explorer/issues/864 --- components/ContractInfo/index.tsx | 8 +++++++- components/ContractInfo/styles.module.scss | 8 ++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/components/ContractInfo/index.tsx b/components/ContractInfo/index.tsx index 4db22e21f..26beb8935 100644 --- a/components/ContractInfo/index.tsx +++ b/components/ContractInfo/index.tsx @@ -220,6 +220,7 @@ const ContractInfo: React.FC<{ address: string; contract: PolyjuiceContractProps {tabIdx === 1 && contract ? (
+
Pure and View
{viewMethodSignatures.map(signature => { const { inputs = [], outputs = [] } = contract.interface.functions[signature] ?? {} return ( @@ -264,7 +265,11 @@ const ContractInfo: React.FC<{ address: string; contract: PolyjuiceContractProps ) })} - {writeMethodSignatures.length ?
Call Static
: null} + {writeMethodSignatures.length ? ( +
+ Call Static +
+ ) : null} {writeMethodSignatures.map(signature => { const { inputs = [], outputs = [] } = contract.interface.functions[signature] ?? {} return ( @@ -324,6 +329,7 @@ const ContractInfo: React.FC<{ address: string; contract: PolyjuiceContractProps
) : null} +
Non-payable and Payable
{writeMethodSignatures.map(signature => { const { inputs = [], outputs = [] } = contract.interface.functions[signature] ?? {} return ( diff --git a/components/ContractInfo/styles.module.scss b/components/ContractInfo/styles.module.scss index 0bc4d842e..c8a9f87fe 100644 --- a/components/ContractInfo/styles.module.scss +++ b/components/ContractInfo/styles.module.scss @@ -310,3 +310,11 @@ white-space: break-spaces; } } + +.methodGroupTitle { + font-weight: 500; + font-size: 1rem; + color: var(--primary-text-color); + margin: 1rem 0; + line-height: 1em; +} From 26189efa5afd7db9d85c7396fa67478da1ee22f3 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Wed, 24 Aug 2022 16:32:36 +0800 Subject: [PATCH 02/10] feat: update style of overlapped token logos (#458) --- components/AssetList/index.tsx | 2 +- components/AssetList/styles.module.scss | 8 ++++++++ components/TokenLogo/styles.module.scss | 22 +++++++++++++--------- pages/tokens/[type].tsx | 4 +++- pages/tokens/styles.module.scss | 8 ++++++++ 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/components/AssetList/index.tsx b/components/AssetList/index.tsx index b48333f91..a5143597d 100644 --- a/components/AssetList/index.tsx +++ b/components/AssetList/index.tsx @@ -66,7 +66,7 @@ const AssetList = ({ list = [] }: { list: UdtList }) => {
- + diff --git a/components/AssetList/styles.module.scss b/components/AssetList/styles.module.scss index 9e53c9cd9..009259ac2 100644 --- a/components/AssetList/styles.module.scss +++ b/components/AssetList/styles.module.scss @@ -38,3 +38,11 @@ .noRecords { @include empty-list; } + +.logo { + min-width: 40px; + text-align: center; + img { + margin: 0 auto; + } +} diff --git a/components/TokenLogo/styles.module.scss b/components/TokenLogo/styles.module.scss index 3cdff12fe..31908aea2 100644 --- a/components/TokenLogo/styles.module.scss +++ b/components/TokenLogo/styles.module.scss @@ -1,5 +1,6 @@ -$size: 1.875rem; -$offset: 8px; +$size: 2rem; +$offset-x: 10px; +$offset-y: 6px; .token, .origin { @@ -13,19 +14,18 @@ $offset: 8px; height: $size; background: #f9f8ff; border-radius: 100%; - cursor: pointer; } .origin { - width: 0.7 * $size; - height: 0.7 * $size; + width: 0.68 * $size; + height: 0.68 * $size; background: #f0f0f0; z-index: 0; } .overlap { - width: calc($size + $offset); - height: calc($size + $offset); + width: calc($size - 2px + $offset-x); + height: calc($size - 2px + $offset-y); position: relative; .origin, .token { @@ -39,10 +39,13 @@ $offset: 8px; transform-origin: 110% 110%; } .token { - top: $offset; - left: $offset; + top: $offset-y; + left: $offset-x; filter: drop-shadow(0px 0px 2px #00000033); transform-origin: -10% -10%; + width: calc($size - 2px); + height: calc($size - 2px); + border: 1px solid #fff; } &:hover { @@ -50,6 +53,7 @@ $offset: 8px; .token { transform: scale(1.3); filter: drop-shadow(0px 0px 4px #00000033); + border: none; } } } diff --git a/pages/tokens/[type].tsx b/pages/tokens/[type].tsx index e28f858ec..dccf2995b 100644 --- a/pages/tokens/[type].tsx +++ b/pages/tokens/[type].tsx @@ -267,7 +267,9 @@ const TokenList = () => { - +
+ +
{type === 'bridge' ? ( diff --git a/pages/tokens/styles.module.scss b/pages/tokens/styles.module.scss index bd21383e1..c417f8517 100644 --- a/pages/tokens/styles.module.scss +++ b/pages/tokens/styles.module.scss @@ -59,6 +59,14 @@ } } +.logo { + min-width: 40px; + text-align: center; + & > img { + margin: 0 auto; + } +} + .noRecords { @include empty-list; } From f1c42cce531ad1cc1b995d662d0d9a4c63da2fd9 Mon Sep 17 00:00:00 2001 From: Keith Date: Wed, 24 Aug 2022 16:06:55 +0800 Subject: [PATCH 03/10] feat: add method field in tx list --- components/TxList/index.tsx | 17 ++++++++++++++++- components/TxList/styles.module.scss | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/components/TxList/index.tsx b/components/TxList/index.tsx index d90e8e4f3..69cc3cba5 100644 --- a/components/TxList/index.tsx +++ b/components/TxList/index.tsx @@ -21,6 +21,8 @@ export type TxListProps = { entries: Array<{ hash: string eth_hash: string | null + method_id: string | null + method_name: string | null type: GraphQLSchema.TransactionType block?: Pick from_account: Pick @@ -59,6 +61,8 @@ const txListQuery = gql` entries { hash eth_hash + method_id + method_name block { hash number @@ -130,6 +134,7 @@ const TxList: React.FC = {t('txHash')} + {t('method')}
{t('block')} @@ -149,6 +154,7 @@ const TxList: React.FC = const hash = item.eth_hash || item.hash const from = item.from_account.eth_address || item.from_account.script_hash const to = item.to_account.eth_address || item.to_account.script_hash + const method = item.method_name || item.method_id return ( @@ -167,6 +173,15 @@ const TxList: React.FC = />
+ + {method ? ( +
+ {method} +
+ ) : ( + '-' + )} + {item.block ? ( @@ -202,7 +217,7 @@ const TxList: React.FC = }) ) : ( - + {isFiltered ? (
diff --git a/components/TxList/styles.module.scss b/components/TxList/styles.module.scss index b204b405b..5ebbca205 100644 --- a/components/TxList/styles.module.scss +++ b/components/TxList/styles.module.scss @@ -20,6 +20,21 @@ padding-right: 0 !important; } +.method { + width: min-content; + max-width: 95px; + overflow: hidden; + text-overflow: ellipsis; + font-size: 0.875rem; + color: var(--primary-text-color); + padding: 6px 8px; + background: #fafafa; + line-height: 1; + border-radius: 8px; + user-select: all; + cursor: default; +} + .noRecords { @include empty-list; } From 286cb9c2388c187fe95035e7044737e6ad05e9bf Mon Sep 17 00:00:00 2001 From: Keith Date: Fri, 26 Aug 2022 01:27:38 +0800 Subject: [PATCH 04/10] feat: add tooltip on method of tx --- components/TxList/index.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/TxList/index.tsx b/components/TxList/index.tsx index 69cc3cba5..4f8ed4e6e 100644 --- a/components/TxList/index.tsx +++ b/components/TxList/index.tsx @@ -175,9 +175,11 @@ const TxList: React.FC = {method ? ( -
- {method} -
+ +
+ {method} +
+
) : ( '-' )} From b39b5210a5433dbab3c9e12f396efb9e28b3ac10 Mon Sep 17 00:00:00 2001 From: Keith Date: Fri, 26 Aug 2022 16:48:12 +0800 Subject: [PATCH 05/10] feat: make tx and account pages csr --- components/QRCodeBtn/index.tsx | 2 +- pages/account/[id].tsx | 111 +++++++++------------- pages/tx/[hash].tsx | 166 ++++++++++++++++----------------- utils/handler.ts | 1 - 4 files changed, 125 insertions(+), 155 deletions(-) diff --git a/components/QRCodeBtn/index.tsx b/components/QRCodeBtn/index.tsx index b4c5095fc..8183cca4b 100644 --- a/components/QRCodeBtn/index.tsx +++ b/components/QRCodeBtn/index.tsx @@ -32,7 +32,7 @@ const QRCodeBtn: React.FC<{ content: string }> = ({ content }) => { errorCorrectionLevel: 'H', }) } catch (err) { - console.log(err) + console.error(err) } } diff --git a/pages/account/[id].tsx b/pages/account/[id].tsx index ff8b514a1..0de85d764 100644 --- a/pages/account/[id].tsx +++ b/pages/account/[id].tsx @@ -1,10 +1,8 @@ import type { GetStaticPaths, GetStaticProps } from 'next' -import { useEffect, useState } from 'react' import { useRouter } from 'next/router' import { useTranslation } from 'next-i18next' import { serverSideTranslations } from 'next-i18next/serverSideTranslations' import { useQuery } from 'react-query' -import BigNumber from 'bignumber.js' import { Skeleton } from '@mui/material' import SubpageHead from 'components/SubpageHead' import AccountOverview, { @@ -26,26 +24,17 @@ import QRCodeBtn from 'components/QRCodeBtn' import PageTitle from 'components/PageTitle' import DownloadMenu, { DOWNLOAD_HREF_LIST } from 'components/DownloadMenu' import { SIZES } from 'components/PageSize' -import { - handleApiError, - fetchBridgedRecordList, - fetchEventLogsListByType, - isEthAddress, - GraphQLSchema, - API_ENDPOINT, - CKB_DECIMAL, -} from 'utils' +import { fetchBridgedRecordList, fetchEventLogsListByType, isEthAddress, GraphQLSchema } from 'utils' import styles from './styles.module.scss' -type State = AccountOverviewProps - const isSmartContractAccount = (account: AccountOverviewProps['account']): account is PolyjuiceContract => { return !!(account as PolyjuiceContract)?.smart_contract } -const Account = (initState: State) => { +const Account = () => { const { query: { + id, tab = 'transactions', before = null, after = null, @@ -55,16 +44,30 @@ const Account = (initState: State) => { page_size = SIZES[1], }, } = useRouter() - const [accountAndList, setAccountAndList] = useState(initState) const [t] = useTranslation(['account', 'common']) - const id = accountAndList.account.eth_address || accountAndList.account.script_hash + const q = isEthAddress(id as string) ? { address: id as string } : { script_hash: id as string } - useEffect(() => { - setAccountAndList(initState) - }, [setAccountAndList, initState]) + const { isLoading: _isAccountLoading, data: accountAndList } = useQuery( + ['account', id], + () => fetchAccountOverview(q), + { + refetchInterval: 10000, + enabled: !!id, + }, + ) - const q = isEthAddress(id) ? { address: id } : { script_hash: id } + const deployment_tx_hash = + isSmartContractAccount(accountAndList) && accountAndList?.smart_contract?.deployment_tx_hash + + const { data: deployerAddr } = useQuery( + ['deployer', deployment_tx_hash], + () => + fetchDeployAddress({ + eth_hash: deployment_tx_hash, + }), + { enabled: !!deployment_tx_hash }, + ) const { isLoading: isOverviewLoading, data: overview } = useQuery( ['account-overview', id], @@ -77,10 +80,10 @@ const Account = (initState: State) => { const { isLoading: isBalanceLoading, data: balance = '0' } = useQuery( ['account-balance', id], - () => fetchAccountBalance(id), + () => fetchAccountBalance(id as string), { refetchInterval: 10000, - enabled: !!id && isEthAddress(id), + enabled: !!id && isEthAddress(id as string), }, ) @@ -126,14 +129,14 @@ const Account = (initState: State) => { const { isLoading: isUdtListLoading, data: udtList } = useQuery( ['account-udt-list', id], - () => fetchUdtList(q.address ? { address_hashes: [id] } : { script_hashes: [id] }), + () => fetchUdtList(q.address ? { address_hashes: [id as string] } : { script_hashes: [id as string] }), { enabled: tab === 'assets' && !!(q.address || q.script_hash) }, ) - const account = overview ?? accountAndList.account + const account = overview ?? accountAndList ?? null /* is script hash supported? */ - const downloadItems = account.eth_address + const downloadItems = account?.eth_address ? [ { label: t('transactionRecords'), href: DOWNLOAD_HREF_LIST.accountTxList(account.eth_address) }, { label: t('ERC20Records'), href: DOWNLOAD_HREF_LIST.accountTransferList(account.eth_address) }, @@ -144,10 +147,9 @@ const Account = (initState: State) => { ] : [] - const title = t(`accountType.${account.type}`) - const accountType = account.type + const title = account ? t(`accountType.${account.type}`) : + const accountType = account?.type - // const tabs = ['transactions', 'erc20', 'bridged', 'assets', 'contract', 'events'] const tabs = [ { label: t('transactionRecords'), key: 'transactions' }, [GraphQLSchema.AccountType.EthUser, GraphQLSchema.AccountType.PolyjuiceContract].includes(accountType) @@ -176,16 +178,18 @@ const Account = (initState: State) => {
{id} - - + +
- + {account ? ( + + ) : null}
tabItem.key === tab)} @@ -199,7 +203,7 @@ const Account = (initState: State) => { ) : ( @@ -207,7 +211,7 @@ const Account = (initState: State) => { ) : null} {tab === 'erc20' ? ( !isTransferListLoading && transferList ? ( - + ) : ( ) @@ -247,31 +251,8 @@ export const getStaticPaths: GetStaticPaths = () => ({ fallback: 'blocking', }) -export const getStaticProps: GetStaticProps = async ({ locale, params }) => { - const { id } = params - - try { - const q = isEthAddress(id) ? { address: id } : { script_hash: id } - - const [account, lng] = await Promise.all([ - fetchAccountOverview(q), - serverSideTranslations(locale, ['common', 'account', 'list']), - null, - ]) - - const balance = await fetch(`${API_ENDPOINT}/accounts/${account.eth_address}`) - .then(r => r.json()) - .then(a => new BigNumber(a.ckb).multipliedBy(new BigNumber(CKB_DECIMAL)).toString()) - .catch(() => '0') - - const deployerAddr = - isSmartContractAccount(account) && account.smart_contract?.deployment_tx_hash - ? await fetchDeployAddress({ eth_hash: account.smart_contract.deployment_tx_hash }) - : null - - return { props: { ...lng, account, deployerAddr, balance } } - } catch (err) { - return handleApiError(err, null, locale, id) - } +export const getStaticProps: GetStaticProps = async ({ locale }) => { + const lng = await serverSideTranslations(locale, ['common', 'account', 'list']) + return { props: lng } } export default Account diff --git a/pages/tx/[hash].tsx b/pages/tx/[hash].tsx index 4eca48243..076a3cc67 100644 --- a/pages/tx/[hash].tsx +++ b/pages/tx/[hash].tsx @@ -1,5 +1,5 @@ -import { useEffect, useState, useMemo } from 'react' -import { GetStaticPaths, GetStaticProps } from 'next' +import type { GetStaticPaths, GetStaticProps } from 'next' +import { useMemo } from 'react' import { useRouter } from 'next/router' import { useTranslation } from 'next-i18next' import { serverSideTranslations } from 'next-i18next/serverSideTranslations' @@ -22,29 +22,13 @@ import Amount from 'components/Amount' import { SIZES } from 'components/PageSize' import PolyjuiceStatus from 'components/PolyjuiceStatus' import ExpandIcon from 'assets/icons/expand.svg' -import { - formatDatetime, - fetchTx, - useWS, - getTxRes, - fetchEventLogsListByType, - handleApiError, - CKB_EXPLORER_URL, - CHANNEL, - NotFoundException, - PCKB_UDT_INFO, -} from 'utils' +import { formatDatetime, fetchTx, fetchEventLogsListByType, CKB_EXPLORER_URL, PCKB_UDT_INFO } from 'utils' import styles from './styles.module.scss' -type RawTx = Parameters[0] -type ParsedTx = ReturnType - const tabs = ['erc20', 'logs', 'raw-data'] -type State = ParsedTx const ADDR_LENGTH = 42 -const Tx = (initState: State) => { - const [tx, setTx] = useState(initState) +const Tx = () => { const { query: { hash, @@ -56,10 +40,14 @@ const Tx = (initState: State) => { page_size = SIZES[1], log_index_sort = 'ASC', }, + replace, } = useRouter() const [t] = useTranslation('tx') - const downloadItems = [{ label: t('ERC20Records'), href: DOWNLOAD_HREF_LIST.txTransferList(tx.hash) }] + const { isLoading: isTxLoading, data: tx } = useQuery(['tx', hash], () => fetchTx(hash as string), { + enabled: !!hash, + refetchInterval: 10000, + }) const { isLoading: isTransferListLoading, data: transferList } = useQuery( ['tx-transfer-list', hash, before, after, address_from, address_to, log_index_sort, page_size], @@ -87,58 +75,38 @@ const Tx = (initState: State) => { }, ) - useEffect(() => { - setTx(initState) - }, [setTx, initState]) + if (!isTxLoading && !tx?.hash) { + replace(`/404?search=${hash}`) + } - useWS( - `${CHANNEL.TX_INFO}${tx.hash}`, - (init: RawTx) => { - if (init) { - setTx(prev => ({ ...getTxRes(init), gasUsed: prev.gasUsed, gasLimit: prev.gasLimit })) - } - }, - ({ - status = 'pending', - l1_block_number, - polyjuice_status, - }: Partial>) => { - setTx(prev => ({ - ...prev, - status, - l1BlockNumber: l1_block_number, - polyjuiceStatus: polyjuice_status ?? prev.polyjuiceStatus, - })) - }, - [setTx, tx.hash], - ) + const downloadItems = [{ label: t('ERC20Records'), href: DOWNLOAD_HREF_LIST.txTransferList(hash as string) }] const decodedInput = useMemo(() => { - if (initState.contractAbi && initState.contractAbi.length && initState.input) { + if (tx && tx.contractAbi && tx.contractAbi.length && tx.input) { try { - const i = new ethers.utils.Interface(initState.contractAbi) - return i.parseTransaction({ data: initState.input }) + const i = new ethers.utils.Interface(tx.contractAbi) + return i.parseTransaction({ data: tx.input }) } catch (err) { console.error(err) return null } } return null - }, [initState.contractAbi, initState.input]) + }, [tx?.contractAbi, tx?.input]) const utf8Input = useMemo(() => { - if (initState.input) { + if (tx?.input) { try { - return ethers.utils.toUtf8String(initState.input) + return ethers.utils.toUtf8String(tx.input) } catch { return null } } return null - }, [initState.input]) + }, [tx?.input]) const inputContents = [ - { type: 'raw', text: tx.input }, + { type: 'raw', text: tx?.input }, decodedInput ? { type: 'decoded', @@ -155,20 +123,32 @@ const Tx = (initState: State) => { field: t('hash'), content: (
- {tx.hash} - + {hash as string} +
), }, { field: t('from'), - content: , + content: isTxLoading ? ( + + ) : tx ? ( + + ) : ( + '-' + ), }, { - field: t(tx.toAlias ? 'interactedContract' : 'to'), - content: , + field: t(tx?.toAlias ? 'interactedContract' : 'to'), + content: isTxLoading ? ( + + ) : tx ? ( + + ) : ( + '-' + ), }, - tx.contractAddress?.length === ADDR_LENGTH + tx?.contractAddress?.length === ADDR_LENGTH ? { field: t('deployed_contract'), content: , @@ -179,11 +159,11 @@ const Tx = (initState: State) => { // FIXME: tx.value is formatted incorrectly content: (
- +
), }, - tx.input + tx?.input ? { field: t('input'), content: ( @@ -208,14 +188,14 @@ const Tx = (initState: State) => { ] const basicInfo = [ - { field: t('finalizeState'), content: t(tx.status) }, + { field: t('finalizeState'), content: tx ? t(tx.status) : }, { field: t('type'), - content: , + content: tx ? : , }, { field: t('l1Block'), - content: tx.l1BlockNumber ? ( + content: tx?.l1BlockNumber ? ( { }, { field: t('l2Block'), - content: tx.blockNumber ? ( + content: tx?.blockNumber ? ( ) : ( t('pending') ), }, - { field: t('index'), content: tx.index ?? '-' }, - { field: t('nonce'), content: (tx.nonce || 0).toLocaleString('en') }, + { field: t('index'), content: tx?.index ?? '-' }, + { field: t('nonce'), content: tx ? (tx.nonce || 0).toLocaleString('en') : }, { field: t('status'), - content: , + content: tx ? : , }, { field: t('gasPrice'), content: - tx.gasPrice !== null ? ( + tx && tx.gasPrice !== null ? ( {`${new BigNumber(tx.gasPrice).toFormat()} ${PCKB_UDT_INFO.symbol}`} + ) : isTxLoading ? ( + ) : ( '-' ), }, { field: t('gasUsed'), - content: tx.gasUsed !== null && tx.polyjuiceStatus !== 'pending' ? new BigNumber(tx.gasUsed).toFormat() : '-', + content: + tx && tx.gasUsed !== null && tx.polyjuiceStatus !== 'pending' ? ( + new BigNumber(tx.gasUsed).toFormat() + ) : isTxLoading ? ( + + ) : ( + '-' + ), }, { field: t('gasLimit'), - content: tx.gasLimit !== null ? new BigNumber(tx.gasLimit).toFormat() : '-', + content: + tx && tx.gasLimit !== null ? ( + new BigNumber(tx.gasLimit).toFormat() + ) : isTxLoading ? ( + + ) : ( + '-' + ), }, { field: t('fee'), content: - tx.gasPrice !== null && typeof tx.gasUsed !== null && tx.polyjuiceStatus !== 'pending' ? ( + tx && tx.gasPrice !== null && typeof tx.gasUsed !== null && tx.polyjuiceStatus !== 'pending' ? ( { showSymbol /> + ) : isTxLoading ? ( + ) : ( '-' ), @@ -274,7 +272,7 @@ const Tx = (initState: State) => { { field: t('timestamp'), content: - tx.timestamp >= 0 ? ( + tx?.timestamp >= 0 ? ( ) : ( t('pending') @@ -286,7 +284,7 @@ const Tx = (initState: State) => { return ( <> - +
@@ -304,7 +302,7 @@ const Tx = (initState: State) => { value={tabs.indexOf(tab as string)} tabs={['erc20_records', 'logs', 'rawData'].map((label, idx) => ({ label: t(label), - href: `/tx/${tx.hash}?tab=${tabs[idx]}`, + href: `/tx/${hash}?tab=${tabs[idx]}`, }))} /> {tab === 'erc20' ? ( @@ -321,7 +319,7 @@ const Tx = (initState: State) => { ) ) : null} - {tab === 'raw-data' && tx ? : null} + {tab === 'raw-data' && tx ? : null}
@@ -333,17 +331,9 @@ export const getStaticPaths: GetStaticPaths = () => ({ fallback: 'blocking', }) -export const getStaticProps: GetStaticProps = async ({ locale, params }) => { - const { hash } = params - - try { - const [tx, lng] = await Promise.all([fetchTx(hash), await serverSideTranslations(locale, ['common', 'tx', 'list'])]) - if (!tx?.hash) { - throw new NotFoundException() - } - return { props: { ...tx, ...lng } } - } catch (err) { - return handleApiError(err, null, locale, hash) - } +export const getStaticProps: GetStaticProps = async ({ locale }) => { + const lng = await serverSideTranslations(locale, ['common', 'tx', 'list']) + return { props: lng } } + export default Tx diff --git a/utils/handler.ts b/utils/handler.ts index 7c49baf95..48737489d 100644 --- a/utils/handler.ts +++ b/utils/handler.ts @@ -34,7 +34,6 @@ export const handleSearchKeyPress = async (e: React.KeyboardEvent Date: Sat, 27 Aug 2022 16:02:52 +0800 Subject: [PATCH 06/10] feat: verify and register in contract page (#481) --- assets/icons/check-success.svg | 5 + assets/icons/submit-success.svg | 11 ++ components/AccountOverview/index.tsx | 73 ++++++-- components/InfoList/index.tsx | 2 +- components/InfoList/styles.module.scss | 3 + components/SmartContract.tsx | 80 --------- components/SmartContractInfo/index.tsx | 166 ++++++++++++++++++ .../SmartContractInfo/styles.module.scss | 17 ++ public/locales/en-US/account.json | 8 +- public/locales/zh-CN/account.json | 8 +- utils/graphql.ts | 2 +- 11 files changed, 277 insertions(+), 98 deletions(-) create mode 100644 assets/icons/check-success.svg create mode 100644 assets/icons/submit-success.svg delete mode 100644 components/SmartContract.tsx create mode 100644 components/SmartContractInfo/index.tsx create mode 100644 components/SmartContractInfo/styles.module.scss diff --git a/assets/icons/check-success.svg b/assets/icons/check-success.svg new file mode 100644 index 000000000..65f864651 --- /dev/null +++ b/assets/icons/check-success.svg @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/assets/icons/submit-success.svg b/assets/icons/submit-success.svg new file mode 100644 index 000000000..d7df30826 --- /dev/null +++ b/assets/icons/submit-success.svg @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/components/AccountOverview/index.tsx b/components/AccountOverview/index.tsx index 9d1a91ced..472228e1f 100644 --- a/components/AccountOverview/index.tsx +++ b/components/AccountOverview/index.tsx @@ -5,7 +5,7 @@ import { Skeleton } from '@mui/material' import User from 'components/User' import EthAddrReg from 'components/EthAddrReg' import MetaContract from 'components/MetaContract' -import SmartContract from 'components/SmartContract' +import SmartContract from 'components/SmartContractInfo' import Polyjuice from 'components/Polyjuice' import SUDT from 'components/SUDT' import UnknownAccount from 'components/UnknownAccount' @@ -13,6 +13,7 @@ import InfoList from 'components/InfoList' import Amount from 'components/Amount' import styles from './styles.module.scss' import { GraphQLSchema, client, provider, PCKB_UDT_INFO } from 'utils' +import { useQuery } from 'react-query' export type BasicScript = Record<'args' | 'code_hash' | 'hash_type', string> export interface AccountBase { @@ -47,7 +48,7 @@ export interface PolyjuiceContract extends AccountBase { | 'abi' | 'constructor_arguments' > | null - udt: Pick | null + udt: Pick | null } export interface PolyjuiceCreator extends AccountBase { type: GraphQLSchema.AccountType.PolyjuiceCreator @@ -83,6 +84,7 @@ export type AccountOverviewProps = { isBalanceLoading?: boolean balance: string deployerAddr?: string + isContractVerified?: boolean } const accountOverviewQuery = gql` @@ -99,6 +101,9 @@ const accountOverviewQuery = gql` name decimal symbol + description + official_site + icon } smart_contract { name @@ -123,6 +128,16 @@ const deployAddrQuery = gql` } ` +const checkSourcify = gql` + query checkSourcify($address: String!) { + sourcify_check_by_addresses(input: { addresses: [$address] }) { + address + chain_ids + status + } + } +` + type Variables = { address: string } | { script_hash: string } export const fetchAccountOverview = (variables: Variables) => @@ -145,14 +160,37 @@ export const fetchDeployAddress = (variables: { eth_hash: string }) => .request<{ transaction: { from_account: Pick } }>(deployAddrQuery, variables) .then(data => data.transaction.from_account.eth_address) -const OverviewPlaceHolderCount = { - [GraphQLSchema.AccountType.EthUser]: 0, - [GraphQLSchema.AccountType.PolyjuiceCreator]: 1, - [GraphQLSchema.AccountType.PolyjuiceContract]: 3, - [GraphQLSchema.AccountType.MetaContract]: 6, - [GraphQLSchema.AccountType.EthAddrReg]: 0, - [GraphQLSchema.AccountType.Udt]: 4, +export const fetchSourcifyStatus = (address: string) => + client.request<{ sourcify_check_by_addresses: { status: string | null } }>(checkSourcify, { address }).then(data => { + return data.sourcify_check_by_addresses[0].status + }) + +const overviewPlaceHolderCount = (account: AccountOverviewProps['account']) => { + switch (account.type) { + case GraphQLSchema.AccountType.EthUser: + return 0 + case GraphQLSchema.AccountType.PolyjuiceCreator: + return 1 + case GraphQLSchema.AccountType.PolyjuiceContract: + const isVerified = !!account.smart_contract?.contract_source_code + if (!!account.smart_contract?.deployment_tx_hash && isVerified) { + return 2 + } else if (!!account.smart_contract?.deployment_tx_hash && !isVerified) { + return 3 + } else if (!account.smart_contract?.deployment_tx_hash && isVerified) { + return 0 + } else { + return 1 + } + case GraphQLSchema.AccountType.MetaContract: + return 6 + case GraphQLSchema.AccountType.EthAddrReg: + return 0 + case GraphQLSchema.AccountType.Udt: + return 4 + } } + const AccountOverview: React.FC = ({ account, balance, @@ -161,6 +199,15 @@ const AccountOverview: React.FC = ({ isOverviewLoading, }) => { const [t] = useTranslation(['account', 'common']) + + const { data: verifyStatus, refetch: refetchStatus } = useQuery( + ['sourcify-check', account.eth_address], + () => fetchSourcifyStatus(account.eth_address), + { + enabled: !!account.eth_address, + }, + ) + return (
{account.type === GraphQLSchema.AccountType.MetaContract ? ( @@ -175,7 +222,9 @@ const AccountOverview: React.FC = ({ deployer={deployerAddr} deployTxHash={account.smart_contract?.deployment_tx_hash} udt={account.udt} - isVerified={!!account.smart_contract?.abi} + address={account.eth_address} + isVerified={!!account.smart_contract?.contract_source_code} + refetchStatus={refetchStatus} /> ) : null} {account.type === GraphQLSchema.AccountType.PolyjuiceCreator ? ( @@ -207,13 +256,13 @@ const AccountOverview: React.FC = ({ new BigNumber(Math.max(account.nonce ?? 0, account.transaction_count ?? 0)).toFormat() ), }, - OverviewPlaceHolderCount[account.type] + overviewPlaceHolderCount(account) ? { field: '', content: (
), } diff --git a/components/InfoList/index.tsx b/components/InfoList/index.tsx index 2d95eabf6..1c6941f41 100644 --- a/components/InfoList/index.tsx +++ b/components/InfoList/index.tsx @@ -1,7 +1,7 @@ import styles from './styles.module.scss' const InfoList: React.FC<{ - title?: string + title?: string | React.ReactNode list: Array<{ field: string; content: React.ReactNode; expandable?: boolean }> style?: React.CSSProperties type?: 'one-column' | 'two-columns' diff --git a/components/InfoList/styles.module.scss b/components/InfoList/styles.module.scss index 6a960a637..59650f67c 100644 --- a/components/InfoList/styles.module.scss +++ b/components/InfoList/styles.module.scss @@ -42,6 +42,9 @@ font-size: 1rem; color: var(--primary-text-color); border-bottom: 1px solid var(--border-color); + dt { + flex: 1 0 100% !important; + } } dl.item { diff --git a/components/SmartContract.tsx b/components/SmartContract.tsx deleted file mode 100644 index 9e7d8583f..000000000 --- a/components/SmartContract.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { useTranslation } from 'next-i18next' -import NextLink from 'next/link' -import Tooltip from 'components/Tooltip' -import InfoList from './InfoList' -import { AddModeratorOutlined as RegisterIcon } from '@mui/icons-material' -import { GraphQLSchema } from 'utils' - -const CONTRACT_FORM_URL = `https://github.com/Magickbase/godwoken_explorer/issues/new/choose` - -const SmartContract: React.FC<{ - deployer: string - deployTxHash: string - udt: Pick | null - isVerified: boolean -}> = ({ deployer, deployTxHash, udt, isVerified }) => { - const [t] = useTranslation('account') - const list = [ - { - field: t('type'), - content: 'Smart Contract', - }, - deployer - ? { - field: t('deployer'), - content: ( - - - - {deployer} - - - - ), - } - : null, - deployTxHash - ? { - field: t('deployTx'), - content: ( - - - - {deployTxHash} - - - - ), - } - : null, - udt?.id - ? { - field: t('token'), - content: ( - - {udt.name ?? '-'} - - ), - } - : null, - { - field: t('verify_status'), - content: isVerified ? ( - t(`verified`) - ) : ( - - {t(`unverified`)} - - ), - }, - ] - - return -} - -export default SmartContract diff --git a/components/SmartContractInfo/index.tsx b/components/SmartContractInfo/index.tsx new file mode 100644 index 000000000..0d1314cc7 --- /dev/null +++ b/components/SmartContractInfo/index.tsx @@ -0,0 +1,166 @@ +import { useTranslation } from 'next-i18next' +import NextLink from 'next/link' +import Tooltip from 'components/Tooltip' +import InfoList from '../InfoList' +import { client, GraphQLSchema } from 'utils' +import NextPageIcon from 'assets/icons/next-page.svg' +import VerifiedIcon from 'assets/icons/check-success.svg' +import SubmittedIcon from 'assets/icons/submit-success.svg' +import { Skeleton } from '@mui/material' +import { useState } from 'react' +import { gql } from 'graphql-request' +import styles from './styles.module.scss' + +const CONTRACT_FORM_URL = `https://github.com/Magickbase/godwoken_explorer/issues/new/choose` + +const verifyAndUpdateFromSourcify = gql` + mutation verifyAndUpdateFromSourcify($address: HashAddress!) { + verify_and_update_from_sourcify(input: { address: $address }) { + account_id + } + } +` + +export const recheckVerifyStatus = (address: string) => + client + .request<{ verify_and_update_from_sourcify: { account_id: string | null } }>(verifyAndUpdateFromSourcify, { + address: address, + }) + .then(data => data.verify_and_update_from_sourcify.account_id) + +const SmartContract: React.FC<{ + deployer: string + deployTxHash: string + udt: Pick | null + isVerified: boolean + refetchStatus: any + address: string +}> = ({ deployer, deployTxHash, udt, isVerified, refetchStatus, address }) => { + const [t] = useTranslation('account') + const [checkAgain, setCheckAgain] = useState(false) + const [isSourcifyCheckLoading, setIsSourcifyCheckLoading] = useState(false) + + const { official_site, description, icon } = udt || {} + const isSubmitted = official_site || description || icon + + const list = [ + { + field: t('type'), + content: 'Smart Contract', + }, + deployer + ? { + field: t('deployer'), + content: ( + + + + {deployer} + + + + ), + } + : null, + deployTxHash + ? { + field: t('deployTx'), + content: ( + + + + {deployTxHash} + + + + ), + } + : null, + udt?.id + ? { + field: t('token'), + content: ( + + {udt.name ?? '-'} + + ), + } + : null, + !isVerified + ? { + field: t('verify_status'), + content: isSourcifyCheckLoading ? ( + + ) : ( + { + try { + setIsSourcifyCheckLoading(true) + const res = await recheckVerifyStatus(address) + if (res) { + if (checkAgain) await refetchStatus() + } else { + window.open('https://sourcify.dev/#/verifier', '_blank').focus() + setCheckAgain(true) + } + setIsSourcifyCheckLoading(false) + } catch { + // TODO: remove next 2 lines after api has error handling other than 500 + window.open('https://sourcify.dev/#/verifier', '_blank').focus() + setCheckAgain(true) + setIsSourcifyCheckLoading(false) + } + }} + style={{ display: 'flex', alignItems: 'center' }} + > + {checkAgain ? t(`verify_again`) : t(`verifyBySourcify`)}{' '} + + + ), + } + : null, + !isSubmitted + ? { + field: t('submit_info'), + content: ( + + {t(`register`)} + + ), + } + : null, + ] + + const TitleWithIcons = () => { + return ( +
+ {t(`basicInfo`)} +
+ {isVerified ? ( + +
+ +
+
+ ) : null} + {isSubmitted ? ( + +
+ +
+
+ ) : null} +
+
+ ) + } + + return } list={list} /> +} + +export default SmartContract diff --git a/components/SmartContractInfo/styles.module.scss b/components/SmartContractInfo/styles.module.scss new file mode 100644 index 000000000..a531ff881 --- /dev/null +++ b/components/SmartContractInfo/styles.module.scss @@ -0,0 +1,17 @@ +.title { + display: flex; + justify-content: space-between; + align-items: center; + padding-right: 1.5rem; + & span { + flex: 1 0 auto; + } + & div { + display: flex; + column-gap: 0.75rem; + height: 1.5rem; + & svg:hover { + filter: drop-shadow(0px 4px 8px rgba(0, 0, 0, 0.1)); + } + } +} diff --git a/public/locales/en-US/account.json b/public/locales/en-US/account.json index e0a2a4890..e2d365f5f 100644 --- a/public/locales/en-US/account.json +++ b/public/locales/en-US/account.json @@ -75,8 +75,12 @@ "events": "Events", "token": "Token", "verify_status": "verify status", - "verified": "verified", - "unverified": "verify it", + "verified": "Status Verified", + "submitted": "Information has been submitted", + "verifyBySourcify": "Verify by sourcify", + "register": "Register", + "submit_info": "Submit Info", + "verify_again": "Verify again", "anonymous_param": "anonymous parameter", "anonymous_response": "anonymous response", "connected_addr": "Connected Address:" diff --git a/public/locales/zh-CN/account.json b/public/locales/zh-CN/account.json index 0fcbf2275..00eba2023 100644 --- a/public/locales/zh-CN/account.json +++ b/public/locales/zh-CN/account.json @@ -75,8 +75,12 @@ "events": "事件", "token": "代币", "verify_status": "验证状态", - "verified": " 已验证", - "unverified": "去验证", + "verified": "状态已验证", + "submitted": "信息已提交", + "verifyBySourcify": "Sourcify 已验证", + "register": "注册", + "submit_info": "提交信息", + "verify_again": "再次验证", "anonymous_param": "匿名参数", "anonymous_response": " 匿名返回值", "connected_addr": " 已连接地址:" diff --git a/utils/graphql.ts b/utils/graphql.ts index 15453e6d5..a47277c57 100644 --- a/utils/graphql.ts +++ b/utils/graphql.ts @@ -42,7 +42,7 @@ export namespace GraphQLSchema { icon: string id: string name: string - official_size: string + official_site: string price: string script_hash: string supply: string From 9435bfda36b5ca51bd61661b4ea735f294ae0ebb Mon Sep 17 00:00:00 2001 From: Keith Date: Sat, 27 Aug 2022 17:12:16 +0800 Subject: [PATCH 07/10] refactor: refine check from sourcify --- components/AccountOverview/index.tsx | 14 ++---- components/SmartContractInfo/index.tsx | 64 +++++++++++++------------- pages/account/[id].tsx | 19 ++++---- public/locales/en-US/account.json | 3 +- public/locales/zh-CN/account.json | 3 +- 5 files changed, 48 insertions(+), 55 deletions(-) diff --git a/components/AccountOverview/index.tsx b/components/AccountOverview/index.tsx index 472228e1f..077ba883b 100644 --- a/components/AccountOverview/index.tsx +++ b/components/AccountOverview/index.tsx @@ -13,7 +13,6 @@ import InfoList from 'components/InfoList' import Amount from 'components/Amount' import styles from './styles.module.scss' import { GraphQLSchema, client, provider, PCKB_UDT_INFO } from 'utils' -import { useQuery } from 'react-query' export type BasicScript = Record<'args' | 'code_hash' | 'hash_type', string> export interface AccountBase { @@ -191,23 +190,16 @@ const overviewPlaceHolderCount = (account: AccountOverviewProps['account']) => { } } -const AccountOverview: React.FC = ({ +const AccountOverview: React.FC Promise }> = ({ account, balance, deployerAddr, isBalanceLoading, isOverviewLoading, + refetch, }) => { const [t] = useTranslation(['account', 'common']) - const { data: verifyStatus, refetch: refetchStatus } = useQuery( - ['sourcify-check', account.eth_address], - () => fetchSourcifyStatus(account.eth_address), - { - enabled: !!account.eth_address, - }, - ) - return (
{account.type === GraphQLSchema.AccountType.MetaContract ? ( @@ -224,7 +216,7 @@ const AccountOverview: React.FC = ({ udt={account.udt} address={account.eth_address} isVerified={!!account.smart_contract?.contract_source_code} - refetchStatus={refetchStatus} + refetch={refetch} /> ) : null} {account.type === GraphQLSchema.AccountType.PolyjuiceCreator ? ( diff --git a/components/SmartContractInfo/index.tsx b/components/SmartContractInfo/index.tsx index 0d1314cc7..a0af11f79 100644 --- a/components/SmartContractInfo/index.tsx +++ b/components/SmartContractInfo/index.tsx @@ -6,7 +6,6 @@ import { client, GraphQLSchema } from 'utils' import NextPageIcon from 'assets/icons/next-page.svg' import VerifiedIcon from 'assets/icons/check-success.svg' import SubmittedIcon from 'assets/icons/submit-success.svg' -import { Skeleton } from '@mui/material' import { useState } from 'react' import { gql } from 'graphql-request' import styles from './styles.module.scss' @@ -16,33 +15,52 @@ const CONTRACT_FORM_URL = `https://github.com/Magickbase/godwoken_explorer/issue const verifyAndUpdateFromSourcify = gql` mutation verifyAndUpdateFromSourcify($address: HashAddress!) { verify_and_update_from_sourcify(input: { address: $address }) { - account_id + abi } } ` -export const recheckVerifyStatus = (address: string) => +const verifyAndCheckSourcify = (address: string) => client - .request<{ verify_and_update_from_sourcify: { account_id: string | null } }>(verifyAndUpdateFromSourcify, { + .request<{ verify_and_update_from_sourcify: { abi: Array | null } }>(verifyAndUpdateFromSourcify, { address: address, }) - .then(data => data.verify_and_update_from_sourcify.account_id) + .then(data => data.verify_and_update_from_sourcify.abi) const SmartContract: React.FC<{ deployer: string deployTxHash: string udt: Pick | null isVerified: boolean - refetchStatus: any address: string -}> = ({ deployer, deployTxHash, udt, isVerified, refetchStatus, address }) => { + refetch: () => Promise +}> = ({ deployer, deployTxHash, udt, isVerified, address, refetch }) => { const [t] = useTranslation('account') - const [checkAgain, setCheckAgain] = useState(false) + const [isCheckAgain, setIsCheckAgain] = useState(false) const [isSourcifyCheckLoading, setIsSourcifyCheckLoading] = useState(false) const { official_site, description, icon } = udt || {} const isSubmitted = official_site || description || icon + const handleCheckClick = async (e: React.SyntheticEvent) => { + e.stopPropagation() + e.preventDefault() + try { + setIsSourcifyCheckLoading(true) + const abi = await verifyAndCheckSourcify(address) + if (!abi) { + setIsCheckAgain(true) + window.open('https://sourcify.dev/#/verifier', '_blank').focus() + return + } + await refetch() + } catch { + // ignore + } finally { + setIsSourcifyCheckLoading(false) + } + } + const list = [ { field: t('type'), @@ -90,30 +108,10 @@ const SmartContract: React.FC<{ ? { field: t('verify_status'), content: isSourcifyCheckLoading ? ( - + {t(`checking`)} ) : ( - { - try { - setIsSourcifyCheckLoading(true) - const res = await recheckVerifyStatus(address) - if (res) { - if (checkAgain) await refetchStatus() - } else { - window.open('https://sourcify.dev/#/verifier', '_blank').focus() - setCheckAgain(true) - } - setIsSourcifyCheckLoading(false) - } catch { - // TODO: remove next 2 lines after api has error handling other than 500 - window.open('https://sourcify.dev/#/verifier', '_blank').focus() - setCheckAgain(true) - setIsSourcifyCheckLoading(false) - } - }} - style={{ display: 'flex', alignItems: 'center' }} - > - {checkAgain ? t(`verify_again`) : t(`verifyBySourcify`)}{' '} + + {isCheckAgain ? t(`verify_again`) : t(`verifyBySourcify`)}{' '} ), @@ -143,9 +141,9 @@ const SmartContract: React.FC<{
{isVerified ? ( -
+ -
+
) : null} {isSubmitted ? ( diff --git a/pages/account/[id].tsx b/pages/account/[id].tsx index 0de85d764..9ec25e0c3 100644 --- a/pages/account/[id].tsx +++ b/pages/account/[id].tsx @@ -48,14 +48,14 @@ const Account = () => { const q = isEthAddress(id as string) ? { address: id as string } : { script_hash: id as string } - const { isLoading: _isAccountLoading, data: accountAndList } = useQuery( - ['account', id], - () => fetchAccountOverview(q), - { - refetchInterval: 10000, - enabled: !!id, - }, - ) + const { + isLoading: _isAccountLoading, + data: accountAndList, + refetch: refetchAccountOverview, + } = useQuery(['account', id], () => fetchAccountOverview(q), { + refetchInterval: 10000, + enabled: !!id, + }) const deployment_tx_hash = isSmartContractAccount(accountAndList) && accountAndList?.smart_contract?.deployment_tx_hash @@ -170,7 +170,7 @@ const Account = () => { ].filter(v => v) return ( <> - +
{title} @@ -188,6 +188,7 @@ const Account = () => { account={account} balance={balance} deployerAddr={deployerAddr} + refetch={refetchAccountOverview} /> ) : null}
diff --git a/public/locales/en-US/account.json b/public/locales/en-US/account.json index e2d365f5f..e63db4a37 100644 --- a/public/locales/en-US/account.json +++ b/public/locales/en-US/account.json @@ -83,5 +83,6 @@ "verify_again": "Verify again", "anonymous_param": "anonymous parameter", "anonymous_response": "anonymous response", - "connected_addr": "Connected Address:" + "connected_addr": "Connected Address:", + "checking": "Checking..." } diff --git a/public/locales/zh-CN/account.json b/public/locales/zh-CN/account.json index 00eba2023..a863ca77d 100644 --- a/public/locales/zh-CN/account.json +++ b/public/locales/zh-CN/account.json @@ -83,5 +83,6 @@ "verify_again": "再次验证", "anonymous_param": "匿名参数", "anonymous_response": " 匿名返回值", - "connected_addr": " 已连接地址:" + "connected_addr": " 已连接地址:", + "checking": "检查中..." } From 0d75ad32e7a43411a2a406657729bd069a47a225 Mon Sep 17 00:00:00 2001 From: Keith Date: Sat, 27 Aug 2022 17:34:27 +0800 Subject: [PATCH 08/10] fix: fix typo --- public/locales/zh-CN/account.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/locales/zh-CN/account.json b/public/locales/zh-CN/account.json index a863ca77d..82e98c310 100644 --- a/public/locales/zh-CN/account.json +++ b/public/locales/zh-CN/account.json @@ -77,7 +77,7 @@ "verify_status": "验证状态", "verified": "状态已验证", "submitted": "信息已提交", - "verifyBySourcify": "Sourcify 已验证", + "verifyBySourcify": "从 Sourcify 验证", "register": "注册", "submit_info": "提交信息", "verify_again": "再次验证", From ed1b253acee255e518eb08c659a938e6287a3633 Mon Sep 17 00:00:00 2001 From: Keith Date: Sat, 27 Aug 2022 17:50:36 +0800 Subject: [PATCH 09/10] refactor: refine overview placeholder of contract account --- components/AccountOverview/index.tsx | 21 ++++++---- components/SmartContractInfo/index.tsx | 57 +++++++++++++------------- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/components/AccountOverview/index.tsx b/components/AccountOverview/index.tsx index 077ba883b..356a988bd 100644 --- a/components/AccountOverview/index.tsx +++ b/components/AccountOverview/index.tsx @@ -171,16 +171,19 @@ const overviewPlaceHolderCount = (account: AccountOverviewProps['account']) => { case GraphQLSchema.AccountType.PolyjuiceCreator: return 1 case GraphQLSchema.AccountType.PolyjuiceContract: - const isVerified = !!account.smart_contract?.contract_source_code - if (!!account.smart_contract?.deployment_tx_hash && isVerified) { - return 2 - } else if (!!account.smart_contract?.deployment_tx_hash && !isVerified) { - return 3 - } else if (!account.smart_contract?.deployment_tx_hash && isVerified) { - return 0 - } else { - return 1 + let count = 1 + if (account.udt?.id) { + count++ } + + if (!account.smart_contract?.contract_source_code) { + count++ + } + + if (!account.udt?.icon && !account.udt?.description && !account.udt?.official_site) { + count++ + } + return count case GraphQLSchema.AccountType.MetaContract: return 6 case GraphQLSchema.AccountType.EthAddrReg: diff --git a/components/SmartContractInfo/index.tsx b/components/SmartContractInfo/index.tsx index a0af11f79..33c8cadd1 100644 --- a/components/SmartContractInfo/index.tsx +++ b/components/SmartContractInfo/index.tsx @@ -1,5 +1,6 @@ import { useTranslation } from 'next-i18next' import NextLink from 'next/link' +import { Skeleton } from '@mui/material' import Tooltip from 'components/Tooltip' import InfoList from '../InfoList' import { client, GraphQLSchema } from 'utils' @@ -66,34 +67,34 @@ const SmartContract: React.FC<{ field: t('type'), content: 'Smart Contract', }, - deployer - ? { - field: t('deployer'), - content: ( - - - - {deployer} - - - - ), - } - : null, - deployTxHash - ? { - field: t('deployTx'), - content: ( - - - - {deployTxHash} - - - - ), - } - : null, + { + field: t('deployer'), + content: deployer ? ( + + + + {deployer} + + + + ) : ( + + ), + }, + { + field: t('deployTx'), + content: deployTxHash ? ( + + + + {deployTxHash} + + + + ) : ( + + ), + }, udt?.id ? { field: t('token'), From 019048ddb4cf87de6ecb838f4f9f9c4b08fe2272 Mon Sep 17 00:00:00 2001 From: Keith Date: Sun, 11 Feb 2024 03:14:41 +0900 Subject: [PATCH 10/10] chore: update copyright --- components/Footer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Footer.tsx b/components/Footer.tsx index 9b955c33a..095796fb2 100644 --- a/components/Footer.tsx +++ b/components/Footer.tsx @@ -179,7 +179,7 @@ const Footer = () => { opacity: 0.5, }} > - Copyright © 2022 Magickbase All Rights Reserved. + Copyright © 2024 Magickbase All Rights Reserved.