diff --git a/src/locales/en.json b/src/locales/en.json
index f26b887ce3..03f2528469 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -735,6 +735,10 @@
"repeat_inscription_symbol": "This inscription is a duplicate with an earlier release of the same symbol."
},
"xudt": {
+ "holder_allocation": "Holder Allocation",
+ "holder_allocation_description": "There are {{ckb}} CKB Holders and {{btc}} BTC holders of current asset.",
+ "lock_hash": "Lock Hash",
+ "count": "Count",
"xudt": "xUDT",
"xudts": "xUDTs",
"name": "Name",
diff --git a/src/locales/zh.json b/src/locales/zh.json
index ccfe1fbbbc..a36049fc26 100644
--- a/src/locales/zh.json
+++ b/src/locales/zh.json
@@ -736,6 +736,10 @@
"repeat_inscription_symbol": "此铭文与早期发布的铭文同名"
},
"xudt": {
+ "holder_allocation": "地址分布",
+ "holder_allocation_description": "当前地址有{{ckb}} CKB地址持有人及{{btc}} BTC 地址持有人",
+ "lock_hash": "Lock Hash",
+ "count": "Count",
"xudt": "xUDT",
"xudts": "xUDTs",
"name": "名称",
diff --git a/src/pages/Xudt/HolderAllocation.module.scss b/src/pages/Xudt/HolderAllocation.module.scss
new file mode 100644
index 0000000000..60b09f14ea
--- /dev/null
+++ b/src/pages/Xudt/HolderAllocation.module.scss
@@ -0,0 +1,92 @@
+@import '../../styles/variables.module';
+
+.holderAllocationContainer {
+ background-color: #fff;
+ margin: 15% auto;
+ padding: 20px 40px;
+ width: 497px;
+ border-radius: 4px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 24px;
+
+ @media (max-width: $mobileBreakPoint) {
+ width: 90%;
+ margin-top: 40%;
+ padding: 24px 16px;
+ align-items: flex-start;
+
+ p {
+ line-height: 24px;
+ }
+ }
+
+ h2 {
+ color: #333;
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 700;
+ margin: 0;
+ }
+
+ p {
+ margin: 0;
+ color: #333;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ width: 100%;
+ word-wrap: break-word;
+ }
+
+ .table {
+ border-radius: 4px;
+ border: 1px solid #e5e5e5;
+ padding: 1px;
+
+ table {
+ thead {
+ background: #fafafa;
+
+ tr {
+ div {
+ color: #666;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: normal;
+ text-transform: capitalize;
+ }
+ }
+ }
+
+ tbody {
+ tr {
+ div {
+ color: #333;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: normal;
+ }
+ }
+ }
+
+ thead,
+ tbody {
+ tr {
+ border-radius: 4px;
+
+ div {
+ font-size: 14px;
+ padding: 12px 16px;
+ }
+ }
+ }
+
+ width: 312px;
+ background: #fff;
+ }
+ }
+}
diff --git a/src/pages/Xudt/HolderAllocation.tsx b/src/pages/Xudt/HolderAllocation.tsx
new file mode 100644
index 0000000000..309ec0bd96
--- /dev/null
+++ b/src/pages/Xudt/HolderAllocation.tsx
@@ -0,0 +1,76 @@
+import { useTranslation } from 'react-i18next'
+import styles from './HolderAllocation.module.scss'
+
+const HolderAllocation = ({ typeHash }: { typeHash: string }) => {
+ const [t] = useTranslation()
+ return (
+
+
{t('xudt.holder_allocation')}
+
+ {t('xudt.holder_allocation_description', {
+ ckb: '1,000',
+ btc: '200',
+ })}
+ {typeHash}
+
+
+
+
+
+
+ {t('xudt.lock_hash')}
+ |
+
+ {t('xudt.count')}
+ |
+
+
+
+
+
+ secp256k1
+ |
+
+ 200
+ |
+
+
+
+ omnilock
+ |
+
+ 400
+ |
+
+
+
+ joyid
+ |
+
+ 100
+ |
+
+
+
+ RGB++
+ |
+
+ 400
+ |
+
+
+
+ other
+ |
+
+ 300
+ |
+
+
+
+
+
+ )
+}
+
+export default HolderAllocation
diff --git a/src/pages/Xudt/UDTComp.tsx b/src/pages/Xudt/UDTComp.tsx
index 972beba9f1..53c658a808 100644
--- a/src/pages/Xudt/UDTComp.tsx
+++ b/src/pages/Xudt/UDTComp.tsx
@@ -8,7 +8,6 @@ import { EyeClosedIcon, EyeOpenIcon } from '@radix-ui/react-icons'
import { Link } from '../../components/Link'
import { CsvExport } from '../../components/CsvExport'
import TransactionItem from '../../components/TransactionItem/index'
-import { UDTTransactionsPagination, UDTTransactionsPanel, TypeScriptController, UDTNoResultPanel } from './styled'
import { parseUDTAmount } from '../../utils/number'
import { ReactComponent as OpenInNew } from '../../assets/open_in_new.svg'
import { deprecatedAddrToNewAddr, getBtcUtxo } from '../../utils/util'
@@ -23,6 +22,9 @@ import { RawBtcRPC } from '../../services/ExplorerService'
import { XUDT } from '../../models/Xudt'
import { getBtcTxList } from '../../services/ExplorerService/fetcher'
import XUDTTag from '../../components/XUDTTag'
+import SimpleButton from '../../components/SimpleButton'
+import SimpleModal from '../../components/Modal'
+import HolderAllocation from './HolderAllocation'
const IssuerContent: FC<{ address: string }> = ({ address }) => {
const { t } = useTranslation()
@@ -56,6 +58,7 @@ export const UDTOverviewCard = ({ typeHash, xudt }: { typeHash: string; xudt: XU
const { t } = useTranslation()
const isMobile = useIsMobile()
const [isScriptDisplayed, setIsScriptDisplayed] = useState(false)
+ const [showHolderAmountModal, setShowHolderAmountModal] = useState(false)
const issuer = xudt?.issuerAddress
const script = xudt?.typeScript ?? null
@@ -104,7 +107,18 @@ export const UDTOverviewCard = ({ typeHash, xudt }: { typeHash: string; xudt: XU
},
{
title: t('xudt.holder_addresses'),
- content: xudt?.addressesCount ?? '-',
+ content: xudt?.addressesCount ? (
+ {
+ setShowHolderAmountModal(true)
+ }}
+ >
+ {xudt.addressesCount}
+
+ ) : (
+ '-'
+ ),
},
{
title: t('xudt.symbol'),
@@ -137,8 +151,11 @@ export const UDTOverviewCard = ({ typeHash, xudt }: { typeHash: string; xudt: XU
+
+
+
-
+
{isScriptDisplayed ? (
@@ -150,7 +167,7 @@ export const UDTOverviewCard = ({ typeHash, xudt }: { typeHash: string; xudt: XU
{t('xudt.type_script_hash')}
)}
-
+
{isScriptDisplayed ? (
script &&
@@ -184,14 +201,14 @@ export const UDTComp = ({
if (filterNoResult) {
return (
-
+
{t('search.udt_filter_no_result')}
-
+
)
}
return (
<>
-
+
{transactions.map(
(transaction, index) =>
transaction && (
@@ -204,15 +221,15 @@ export const UDTComp = ({
/>
),
)}
-
-
+
+
>
)
}
diff --git a/src/pages/Xudt/index.tsx b/src/pages/Xudt/index.tsx
index 2b1a373f85..2e10eb8ff1 100644
--- a/src/pages/Xudt/index.tsx
+++ b/src/pages/Xudt/index.tsx
@@ -1,8 +1,8 @@
import { useParams } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { useQuery } from '@tanstack/react-query'
+import classNames from 'classnames'
import Content from '../../components/Content'
-import { UDTContentPanel, UDTTransactionTitlePanel } from './styled'
import UDTComp, { UDTOverviewCard } from './UDTComp'
import { usePaginationParamsInPage, useSearchParams, useUpdateSearchParams } from '../../hooks'
import Filter from '../../components/Filter'
@@ -67,12 +67,12 @@ export const Xudt = () => {
return (
-
+
-
-
-
+
+
+
{`${t('transaction.transactions')} (${localeNumberString(total)})`}
@@ -85,7 +85,7 @@ export const Xudt = () => {
/>
-
+
{data => (
@@ -100,7 +100,7 @@ export const Xudt = () => {
/>
)}
-
+
)
}
diff --git a/src/pages/Xudt/styled.tsx b/src/pages/Xudt/styled.tsx
deleted file mode 100644
index d8c28d3eb7..0000000000
--- a/src/pages/Xudt/styled.tsx
+++ /dev/null
@@ -1,104 +0,0 @@
-import styled from 'styled-components'
-import SimpleButton from '../../components/SimpleButton'
-import variables from '../../styles/variables.module.scss'
-
-export const UDTContentPanel = styled.div`
- display: flex;
- flex-direction: column;
- align-items: center;
- margin-top: 25px;
- margin-bottom: 40px;
-
- @media (max-width: ${variables.mobileBreakPoint}) {
- margin: 0;
- padding: 20px;
- }
-`
-
-export const TypeScriptController = styled(SimpleButton)`
- font-size: 16px;
- font-weight: 600;
- cursor: pointer;
- color: ${props => props.theme.primary};
- display: flex;
- align-items: center;
-
- > img {
- width: 12px;
- height: 12px;
- margin: 2px 0 0 5px;
- }
-
- @media (max-width: ${variables.mobileBreakPoint}) {
- font-size: 14px;
-
- > img {
- margin: 0 0 0 5px;
- }
- }
-`
-
-export const UDTTransactionsPanel = styled.div`
- width: 100%;
-`
-
-export const UDTTransactionsPagination = styled.div`
- margin-top: 4px;
- width: 100%;
-`
-
-export const UDTTransactionTitlePanel = styled.div`
- width: 100%;
- height: 58px;
- padding: 0 40px;
- background: white;
- border-radius: 6px 6px 0 0;
- box-shadow: 2px 2px 6px 0 #dfdfdf;
-
- @media (max-width: ${variables.mobileBreakPoint}) {
- height: 108px;
- padding: 16px;
- }
-
- .udtTransactionContainer {
- width: 100%;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: space-between;
- font-size: 18px;
- margin-bottom: 5px;
-
- @media (max-width: ${variables.mobileBreakPoint}) {
- flex-direction: column;
- align-items: flex-start;
- }
- }
-
- .udtTransactionTitle {
- font-size: 24px;
- font-weight: 600;
- font-style: normal;
- line-height: 0.83;
- }
-`
-
-export const UDTNoResultPanel = styled.div`
- width: 100%;
- height: 94px;
- border-radius: 0 0 6px 6px;
- box-shadow: 0 2px 6px 0 rgb(0 0 0 / 12%);
- background-color: #fff;
- margin-top: 4px;
- display: flex;
- justify-content: center;
- align-items: center;
-
- > span {
- white-space: pre-wrap;
- font-size: 14px;
- letter-spacing: 0.2px;
- color: #666;
- text-align: center;
- }
-`
diff --git a/src/pages/Xudt/styles.module.scss b/src/pages/Xudt/styles.module.scss
index 918481d460..8264b704fc 100644
--- a/src/pages/Xudt/styles.module.scss
+++ b/src/pages/Xudt/styles.module.scss
@@ -1,5 +1,58 @@
@import '../../styles/variables.module';
+.container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin-top: 25px;
+ margin-bottom: 40px;
+
+ @media (max-width: $mobileBreakPoint) {
+ margin: 0;
+ padding: 20px;
+ }
+}
+
+.uDTTransactionTitlePanel {
+ width: 100%;
+ height: 58px;
+ padding: 0 40px;
+ background: white;
+ border-radius: 6px 6px 0 0;
+ box-shadow: 2px 2px 6px 0 #dfdfdf;
+
+ @media (max-width: $mobileBreakPoint) {
+ height: 108px;
+ padding: 16px;
+ }
+
+ .udtTransactionContainer {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ font-size: 18px;
+ margin-bottom: 5px;
+
+ @media (max-width: $mobileBreakPoint) {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+ }
+
+ .udtTransactionTitle {
+ font-size: 24px;
+ font-weight: 600;
+ font-style: normal;
+ line-height: 0.83;
+ }
+}
+
+.holderAddressesButton {
+ color: var(--primary-color);
+}
+
.udtOverviewCard:not(
[_='This `:not` selector is used to increase the specificity of the selector and serves no other purpose.']
) {
@@ -168,3 +221,55 @@
background: #f7f7f7;
word-break: break-all;
}
+
+.uDTNoResultPanel {
+ width: 100%;
+ height: 94px;
+ border-radius: 0 0 6px 6px;
+ box-shadow: 0 2px 6px 0 rgb(0 0 0 / 12%);
+ background-color: #fff;
+ margin-top: 4px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ > span {
+ white-space: pre-wrap;
+ font-size: 14px;
+ letter-spacing: 0.2px;
+ color: #666;
+ text-align: center;
+ }
+}
+
+.uDTTransactionsPagination {
+ margin-top: 4px;
+ width: 100%;
+}
+
+.typeScriptController {
+ font-size: 16px;
+ font-weight: 600;
+ cursor: pointer;
+ color: var(--primary-color);
+ display: flex;
+ align-items: center;
+
+ > img {
+ width: 12px;
+ height: 12px;
+ margin: 2px 0 0 5px;
+ }
+
+ @media (max-width: $mobileBreakPoint) {
+ font-size: 14px;
+
+ > img {
+ margin: 0 0 0 5px;
+ }
+ }
+}
+
+.uDTTransactionsPanel {
+ width: 100%;
+}