Skip to content

Commit

Permalink
Merge pull request #523 from Magickbase/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Keith-CY authored Sep 7, 2022
2 parents add1a7c + 53c9963 commit 4d89c51
Show file tree
Hide file tree
Showing 19 changed files with 286 additions and 74 deletions.
3 changes: 3 additions & 0 deletions assets/icons/is-pending-tx-list.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions components/AccountOverview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ const AccountOverview: React.FC<AccountOverviewProps & { refetch: () => Promise<
address={account.eth_address}
isVerified={!!account.smart_contract?.contract_source_code}
refetch={refetch}
isLoading={isOverviewLoading}
/>
) : null}
{account.type === GraphQLSchema.AccountType.PolyjuiceCreator ? (
Expand Down
1 change: 0 additions & 1 deletion components/AssetList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useTranslation } from 'next-i18next'
import NextLink from 'next/link'
import { gql } from 'graphql-request'
import BigNumber from 'bignumber.js'
import Table from 'components/Table'
import TokenLogo from 'components/TokenLogo'
import Amount from 'components/Amount'
Expand Down
11 changes: 8 additions & 3 deletions components/SmartContractInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ const SmartContract: React.FC<{
udt: Pick<GraphQLSchema.Udt, 'id' | 'name' | 'official_site' | 'description' | 'icon'> | null
isVerified: boolean
address: string
isLoading: boolean
refetch: () => Promise<void>
}> = ({ deployer, deployTxHash, udt, isVerified, address, refetch }) => {
}> = ({ deployer, deployTxHash, udt, isVerified, address, refetch, isLoading }) => {
const [t] = useTranslation('account')
const [isCheckAgain, setIsCheckAgain] = useState(false)
const [isSourcifyCheckLoading, setIsSourcifyCheckLoading] = useState(false)
Expand Down Expand Up @@ -77,8 +78,10 @@ const SmartContract: React.FC<{
</NextLink>
</span>
</Tooltip>
) : (
) : isLoading ? (
<Skeleton animation="wave" />
) : (
'-'
),
},
{
Expand All @@ -91,8 +94,10 @@ const SmartContract: React.FC<{
</NextLink>
</span>
</Tooltip>
) : (
) : isLoading ? (
<Skeleton animation="wave" />
) : (
'-'
),
},
udt?.id
Expand Down
26 changes: 15 additions & 11 deletions components/TxList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const txListQuery = gql`
$limit: Int
$start_block_number: Int
$end_block_number: Int
$status: Status
) {
transactions(
input: {
Expand All @@ -56,6 +57,7 @@ const txListQuery = gql`
start_block_number: $start_block_number
end_block_number: $end_block_number
combine_from_to: true
status: $status
}
) {
entries {
Expand Down Expand Up @@ -93,25 +95,27 @@ const txListQuery = gql`
}
}
`
interface Cursor {
type Status = 'PENDING' | 'ON_CHAINED' | null
interface Filter {
limit?: number
before: string
after: string
start_block_number?: number | null
end_block_number?: number | null
status?: Status
}
interface EthAccountTxListVariables extends Nullable<Cursor> {
interface EthAccountTxListVariables extends Nullable<Filter> {
address?: string | null
}
interface GwAccountTxListVariables extends Nullable<Cursor> {
interface GwAccountTxListVariables extends Nullable<Filter> {
script_hash?: string | null
}
interface BlockTxListVariables extends Nullable<Cursor> {}
type Variables = Cursor | EthAccountTxListVariables | GwAccountTxListVariables | BlockTxListVariables
interface BlockTxListVariables extends Nullable<Filter> {}
type Variables = Filter | EthAccountTxListVariables | GwAccountTxListVariables | BlockTxListVariables

export const fetchTxList = (variables: Variables) =>
export const fetchTxList = ({ status = 'ON_CHAINED', ...variables }: Variables) =>
client
.request<TxListProps>(txListQuery, variables)
.request<TxListProps>(txListQuery, { status, ...variables })
.then(data => data.transactions)
.catch(() => ({ entries: [], metadata: { before: null, after: null, total_count: 0 } }))

Expand Down Expand Up @@ -153,7 +157,7 @@ const TxList: React.FC<TxListProps & { maxCount?: string; pageSize?: number }> =
entries.map(item => {
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 to = item.to_account?.eth_address || item.to_account?.script_hash || '-'
const method = item.method_name || item.method_id

return (
Expand All @@ -166,7 +170,7 @@ const TxList: React.FC<TxListProps & { maxCount?: string; pageSize?: number }> =
</div>
</Tooltip>
<TxStatusIcon
status={getBlockStatus(item.block?.status)}
status={getBlockStatus(item.block?.status ?? GraphQLSchema.BlockStatus.Pending)}
isSuccess={
item.polyjuice ? item.polyjuice.status === GraphQLSchema.PolyjuiceStatus.Succeed : true
}
Expand Down Expand Up @@ -203,10 +207,10 @@ const TxList: React.FC<TxListProps & { maxCount?: string; pageSize?: number }> =
)}
</td>
<td>
<Address address={from} type={item.from_account.type} />
<Address address={from} type={item.from_account?.type} />
</td>
<td>
<Address address={to} type={item.to_account.type} />
<Address address={to} type={item.to_account?.type} />
</td>
<td className={styles.direction}>
<TransferDirection from={from} to={to} viewer={viewer ?? ''} />
Expand Down
9 changes: 6 additions & 3 deletions components/TxStatusIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ import type { TxStatus } from 'utils'

const TxStatusIcon: React.FC<{ status: TxStatus; isSuccess?: boolean }> = ({ status, isSuccess = false }) => {
const [t] = useTranslation('common')
if (!isSuccess) {
return <FailedIcon style={{ flexShrink: 0 }} />
}

if (status === 'pending') {
return (
Expand All @@ -19,6 +16,11 @@ const TxStatusIcon: React.FC<{ status: TxStatus; isSuccess?: boolean }> = ({ sta
</Tooltip>
)
}

if (!isSuccess) {
return <FailedIcon style={{ flexShrink: 0 }} />
}

if (status === 'committed') {
return (
<Tooltip title={t(status)} placement="top">
Expand All @@ -37,6 +39,7 @@ const TxStatusIcon: React.FC<{ status: TxStatus; isSuccess?: boolean }> = ({ sta
</Tooltip>
)
}

return <FailedIcon style={{ flexShrink: 0 }} />
}

Expand Down
22 changes: 5 additions & 17 deletions pages/account/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,14 @@ const Account = () => {
const q = isEthAddress(id as string) ? { address: id as string } : { script_hash: id as string }

const {
isLoading: _isAccountLoading,
data: accountAndList,
isLoading: isOverviewLoading,
data: account,
refetch: refetchAccountOverview,
} = useQuery(['account', id], () => fetchAccountOverview(q), {
} = useQuery(['account-overview', id], () => fetchAccountOverview(q), {
refetchInterval: 10000,
enabled: !!id,
})

const deployment_tx_hash =
isSmartContractAccount(accountAndList) && accountAndList?.smart_contract?.deployment_tx_hash
const deployment_tx_hash = isSmartContractAccount(account) && account?.smart_contract?.deployment_tx_hash

const { data: deployerAddr } = useQuery(
['deployer', deployment_tx_hash],
Expand All @@ -69,15 +67,6 @@ const Account = () => {
{ enabled: !!deployment_tx_hash },
)

const { isLoading: isOverviewLoading, data: overview } = useQuery(
['account-overview', id],
() => fetchAccountOverview(q),
{
refetchInterval: 10000,
enabled: !!id,
},
)

const { isLoading: isBalanceLoading, data: balance = '0' } = useQuery(
['account-balance', id],
() => fetchAccountBalance(id as string),
Expand All @@ -97,6 +86,7 @@ const Account = () => {
start_block_number: block_from ? +block_from : null,
end_block_number: block_to ? +block_to : null,
limit: +page_size,
status: null,
}),
{
enabled: tab === 'transactions' && !!id,
Expand Down Expand Up @@ -133,8 +123,6 @@ const Account = () => {
{ enabled: tab === 'assets' && !!(q.address || q.script_hash) },
)

const account = overview ?? accountAndList ?? null

/* is script hash supported? */
const downloadItems = account?.eth_address
? [
Expand Down
16 changes: 10 additions & 6 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const VIDEO_NAME = IS_MAINNET ? 'home-video' : 'testnet-home-video'

const queryHomeLists = gql`
query {
transactions(input: { limit: 10 }) {
transactions(input: { limit: 10, status: ON_CHAINED }) {
entries {
eth_hash
hash
Expand Down Expand Up @@ -447,9 +447,9 @@ const TxList: React.FC<{ list: HomeLists['transactions']['entries']; isLoading:
{list?.slice(0, length).map((tx, idx) => {
const hash = tx.eth_hash ?? tx.hash
const from = tx.from_account.eth_address || tx.from_account.script_hash
const to = tx.to_account.eth_address || tx.to_account.script_hash
const to = tx.to_account?.eth_address || tx.to_account?.script_hash || '-'
const isSpecialFrom = SPECIAL_ADDR_TYPES.includes(tx.from_account.type)
const isSpecialTo = SPECIAL_ADDR_TYPES.includes(tx.to_account.type)
const isSpecialTo = SPECIAL_ADDR_TYPES.includes(tx.to_account?.type)
return (
<Box key={hash} sx={{ '& :hover': { backgroundColor: 'primary.light' } }}>
{idx !== 0 && <Divider variant="middle" color="#f0f0f0" sx={{ borderColor: 'transparent' }} />}
Expand Down Expand Up @@ -506,9 +506,13 @@ const TxList: React.FC<{ list: HomeLists['transactions']['entries']; isLoading:
pt={0.5}
color="secondary.light"
>
<time dateTime={new Date(tx.block.timestamp).toISOString()} title={t('timestamp')}>
{timeDistance(tx.block.timestamp, language)}
</time>
{tx.block ? (
<time dateTime={new Date(tx.block.timestamp).toISOString()} title={t('timestamp')}>
{timeDistance(tx.block.timestamp, language)}
</time>
) : (
t('pending')
)}
</Box>
</Stack>
<Stack
Expand Down
58 changes: 56 additions & 2 deletions pages/token/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { GetStaticProps, GetStaticPaths } from 'next'
import { useEffect } from 'react'
import { useEffect, useState } from 'react'
import { useTranslation } from 'next-i18next'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { useRouter } from 'next/router'
Expand All @@ -15,21 +15,28 @@ import TokenHolderList from 'components/TokenHolderList/index'
import HashLink from 'components/HashLink'
import DownloadMenu, { DOWNLOAD_HREF_LIST } from 'components/DownloadMenu'
import Amount from 'components/Amount'
import Alert from 'components/Alert'
import { fetchToken, fetchBridgedRecordList, fetchTokenHolderList } from 'utils'
import styles from './styles.module.scss'

import type { API } from 'utils/api/utils'
import { SIZES } from 'components/PageSize'
import TokenLogo from 'components/TokenLogo'
import Tooltip from 'components/Tooltip'

const tabs = ['transfers', 'bridged', 'holders']

const isEtheremInjected = (ethereum: any): ethereum is { request: Function } => {
return ethereum && 'request' in ethereum && typeof ethereum.request === 'function'
}

type Props = {
token: API.Token.Parsed
}

const Token: React.FC<Props> = () => {
const [t, { language }] = useTranslation('tokens')
const [msg, setMsg] = useState<{ type: 'success' | 'error'; text: string }>(null)
const {
replace,
query: { id, tab = 'transfers', page = '1', before = null, after = null, page_size = SIZES[1] },
Expand Down Expand Up @@ -142,6 +149,36 @@ const Token: React.FC<Props> = () => {
},
]

const handleImportIntoMetamask = async () => {
const ethereum: unknown | undefined = window['ethereum']
if (isEtheremInjected(ethereum)) {
const symbol = token.symbol.split('.')[0] || ''
try {
await ethereum.request({
method: 'wallet_watchAsset',
params: {
type: 'ERC20',
options: {
address: token.address,
symbol,
decimals: token.decimal,
image: token.icon,
},
},
})
setMsg({ type: 'success', text: t(`import-token-success`) })
} catch (err) {
if (err.code === 4001) {
setMsg({ type: 'error', text: t(`rejected-by-metamask`) })
return
}
setMsg({ type: 'error', text: err.message })
}
return
}
setMsg({ type: 'error', text: t(`ethereum-is-not-injected`) })
}

return (
<>
<SubpageHead subtitle={`${t('token')} ${token?.name || token?.symbol || '-'}`} />
Expand All @@ -158,7 +195,23 @@ const Token: React.FC<Props> = () => {
<DownloadMenu items={downloadItems} />
</PageTitle>
<div className={styles.overview}>
<InfoList title={t(`tokenInfo`)} list={tokenInfo} />
<InfoList
title={
<div className={styles.infoTitle}>
{t(`tokenInfo`)}
<Tooltip title={t('import-token-into-metamask')} placement="top">
<img
src="/logos/metamask.png"
alt="MetaMask"
className={styles.metamask}
title={t('import-into-metamask')}
onClick={handleImportIntoMetamask}
/>
</Tooltip>
</div>
}
list={tokenInfo}
/>
<InfoList title={t(`tokenData`)} list={tokenData} />
</div>

Expand Down Expand Up @@ -193,6 +246,7 @@ const Token: React.FC<Props> = () => {
) : null}
</div>
</div>
<Alert open={!!msg} onClose={() => setMsg(null)} content={msg?.text} type={msg?.type} />
</>
)
}
Expand Down
17 changes: 17 additions & 0 deletions pages/token/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,20 @@
border-radius: 0.5rem;
}
}

.infoTitle {
display: flex;
align-items: center;
justify-content: space-between;
padding-right: 1rem;
}

.metamask {
width: 1.6rem;
height: 1.6rem;
cursor: pointer;
@media screen and (max-width: 1024px) {
width: 1.25rem;
height: 1.25rem;
}
}
Loading

1 comment on commit 4d89c51

@vercel
Copy link

@vercel vercel bot commented on 4d89c51 Sep 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.