diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketHistoryList.tsx b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketHistoryList.tsx index bb388d57f596..842dfe8572c3 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketHistoryList.tsx +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketHistoryList.tsx @@ -59,8 +59,8 @@ export function RedPacketHistoryList(props: RedPacketHistoryListProps) { ) : ( - {histories.map((history) => ( -
+ {histories.map((history, i) => ( +
))} diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketInHistoryList.tsx b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketInHistoryList.tsx index aa9815bc87e3..3d91bb900c81 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketInHistoryList.tsx +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketInHistoryList.tsx @@ -1,11 +1,14 @@ import { MouseEvent, useCallback, useState } from 'react' +import { useAsync } from 'react-use' +import { Interface } from '@ethersproject/abi' import BigNumber from 'bignumber.js' import classNames from 'classnames' import { Box, ListItem, Typography, Popper, useMediaQuery, Theme } from '@mui/material' import { makeStyles } from '@masknet/theme' import { omit, pick } from 'lodash-unified' import { TokenIcon } from '@masknet/shared' -import { ChainId, SchemaType, useTokenConstants } from '@masknet/web3-shared-evm' +import { ChainId, SchemaType, useRedPacketConstants } from '@masknet/web3-shared-evm' +import REDPACKET_ABI from '@masknet/web3-contracts/abis/HappyRedPacketV4.json' import intervalToDuration from 'date-fns/intervalToDuration' import nextDay from 'date-fns/nextDay' import ActionButton from '../../../extension/options-page/DashboardComponents/ActionButton' @@ -16,8 +19,10 @@ import { StyledLinearProgress } from '../../ITO/SNSAdaptor/StyledLinearProgress' import { RedPacketJSONPayload, RedPacketJSONPayloadFromChain, RedPacketStatus } from '../types' import { useAvailabilityComputed } from './hooks/useAvailabilityComputed' import { useRefundCallback } from './hooks/useRefundCallback' -import { useAccount, useFungibleToken } from '@masknet/plugin-infra/web3' -import { formatBalance, FungibleToken, NetworkPluginID } from '@masknet/web3-shared-base' +import { useAccount, useChainId, useFungibleToken, useWeb3Connection } from '@masknet/plugin-infra/web3' +import { formatBalance, FungibleToken, NetworkPluginID, isSameAddress } from '@masknet/web3-shared-base' + +const interFace = new Interface(REDPACKET_ABI) const useStyles = makeStyles()((theme) => { const smallQuery = `@media (max-width: ${theme.breakpoints.values.sm}px)` @@ -180,16 +185,50 @@ export function RedPacketInHistoryList(props: RedPacketInHistoryListProps) { const t = useI18N() const { classes } = useStyles() const account = useAccount(NetworkPluginID.PLUGIN_EVM) + const chainId = useChainId(NetworkPluginID.PLUGIN_EVM) + const connection = useWeb3Connection(NetworkPluginID.PLUGIN_EVM) + const { HAPPY_RED_PACKET_ADDRESS_V4 } = useRedPacketConstants(chainId) const isSmall = useMediaQuery((theme: Theme) => theme.breakpoints.down('sm')) + + const { value: receipt } = useAsync(async () => { + const result = await connection.getTransactionReceipt(history.txid) + if (!result) return null + + const log = result.logs.find((log) => isSameAddress(log.address, HAPPY_RED_PACKET_ADDRESS_V4)) + if (!log) return null + + type CreationSuccessEventParams = { + id: string + creation_time: BigNumber + } + const eventParams = interFace.decodeEventLog( + 'CreationSuccess', + log.data, + log.topics, + ) as unknown as CreationSuccessEventParams + + return { + rpid: eventParams.id, + creation_time: eventParams.creation_time.toNumber() * 1000, + } + }, [connection, history, HAPPY_RED_PACKET_ADDRESS_V4]) + + const rpid = receipt?.rpid ?? '' + const creation_time = receipt?.creation_time ?? 0 + const { + value: availability, computed: { canRefund, canSend, listOfStatus, isPasswordValid }, retry: revalidateAvailability, - } = useAvailabilityComputed(account, history) - const { NATIVE_TOKEN_ADDRESS } = useTokenConstants() + } = useAvailabilityComputed(account, { ...history, rpid, creation_time }) + + const claimerNumber = availability ? Number(availability.claimed) : 0 + const total_remaining = availability?.balance + const [{ loading: isRefunding }, refunded, refundCallback] = useRefundCallback( history.contract_version, account, - history.rpid, + rpid, ) const tokenAddress = (history as RedPacketJSONPayload).token?.address ?? (history as RedPacketJSONPayloadFromChain).token_address @@ -216,13 +255,11 @@ export function RedPacketInHistoryList(props: RedPacketInHistoryListProps) { // #region refund time const refundDuration = - canSend && !isPasswordValid - ? intervalToDuration({ start: Date.now(), end: nextDay(history.creation_time, 1) }) - : null + canSend && !isPasswordValid ? intervalToDuration({ start: Date.now(), end: nextDay(creation_time, 1) }) : null const formatRefundDuration = `${refundDuration?.hours}h ${refundDuration?.minutes}m` // #endregion - return ( + return !rpid ? null : ( {t.history_duration({ - startTime: dateTimeFormat(new Date(history.creation_time)), - endTime: dateTimeFormat(new Date(history.creation_time + history.duration), false), + startTime: dateTimeFormat(new Date(creation_time)), + endTime: dateTimeFormat(new Date(creation_time + history.duration), false), })} @@ -301,7 +338,7 @@ export function RedPacketInHistoryList(props: RedPacketInHistoryListProps) {
@@ -310,7 +347,7 @@ export function RedPacketInHistoryList(props: RedPacketInHistoryListProps) { strong: , }} values={{ - claimedShares: String(history.claimers?.length ?? 0), + claimedShares: String(claimerNumber), shares: String(history.shares), }} /> @@ -324,7 +361,7 @@ export function RedPacketInHistoryList(props: RedPacketInHistoryListProps) { values={{ amount: formatBalance(history.total, historyToken?.decimals, 6), claimedAmount: formatBalance( - new BigNumber(history.total).minus(history?.total_remaining ?? 0), + new BigNumber(history.total).minus(total_remaining ?? 0), historyToken?.decimals, 6, ), diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/utils/chain.ts b/packages/mask/src/plugins/RedPacket/SNSAdaptor/utils/chain.ts index 650abaeb9175..1c4567f445ba 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/utils/chain.ts +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/utils/chain.ts @@ -6,7 +6,6 @@ import { ChainId, chainResolver, getExplorerConstants, getRedPacketConstants } f import { Interface } from '@ethersproject/abi' import type { RedPacketJSONPayloadFromChain } from '../../types' import REDPACKET_ABI from '@masknet/web3-contracts/abis/HappyRedPacketV4.json' -import { checkAvailability } from './checkAvailability' import type { Web3Helper } from '@masknet/plugin-infra/src/web3-helpers' const interFace = new Interface(REDPACKET_ABI) @@ -87,11 +86,9 @@ export async function getRedPacketHistory( name: decodedInputParam._name, message: decodedInputParam._message, }, - // #region Retrieve at step 3 + // #region Retrieve at RedPacketInHistoryList component rpid: '', creation_time: 0, - // #endregion - // #region Retrieve at step 4 total_remaining: '', claimers: [], // #endregion @@ -105,52 +102,5 @@ export async function getRedPacketHistory( } }) // #endregion - - // #region - // 3. Decode CreationSuccess event log to retrieve `rpid` and `creation_time` for payload - type CreationSuccessEventParams = { - id: string - creation_time: BigNumber - } - - const eventLogResponse = await Promise.allSettled( - payloadList.map(async (payload) => { - const result = await connection.getTransactionReceipt(payload.txid) - if (!result) return null - - const log = result.logs.find((log) => isSameAddress(log.address, HAPPY_RED_PACKET_ADDRESS_V4)) - if (!log) return null - const eventParams = interFace.decodeEventLog( - 'CreationSuccess', - log.data, - log.topics, - ) as unknown as CreationSuccessEventParams - - payload.rpid = eventParams.id - payload.creation_time = eventParams.creation_time.toNumber() * 1000 - - // 4. retrieve `claimers` and `total_remaining` - // const r = await redPacketContract.methods.check_availability(payload.rpid).call({ - // from: payload.sender.address, - // }) - - const data = await checkAvailability( - payload.rpid, - payload.sender.address, - payload.contract_address, - chainId, - connection, - ) - - payload.claimers = Array.from({ length: data.claimed }).map(() => ({ address: '', name: '' })) - payload.total_remaining = data.balance - - return payload - }), - ) - // #endregion - - return eventLogResponse - .map((v) => (v.status === 'fulfilled' && v.value ? v.value : null)) - .filter((v) => Boolean(v)) as RedPacketJSONPayloadFromChain[] + return payloadList }