Skip to content

Commit

Permalink
fixup! fix: mf-6332 handle unsend redpacket
Browse files Browse the repository at this point in the history
  • Loading branch information
swkatmask committed Oct 16, 2024
1 parent 35c2b88 commit 2c7782b
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ interface TokenInfo {
decimals: number
amount?: string
}
const RedPacketStatus = FireflyRedPacketAPI.RedPacketStatus
interface Props {
rpid: string
account: string
Expand All @@ -55,7 +56,10 @@ interface Props {
redpacketMsg?: string
chainId: ChainId
totalAmount?: string
/** timestamp in seconds */
createdAt?: number
canResend: boolean
onResend?(): void
}

export const RedPacketActionButton = memo(function RedPacketActionButton(props: Props) {
Expand All @@ -71,6 +75,8 @@ export const RedPacketActionButton = memo(function RedPacketActionButton(props:
chainId,
totalAmount,
createdAt,
canResend,
onResend,
} = props
const { classes } = useStyles()
const isSmall = useMediaQuery((theme: Theme) => theme.breakpoints.down('sm'))
Expand All @@ -79,12 +85,12 @@ export const RedPacketActionButton = memo(function RedPacketActionButton(props:

const [{ loading: isRefunding }, refunded, refundCallback] = useRefundCallback(4, account, rpid, chainId)
const statusToTransMap = {
[FireflyRedPacketAPI.RedPacketStatus.Send]: t.send(),
[FireflyRedPacketAPI.RedPacketStatus.Expired]: t.expired(),
[FireflyRedPacketAPI.RedPacketStatus.Empty]: t.empty(),
[FireflyRedPacketAPI.RedPacketStatus.Refund]: t.expired(),
[FireflyRedPacketAPI.RedPacketStatus.View]: t.view(),
[FireflyRedPacketAPI.RedPacketStatus.Refunding]: t.refund(),
[RedPacketStatus.Send]: t.send(),
[RedPacketStatus.Expired]: t.expired(),
[RedPacketStatus.Empty]: t.empty(),
[RedPacketStatus.Refund]: t.expired(),
[RedPacketStatus.View]: canResend ? t.share() : t.view(),
[RedPacketStatus.Refunding]: t.refund(),
}

const [{ loading: isSharing }, shareCallback] = useAsyncFn(async () => {
Expand Down Expand Up @@ -123,12 +129,14 @@ export const RedPacketActionButton = memo(function RedPacketActionButton(props:
)
}, [])

const redpacketStatus = refunded ? FireflyRedPacketAPI.RedPacketStatus.Refund : _redpacketStatus
const redpacketStatus = refunded ? RedPacketStatus.Refund : _redpacketStatus

const handleClick = useCallback(async () => {
if (redpacketStatus === FireflyRedPacketAPI.RedPacketStatus.Send) await shareCallback()
if (redpacketStatus === FireflyRedPacketAPI.RedPacketStatus.Refunding) await refundCallback()
}, [redpacketStatus, shareCallback, refundCallback])
if (canResend) onResend?.()
else if (redpacketStatus === RedPacketStatus.Send || redpacketStatus === RedPacketStatus.View)
await shareCallback()
else if (redpacketStatus === RedPacketStatus.Refunding) await refundCallback()
}, [redpacketStatus, shareCallback, refundCallback, canResend, onResend])

return (
<ActionButton
Expand All @@ -139,9 +147,9 @@ export const RedPacketActionButton = memo(function RedPacketActionButton(props:
}}
className={classes.actionButton}
disabled={
redpacketStatus === FireflyRedPacketAPI.RedPacketStatus.Empty ||
redpacketStatus === FireflyRedPacketAPI.RedPacketStatus.Expired ||
redpacketStatus === FireflyRedPacketAPI.RedPacketStatus.Refund
redpacketStatus === RedPacketStatus.Empty ||
redpacketStatus === RedPacketStatus.Expired ||
redpacketStatus === RedPacketStatus.Refund
}
size="large">
<span>{statusToTransMap[redpacketStatus]}</span>
Expand Down
56 changes: 28 additions & 28 deletions packages/plugins/RedPacket/src/SiteAdaptor/RedPacketDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,46 @@
import { useCallback, useContext, useMemo, useState, Suspense } from 'react'
import * as web3_utils from /* webpackDefer: true */ 'web3-utils'
import { DialogContent, Tab, useTheme } from '@mui/material'
import { TabContext, TabPanel } from '@mui/lab'
import { CrossIsolationMessages, NetworkPluginID, PluginID } from '@masknet/shared-base'
import { useChainContext, useGasPrice } from '@masknet/web3-hooks-base'
import { Icons } from '@masknet/icons'
import {
useCurrentVisitingIdentity,
useLastRecognizedIdentity,
useSiteThemeMode,
} from '@masknet/plugin-infra/content-script'
import {
ApplicationBoardModal,
InjectedDialog,
LoadingStatus,
NetworkTab,
useCurrentLinkedPersona,
LoadingStatus,
} from '@masknet/shared'
import { ChainId, type GasConfig, GasEditor } from '@masknet/web3-shared-evm'
import { type FireflyRedPacketAPI, type RedPacketJSONPayload } from '@masknet/web3-providers/types'
import { CrossIsolationMessages, NetworkPluginID, PluginID } from '@masknet/shared-base'
import { queryClient } from '@masknet/shared-base-ui'
import { makeStyles, MaskTabList, useTabs } from '@masknet/theme'
import {
useCurrentVisitingIdentity,
useLastRecognizedIdentity,
useSiteThemeMode,
} from '@masknet/plugin-infra/content-script'
import { Icons } from '@masknet/icons'
import { useChainContext, useGasPrice } from '@masknet/web3-hooks-base'
import { EVMWeb3 } from '@masknet/web3-providers'
import { type FireflyRedPacketAPI, type RedPacketJSONPayload } from '@masknet/web3-providers/types'
import { ChainId, type GasConfig, GasEditor } from '@masknet/web3-shared-evm'
import { Telemetry } from '@masknet/web3-telemetry'
import { EventID, EventType } from '@masknet/web3-telemetry/types'
import { EVMWeb3 } from '@masknet/web3-providers'
import { useRedPacketTrans } from '../locales/index.js'
import { reduceUselessPayloadInfo } from './utils/reduceUselessPayloadInfo.js'
import { TabContext, TabPanel } from '@mui/lab'
import { DialogContent, Tab, useTheme } from '@mui/material'
import { Suspense, useCallback, useContext, useMemo, useState } from 'react'
import * as web3_utils from /* webpackDefer: true */ 'web3-utils'
import { base } from '../base.js'
import { RedPacketMetaKey } from '../constants.js'
import { useRedPacketTrans } from '../locales/index.js'
import type { FireflyContext, FireflyRedpacketSettings } from '../types.js'
import { ClaimRequirementsDialog } from './ClaimRequirementsDialog.js'
import { ClaimRequirementsRuleDialog } from './ClaimRequirementsRuleDialog.js'
import { FireflyRedpacketConfirmDialog } from './FireflyRedpacketConfirmDialog.js'
import { FireflyRedPacketHistoryDetails } from './FireflyRedPacketHistoryDetails.js'
import { FireflyRedPacketPast } from './FireflyRedPacketPast.js'
import type { RedPacketSettings } from './hooks/useCreateCallback.js'
import { openComposition } from './openComposition.js'
import { RedPacketConfirmDialog } from './RedPacketConfirmDialog.js'
import { RedPacketERC20Form } from './RedPacketERC20Form.js'
import { RedPacketERC721Form } from './RedPacketERC721Form.js'
import { openComposition } from './openComposition.js'
import { FireflyRedPacketPast } from './FireflyRedPacketPast.js'
import { FireflyRedPacketHistoryDetails } from './FireflyRedPacketHistoryDetails.js'
import { ClaimRequirementsDialog } from './ClaimRequirementsDialog.js'
import { ClaimRequirementsRuleDialog } from './ClaimRequirementsRuleDialog.js'
import type { FireflyContext, FireflyRedpacketSettings } from '../types.js'
import { FireflyRedpacketConfirmDialog } from './FireflyRedpacketConfirmDialog.js'
import { RedPacketPast } from './RedPacketPast.js'
import { CompositionTypeContext } from './RedPacketInjection.js'
import { base } from '../base.js'
import { queryClient } from '@masknet/shared-base-ui'
import { RedPacketPast } from './RedPacketPast.js'
import { reduceUselessPayloadInfo } from './utils/reduceUselessPayloadInfo.js'

const useStyles = makeStyles<{ scrollY: boolean; isDim: boolean }>()((theme, { isDim, scrollY }) => {
// it's hard to set dynamic color, since the background color of the button is blended transparent
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { TokenIcon } from '@masknet/shared'
import { NetworkPluginID } from '@masknet/shared-base'
import { useEverSeen } from '@masknet/shared-base-ui'
import { makeStyles } from '@masknet/theme'
import { useChainContext, useFungibleToken, useNetworkDescriptor } from '@masknet/web3-hooks-base'
import { type FireflyRedPacketAPI, type RedPacketJSONPayload } from '@masknet/web3-providers/types'
import { FireflyRedPacketAPI, type RedPacketJSONPayload } from '@masknet/web3-providers/types'
import { formatBalance } from '@masknet/web3-shared-base'
import { ChainId, NETWORK_DESCRIPTORS } from '@masknet/web3-shared-evm'
import { ChainId, NETWORK_DESCRIPTORS, useRedPacketConstants } from '@masknet/web3-shared-evm'
import { Box, ListItem, Typography } from '@mui/material'
import { useQuery } from '@tanstack/react-query'
import { format, fromUnixTime } from 'date-fns'
import { memo } from 'react'
import { RedPacketTrans, useRedPacketTrans } from '../locales/index.js'
import { RedPacketRPC } from '../messages.js'
import { RedPacketActionButton } from './RedPacketActionButton.js'
import { useRedpacketToken } from './hooks/useRedpacketToken.js'
import { useEverSeen } from '@masknet/shared-base-ui'
import { useCreateRedPacketReceipt } from './hooks/useCreateRedPacketReceipt.js'

const DEFAULT_BACKGROUND = NETWORK_DESCRIPTORS.find((x) => x.chainId === ChainId.Mainnet)!.backgroundGradient!
const useStyles = makeStyles<{ listItemBackground?: string; listItemBackgroundIcon?: string }>()((
Expand Down Expand Up @@ -145,7 +148,7 @@ interface RedPacketInHistoryListProps {
}

export const RedPacketInHistoryList = memo(function RedPacketInHistoryList(props: RedPacketInHistoryListProps) {
const { history } = props
const { history, onSelect } = props
const {
rp_msg,
create_time,
Expand Down Expand Up @@ -178,6 +181,14 @@ export const RedPacketInHistoryList = memo(function RedPacketInHistoryList(props
const { data: tokenAddress } = useRedpacketToken(chainId, history.trans_hash, seen && token_symbol === 'MATIC')
const { data: token } = useFungibleToken(NetworkPluginID.PLUGIN_EVM, tokenAddress, undefined, { chainId })
const tokenSymbol = token?.symbol ?? token_symbol
const contractAddress = useRedPacketConstants(chainId).HAPPY_RED_PACKET_ADDRESS_V4
const { data: redpacketRecord } = useQuery({
queryKey: ['redpacket', 'by-tx-hash', history.trans_hash],
queryFn: async () => RedPacketRPC.getRedPacketRecord(history.trans_hash),
})
const { data: createSuccessResult } = useCreateRedPacketReceipt(history.trans_hash, chainId)
const canResend =
redpacket_status === FireflyRedPacketAPI.RedPacketStatus.View && !!redpacketRecord && !!createSuccessResult

return (
<ListItem className={classes.root}>
Expand Down Expand Up @@ -225,6 +236,26 @@ export const RedPacketInHistoryList = memo(function RedPacketInHistoryList(props
chainId={chainId}
totalAmount={total_amounts}
createdAt={create_time}
canResend={canResend}
onResend={() => {
if (!canResend) return
onSelect({
txid: history.trans_hash,
contract_address: contractAddress!,
rpid: history.redpacket_id,
shares: +history.total_numbers,
is_random: createSuccessResult.ifrandom,
creation_time: history.create_time,
contract_version: 4,
sender: {
address: account,
name: createSuccessResult.name,
message: createSuccessResult.message,
},
total: history.total_amounts,
duration: +createSuccessResult.duration,
})
}}
/>
: null}
</section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,28 +79,31 @@ export function useCreateFTRedpacketCallback(

// the events log is not available
if (!events?.CreationSuccess?.returnValues.id) return

payload.current.sender = {
address: account,
name: currentAccount || settings.name,
message: settings.message,
}
payload.current.is_random = settings.isRandom
payload.current.shares = settings.shares
payload.current.password = privateKey
payload.current.rpid = CreationSuccess.id
payload.current.total = CreationSuccess.total
payload.current.duration = settings.duration
payload.current.creation_time = Number.parseInt(CreationSuccess.creation_time, 10) * 1000
payload.current.token = settings.token
const redpacketPayload = {
sender: {
address: account,
name: currentAccount || settings.name,
message: settings.message,
},
is_random: settings.isRandom,
shares: settings.shares,
password: privateKey,
rpid: CreationSuccess.id,
total: CreationSuccess.total,
duration: settings.duration,
creation_time: Number.parseInt(CreationSuccess.creation_time, 10) * 1000,
token: settings.token,
} as const
Object.assign(payload.current, redpacketPayload)

const record: RedPacketRecord = {
chainId,
id: receipt.transactionHash,
from: '',
password: privateKey,
contract_version,
}
RedPacketRPC.addRedPacket(record, chainId)
RedPacketRPC.addRedPacket(record)

// output the redpacket as JSON payload
onCreated?.(payload.current)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { NetworkPluginID } from '@masknet/shared-base'
import REDPACKET_ABI from '@masknet/web3-contracts/abis/HappyRedPacketV4.json'
import { useWeb3Connection } from '@masknet/web3-hooks-base'
import { isSameAddress } from '@masknet/web3-shared-base'
import { type ChainId, decodeEvents, useRedPacketConstants } from '@masknet/web3-shared-evm'
import { useQuery } from '@tanstack/react-query'
import type { AbiItem } from 'web3-utils'

type CreationSuccessEventParams = {
id: string

Check failure on line 10 in packages/plugins/RedPacket/src/SiteAdaptor/hooks/useCreateRedPacketReceipt.ts

View workflow job for this annotation

GitHub Actions / type-check

Duplicate identifier 'id'.
/** seconds in string */
creation_time: string
/** creator wallet address */
creator: string
/** seconds in string */
duration: '86400'
id: HexString

Check failure on line 17 in packages/plugins/RedPacket/src/SiteAdaptor/hooks/useCreateRedPacketReceipt.ts

View workflow job for this annotation

GitHub Actions / type-check

Duplicate identifier 'id'.

Check failure on line 17 in packages/plugins/RedPacket/src/SiteAdaptor/hooks/useCreateRedPacketReceipt.ts

View workflow job for this annotation

GitHub Actions / type-check

Subsequent property declarations must have the same type. Property 'id' must be of type 'string', but here has type '`0x${string}`'.
ifrandom: boolean
message: string
/** creator's name */
name: string
/** account in string*/
number: string
token_address: HexString
/** account in string*/
total: string
}
export function useCreateRedPacketReceipt(txHash: string, chainId: ChainId) {
const { HAPPY_RED_PACKET_ADDRESS_V4 } = useRedPacketConstants(chainId)
const Web3 = useWeb3Connection(NetworkPluginID.PLUGIN_EVM)

return useQuery({
queryKey: ['redpacket', 'creation-success-params', chainId, txHash],
queryFn: async () => {
if (!txHash || !Web3) return null

const receipt = await Web3.getTransactionReceipt(txHash, { chainId })
if (!receipt) return null

const log = receipt.logs.find((log) => isSameAddress(log.address, HAPPY_RED_PACKET_ADDRESS_V4))
if (!log) return null

const eventParams = decodeEvents(REDPACKET_ABI as AbiItem[], [log]) as unknown as {
CreationSuccess: {
returnValues: CreationSuccessEventParams
}
}

const { returnValues } = eventParams.CreationSuccess
console.log({ eventParams, returnValues, txHash })

return returnValues
},
})
}
3 changes: 1 addition & 2 deletions packages/plugins/RedPacket/src/Worker/services.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { ChainId } from '@masknet/web3-shared-evm'
import {
type RedPacketRecord,
type RedPacketJSONPayloadFromChain,
Expand All @@ -9,7 +8,7 @@ import * as nftDb from './databaseForNft.js'

export { addRedPacketNft, getRedPacketNft, updateRedPacketNft } from './databaseForNft.js'

export async function addRedPacket(record: RedPacketRecord, chainId: ChainId) {
export async function addRedPacket(record: RedPacketRecord) {
await database.addRedPacket(record)
}

Expand Down
2 changes: 2 additions & 0 deletions packages/web3-providers/src/RedPacket/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import type { BigNumber } from 'bignumber.js'

// #region erc20 red packet
export interface RedPacketRecord {
/** since 2.27.1 */
chainId: number
id: string
/** From twitter/facebook url */
from: string
Expand Down
4 changes: 2 additions & 2 deletions packages/web3-shared/evm/src/libs/EtherscanURL.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { ChainId } from '../types/index.js'
import { getEtherscanConstants } from '../constants/index.js'
import { getEtherscanConstant } from '../constants/index.js'

export class EtherscanURL {
static from(chainId: ChainId) {
const { ETHERSCAN_URL = '' } = getEtherscanConstants(chainId)
const ETHERSCAN_URL = getEtherscanConstant(chainId, 'ETHERSCAN_URL') || ''
if (process.env.NODE_ENV === 'development' && !EtherscanURL) {
console.error('Etherscan URL for %s is empty', chainId)
}
Expand Down

0 comments on commit 2c7782b

Please sign in to comment.