Skip to content

Commit

Permalink
Feature/l1 l2 (#348)
Browse files Browse the repository at this point in the history
Co-authored-by: Chen Yu <[email protected]>
  • Loading branch information
Daryl-L and Keith-CY authored Jun 19, 2024
1 parent 398154e commit c65f7c1
Show file tree
Hide file tree
Showing 17 changed files with 128 additions and 82 deletions.
2 changes: 1 addition & 1 deletion src/components/LiteTransactionList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const LiteTransactionList: React.FC<{
>
{item.transactionHash}
</AddressText>
{item.isRgbTransaction && <RGBPP transaction={item} />}
{item.isRgbTransaction && item.rgbTransferStep && <RGBPP transaction={item} />}
</div>
</td>
{isPendingListActive ? null : (
Expand Down
24 changes: 3 additions & 21 deletions src/components/RGBPP/index.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,15 @@
import { useMemo, useState } from 'react'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Transaction } from '../../models/Transaction'
import SimpleModal from '../Modal'
import SimpleButton from '../SimpleButton'
import TransactionRGBPPDigestModal from '../TransactionItem/TransactionRGBPPDigestModal'
import styles from './styles.module.scss'
import { TransactionLeapDirection } from './types'

const RGBPP = ({ transaction }: { transaction: Transaction }) => {
const [showModal, setShowModal] = useState(false)
const { t } = useTranslation()

const direction = useMemo(() => {
// FIXME: should be from API because inputs/outputs are paginated
const inputCellCount = transaction.displayInputs.filter(c => c.rgbInfo).length
const outputCellCount = transaction.displayOutputs.filter(c => c.rgbInfo).length
if (inputCellCount === outputCellCount) {
return TransactionLeapDirection.NONE
}
if (inputCellCount > outputCellCount) {
return TransactionLeapDirection.OUT
}
return TransactionLeapDirection.IN
}, [transaction])

return (
<div>
<SimpleButton
Expand All @@ -32,15 +18,11 @@ const RGBPP = ({ transaction }: { transaction: Transaction }) => {
}}
>
<div className={styles.rgbpp}>
<span>{t('transaction.view_rgbpp_digest')}</span>
<span>RGB++: {t(`rgbpp.transaction.step.${transaction.rgbTransferStep}`)}</span>
</div>
</SimpleButton>
<SimpleModal isShow={showModal} setIsShow={setShowModal}>
<TransactionRGBPPDigestModal
onClickClose={() => setShowModal(false)}
hash={transaction.transactionHash}
leapDirection={direction}
/>
<TransactionRGBPPDigestModal onClickClose={() => setShowModal(false)} hash={transaction.transactionHash} />
</SimpleModal>
</div>
)
Expand Down
1 change: 1 addition & 0 deletions src/components/RGBPP/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export enum TransactionLeapDirection {
NONE = 'none',
IN = 'in',
OUT = 'out',
WITH_IN_BTC = 'with_in_btc',
}
Original file line number Diff line number Diff line change
@@ -1,39 +1,36 @@
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { Tooltip } from 'antd'
import { useQuery } from '@tanstack/react-query'
import BigNumber from 'bignumber.js'
import { ReactComponent as CopyIcon } from '../../../assets/copy_icon.svg'
import { ReactComponent as RedirectIcon } from '../../../assets/redirect-icon.svg'
import { TransactionRGBPPDigestTransfer } from './TransactionRGBPPDigestTransfer'
import { useSetToast } from '../../Toast'
import { explorerService, LiteTransfer } from '../../../services/ExplorerService'
import SmallLoading from '../../Loading/SmallLoading'
import { TransactionLeapDirection } from '../../RGBPP/types'
import { LiteTransfer, RGBDigest } from '../../../services/ExplorerService'
import SimpleButton from '../../SimpleButton'
import EllipsisMiddle from '../../EllipsisMiddle'
import styles from './styles.module.scss'
import AddressText from '../../AddressText'
import { useIsMobile } from '../../../hooks'
import { Link } from '../../Link'
import config from '../../../config'
import SmallLoading from '../../Loading/SmallLoading'

export const TransactionRGBPPDigestContent = ({
leapDirection,
hash,
digest,
isFetched,
}: {
leapDirection: TransactionLeapDirection
hash: string
digest?: RGBDigest
isFetched: boolean
}) => {
const { t } = useTranslation()
const setToast = useSetToast()
const isMobile = useIsMobile()

const { data, isFetched } = useQuery(['rgb-digest', hash], () => explorerService.api.fetchRGBDigest(hash))

const transfers = useMemo(() => {
const m = new Map<string, LiteTransfer.Transfer[]>()
data?.data.transfers?.forEach(tf => {
digest?.transfers.forEach(tf => {
const list = m.get(tf.address) || []
tf.transfers.forEach(i => {
let asset: LiteTransfer.Transfer | undefined
Expand Down Expand Up @@ -84,7 +81,7 @@ export const TransactionRGBPPDigestContent = ({
m.set(tf.address, list)
})
return m
}, [data?.data.transfers])
}, [digest?.transfers])

if (!isFetched) {
return (
Expand All @@ -93,17 +90,17 @@ export const TransactionRGBPPDigestContent = ({
</div>
)
}
if (!data) {
if (!digest) {
return <div className={styles.noRecords}>{t('transaction.no_records')}</div>
}

return (
<div className={styles.content}>
{data.data.commitment ? (
{digest.commitment ? (
<div className={styles.transactionInfo}>
<div className={styles.txid}>
<span>{t('address.seal_tx_on_bitcoin')}</span>
{data.data.txid && (
{digest.txid && (
<>
<AddressText
ellipsisMiddle={!isMobile}
Expand All @@ -113,32 +110,27 @@ export const TransactionRGBPPDigestContent = ({
className={styles.address}
style={{ overflow: 'hidden' }}
>
{data.data.txid}
{digest.txid}
</AddressText>
<Link to={`${config.BITCOIN_EXPLORER}/tx/${data.data.txid}`} className={styles.action}>
<Link to={`${config.BITCOIN_EXPLORER}/tx/${digest.txid}`} className={styles.action}>
<RedirectIcon />
</Link>
</>
)}
</div>
<div className={styles.btcConfirmationsAndDirection}>
{typeof data.data.confirmations === 'number' && (
<span className={styles.blockConfirm}>({data.data.confirmations} Confirmations on Bitcoin)</span>
{typeof digest.confirmations === 'number' && (
<span className={styles.blockConfirm}>({digest.confirmations} Confirmations on Bitcoin)</span>
)}
{leapDirection !== TransactionLeapDirection.NONE ? (
<Tooltip placement="top" title={t(`address.leap_${leapDirection}_tip`)}>
<span className={styles.leap}>{t(`address.leap_${leapDirection}`)}</span>
</Tooltip>
) : null}
</div>
<div className={styles.commitment}>
<span>Commitment:</span>
<div style={{ width: '64ch', minWidth: '20ch' }}>
<EllipsisMiddle text={data.data.commitment} className={styles.commitmentText} />
<EllipsisMiddle text={digest.commitment} className={styles.commitmentText} />
<SimpleButton
className={styles.action}
onClick={() => {
navigator.clipboard.writeText(data.data.commitment)
navigator.clipboard.writeText(digest.commitment)
setToast({ message: t('common.copied') })
}}
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,49 @@
import { useTranslation } from 'react-i18next'
import { useQuery } from '@tanstack/react-query'
import { useMemo } from 'react'
import styles from './styles.module.scss'
import CloseIcon from '../../../assets/modal_close.png'
import { TransactionRGBPPDigestContent } from './TransactionRGBPPDigestContent'
import { explorerService } from '../../../services/ExplorerService'
import { TransactionLeapDirection } from '../../RGBPP/types'

const TransactionRGBPPDigestModal = ({
hash,
leapDirection,
onClickClose,
}: {
onClickClose: Function
hash: string
leapDirection: TransactionLeapDirection
}) => {
const TransactionRGBPPDigestModal = ({ hash, onClickClose }: { onClickClose: Function; hash: string }) => {
const { t } = useTranslation()

return (
<div className={styles.container}>
<div className={styles.header}>
<span className={styles.left}>{t('address.transaction_rgbpp_digest')}</span>
<button onClick={() => onClickClose()} type="button" className={styles.buttonClose}>
<img src={CloseIcon} alt="close icon" className={styles.closeIcon} />
</button>
const { data, isFetched } = useQuery(['rgb-digest', hash], () => explorerService.api.fetchRGBDigest(hash))

const direction = useMemo(() => {
switch (data?.data.leapDirection) {
case 'in':
return TransactionLeapDirection.IN
case 'leapoutBTC':
return TransactionLeapDirection.OUT
case 'withinBTC':
return TransactionLeapDirection.WITH_IN_BTC
default:
return TransactionLeapDirection.NONE
}
}, [data])

if (isFetched && data?.data) {
return (
<div className={styles.container}>
<div className={styles.header}>
<div className={styles.left}>
<span>{t('address.transaction_rgbpp_digest')}</span>
{direction !== TransactionLeapDirection.NONE && (
<span className={styles.leap}>{t(`address.leap_${direction}`)}</span>
)}
</div>
<button onClick={() => onClickClose()} type="button" className={styles.buttonClose}>
<img src={CloseIcon} alt="close icon" className={styles.closeIcon} />
</button>
</div>
<TransactionRGBPPDigestContent hash={hash} digest={data?.data} isFetched={isFetched} />
</div>
<TransactionRGBPPDigestContent leapDirection={leapDirection} hash={hash} />
</div>
)
)
}
return null
}

export default TransactionRGBPPDigestModal
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@
.header {
display: flex;
justify-content: space-between;
margin-bottom: 10px;

.left {
display: flex;
gap: 8px;
align-items: center;
}

> span {
font-family: Roboto, sans-serif;
Expand Down Expand Up @@ -71,7 +78,9 @@

.txid,
.commitment {
max-width: 100%;
display: flex;
flex: 1 1;
flex-shrink: 1;
overflow: hidden;
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
Expand Down
2 changes: 1 addition & 1 deletion src/components/TransactionItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ const TransactionItem = ({
>
{transaction.transactionHash}
</AddressText>
{transaction.isRgbTransaction && <RGBPP transaction={transaction} />}
{transaction.isRgbTransaction && transaction.rgbTransferStep && <RGBPP transaction={transaction} />}
</div>
<div className={styles.right}>
<Time tx={isBlock ? undefined : transaction} />
Expand Down
7 changes: 6 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@
"tx_on_bitcoin": "Tx On Bitcoin",
"leap_in": "L1 → L2",
"leap_out": "L2 → L1",
"leap_with_in_btc": "L1 → L1",
"leap_in_tip": "This RGB++ transaction is marked as \"L1 → L2\", indicating that the number of cells with RGB++ lock in the output exceeds the number of cells with RGB++ lock in the input.",
"leap_out_tip": "This RGB++ transaction is marked as \"L2 → L1\", indicating that the number of cells with RGB++ lock in the input exceeds the number of cells with RGB++ lock in the output.",
"view_in_btc_explorer": "View in Bitcoin Explorer",
Expand Down Expand Up @@ -454,7 +455,11 @@
"btc_txid": "BTC TXID",
"cell": "Cell",
"cells": "Cells",
"view_on_bitcoin_explorer": "View on Bitcoin Explorer"
"view_on_bitcoin_explorer": "View on Bitcoin Explorer",
"step": {
"isomorphic": "Isomorphic",
"unlock": "Unlock"
}
},
"amount": "Amount"
},
Expand Down
7 changes: 6 additions & 1 deletion src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@
"tx_on_bitcoin": "Tx On Bitcoin",
"leap_in": "L1 → L2",
"leap_out": "L2 → L1",
"leap_with_in_btc": "L1 → L1",
"leap_in_tip": "本笔 RGB++ 交易被标记为\"L1 → L2\",即存在一般 CKB 资产转化为 RGB++ 资产。",
"leap_out_tip": "本笔 RGB++ 交易被标记为\"L2 → L1\",即存在 RGB++ 资产转化为一般 CKB 资产。",
"view_in_btc_explorer": "在 Bitcoin 浏览器查看",
Expand Down Expand Up @@ -454,7 +455,11 @@
"btc_txid": "BTC 交易",
"cell": "Cell",
"cells": "Cells",
"view_on_bitcoin_explorer": "在 Bitcoin 浏览器查看"
"view_on_bitcoin_explorer": "在 Bitcoin 浏览器查看",
"step": {
"isomorphic": "同构",
"unlock": "解锁"
}
},
"amount": "数量"
},
Expand Down
1 change: 1 addition & 0 deletions src/models/Transaction/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface Transaction {
displayOutputs: Cell[]
liveCellChanges: string
capacityInvolved: string
rgbTransferStep: string | null
txStatus: string
detailedMessage: string
bytes: number
Expand Down
2 changes: 1 addition & 1 deletion src/pages/RGBPP/TransactionList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const RGBPPTransactionList = () => {
leapDirection = TransactionLeapDirection.IN
}

if (tx.leapDirection === 'out') {
if (tx.leapDirection === '') {
leapDirection = TransactionLeapDirection.OUT
}

Expand Down
31 changes: 20 additions & 11 deletions src/pages/Transaction/TransactionComp/RGBDigestComp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export const RGBDigestComp = ({ hash, txid }: { hash: string; txid?: string }) =
: undefined,
)

const { data: rgbDigest, isFetched: isDigestFetched } = useQuery(['rgb-digest', hash], () =>
explorerService.api.fetchRGBDigest(hash),
)

const { data: displayInputs } = useQuery(
['transaction_inputs', hash, 1, 10],
async () => {
Expand Down Expand Up @@ -64,27 +68,32 @@ export const RGBDigestComp = ({ hash, txid }: { hash: string; txid?: string }) =
}, [displayInputs, displayOutputs])

const direction = useMemo(() => {
// FIXME: should be from API because inputs/outputs are paginated
const inputCellCount = displayInputs.data.filter(c => c.rgbInfo).length
const outputCellCount = displayOutputs.data.filter(c => c.rgbInfo).length
if (inputCellCount === outputCellCount) {
return TransactionLeapDirection.NONE
switch (rgbDigest?.data.leapDirection) {
case 'in':
return TransactionLeapDirection.IN
case 'leapoutBTC':
return TransactionLeapDirection.OUT
case 'withinBTC':
return TransactionLeapDirection.WITH_IN_BTC
default:
return TransactionLeapDirection.NONE
}
if (inputCellCount > outputCellCount) {
return TransactionLeapDirection.OUT
}
return TransactionLeapDirection.IN
}, [displayInputs, displayOutputs])
}, [rgbDigest])

return (
<>
<Card className={styles.transactionHeader}>
<div className={styles.headerContent}>
<p>{t('transaction.rgb_digest')} </p>
{direction !== TransactionLeapDirection.NONE && (
<span className={styles.leap}>{t(`address.leap_${direction}`)}</span>
)}
</div>
</Card>
<Card className={styles.digestContent}>
<TransactionRGBPPDigestContent hash={hash} leapDirection={direction} />
{rgbDigest && (
<TransactionRGBPPDigestContent hash={hash} digest={rgbDigest?.data} isFetched={isDigestFetched} />
)}
<div className={styles.btcTxContent}>
{isBtcTxLoading ? <SmallLoading /> : null}
{btcTx?.vout.some(v => v.scriptPubKey.asm.includes('OP_RETURN')) ? (
Expand Down
Loading

0 comments on commit c65f7c1

Please sign in to comment.