diff --git a/src/pages/Fiber/GraphChannelList/index.module.scss b/src/pages/Fiber/GraphChannelList/index.module.scss new file mode 100644 index 000000000..c5a79afc0 --- /dev/null +++ b/src/pages/Fiber/GraphChannelList/index.module.scss @@ -0,0 +1,138 @@ +@import '../../../styles/variables.module'; +@import '../../../styles/table.module'; + +.container { + margin: 24px 120px; + font-size: 1rem; + + .channels { + border-radius: 6px; + box-shadow: rgb(0 0 0 / 12%) 0 2px 6px 0; + overflow: hidden; + + .list { + font-size: 0.875rem; + + a { + color: var(--primary-color); + } + + svg { + pointer-events: none; + } + } + } + + button { + display: flex; + align-items: center; + appearance: none; + padding: 0; + border: none; + background: none; + cursor: pointer; + + &:hover { + color: var(--primary-color); + } + } + + .header { + font-size: 1.5rem; + margin-bottom: 20px; + } + + .channel { + margin-bottom: 4px; + background: #fff; + padding: 8px 40px; + + h1 { + font-size: 1.2rem; + } + + dl { + display: flex; + gap: 4px; + } + + dl, + dd, + dt { + margin: 0; + white-space: pre; + flex-wrap: wrap; + } + + dt { + &::after { + content: ':'; + } + } + + dd { + display: flex; + align-items: center; + gap: 4px; + } + + .general { + dd { + .content { + & > *:first-child { + display: none; + } + + @media screen and (width<800px) { + & > *:first-child { + display: flex; + } + + & > *:last-child { + display: none; + } + } + } + } + } + + .nodesContainer { + border-radius: 6px; + border: 1px solid #ccc; + padding: 8px; + margin-top: 8px; + } + + .nodes { + display: flex; + + h3 { + font-size: 1rem; + } + + gap: 20px; + + .node { + flex: 1; + } + + @media screen and (width<670px) { + flex-direction: column; + } + } + } + + .pagination { + background: #fff; + padding: 8px 40px; + margin-top: 4px; + } + + @media screen and (width < $extraLargeBreakPoint) { + margin: 24px 20px; + } + + @media screen and (width < 1330px) { + font-size: 14px; + } +} diff --git a/src/pages/Fiber/GraphChannelList/index.tsx b/src/pages/Fiber/GraphChannelList/index.tsx new file mode 100644 index 000000000..ce1c91fce --- /dev/null +++ b/src/pages/Fiber/GraphChannelList/index.tsx @@ -0,0 +1,176 @@ +import { useQuery } from '@tanstack/react-query' +import { useTranslation } from 'react-i18next' +import { Link } from 'react-router-dom' +import { Tooltip } from 'antd' +import { CopyIcon } from '@radix-ui/react-icons' +import dayjs from 'dayjs' +import Content from '../../../components/Content' +import { useSetToast } from '../../../components/Toast' +import { explorerService } from '../../../services/ExplorerService' +import { shannonToCkb } from '../../../utils/util' +import { localeNumberString } from '../../../utils/number' +import { parseNumericAbbr } from '../../../utils/chart' +import styles from './index.module.scss' +import Pagination from '../Pagination' +import { PAGE_SIZE } from '../../../constants/common' + +const TIME_TEMPLATE = 'YYYY/MM/DD hh:mm:ss' + +const GraphNodeList = () => { + const [t] = useTranslation() + const setToast = useSetToast() + + const { data } = useQuery({ + queryKey: ['fiber', 'graph', 'channels'], + queryFn: () => explorerService.api.getGraphChannels(), + }) + + const list = data?.data.fiberGraphChannels ?? [] + const pageInfo = data?.data.meta ?? { total: 1, pageSize: PAGE_SIZE } + const totalPages = Math.ceil(pageInfo.total / pageInfo.pageSize) + + const handleCopy = (e: React.SyntheticEvent) => { + const elm = e.target + if (!(elm instanceof HTMLElement)) return + const { copyText } = elm.dataset + if (!copyText) return + e.stopPropagation() + e.preventDefault() + navigator?.clipboard.writeText(copyText).then(() => setToast({ message: t('common.copied') })) + } + + return ( + +
+

+ CKB Fiber Graph Channels +

+
+
+ {list.map(channel => { + const outPoint = { + txHash: channel.channelOutpoint.slice(0, -8), + index: parseInt(channel.channelOutpoint.slice(-8), 16), + } + + const ckb = shannonToCkb(channel.capacity) + const amount = parseNumericAbbr(ckb) + return ( +
+

General

+
+
+
Out Point
+
+
+ + + {`${outPoint.txHash.slice(0, 6)}...${outPoint.txHash.slice(-6)}#${outPoint.index}`} + + + + {`${outPoint.txHash}#${outPoint.index}`} + +
+ +
+
+ +
+
Capacity
+
+ + {`${amount} CKB`} + +
+
+ +
+
Chain Hash
+
+
+ + {`${channel.chainHash.slice(0, 8)}...${channel.chainHash.slice( + -8, + )}`} + + {channel.chainHash} +
+ +
+
+ +
+
Funded at
+
+ + {localeNumberString(channel.fundingTxBlockNumber)} + + (
{dayjs(+channel.lastUpdatedTimestamp).format(TIME_TEMPLATE)}
) +
+
+
+ +
+

Nodes

+
+
+

First Node

+
+
Public Key
+
+ + {`${channel.node1.slice(0, 8)}...${channel.node1.slice( + -8, + )}`} + + +
+
+
+
Fee Rate
+
{`${localeNumberString(channel.node1ToNode2FeeRate)} shannon/kB`}
+
+
+
+

Second Node

+
+
Public Key
+
+ + {`${channel.node2.slice(0, 8)}...${channel.node2.slice( + -8, + )}`} + + +
+
+
+
Fee Rate
+
{`${localeNumberString(channel.node2ToNode1FeeRate)} shannon/kB`}
+
+
+
+
+
+ ) + })} +
+
+ +
+
+
+
+ ) +} + +export default GraphNodeList diff --git a/src/pages/Fiber/GraphNodeList/index.tsx b/src/pages/Fiber/GraphNodeList/index.tsx index ca56cb443..ad22a82f0 100644 --- a/src/pages/Fiber/GraphNodeList/index.tsx +++ b/src/pages/Fiber/GraphNodeList/index.tsx @@ -83,7 +83,7 @@ const fields = [ return ( - {v.length > 16 ? `${v.slice(0, 8)}...${v.slice(-8)}` : v} + {`${v.slice(0, 8)}...${v.slice(-8)}`}