diff --git a/packages/plugin-infra/src/site-adaptor/context.ts b/packages/plugin-infra/src/site-adaptor/context.ts index 47d08e1ca5c3..29f067f23529 100644 --- a/packages/plugin-infra/src/site-adaptor/context.ts +++ b/packages/plugin-infra/src/site-adaptor/context.ts @@ -10,7 +10,6 @@ export interface __SiteAdaptorContext__ { currentVisitingProfile: Subscription currentNextIDPlatform: NextIDPlatform | undefined currentPersonaIdentifier: Subscription - share: undefined | ((text: string, source?: string) => void) getPostURL: (identifier: PostIdentifier) => URL | null getProfileURL: (identifier: ProfileIdentifier) => URL | null getUserIdentity: ((useId: string) => Promise) | undefined @@ -19,7 +18,6 @@ export interface __SiteAdaptorContext__ { publishPost: ((mediaObjects: Array, options?: any) => Promise) | undefined getSearchedKeyword: (() => string) | undefined connectPersona: () => Promise - requestLogin?: (...args: any[]) => void } export let lastRecognizedProfile: __SiteAdaptorContext__['lastRecognizedProfile'] export let currentVisitingProfile: __SiteAdaptorContext__['currentVisitingProfile'] @@ -27,14 +25,12 @@ export let currentNextIDPlatform: NextIDPlatform | undefined export let currentPersonaIdentifier: __SiteAdaptorContext__['currentPersonaIdentifier'] export let getPostURL: __SiteAdaptorContext__['getPostURL'] export let getProfileURL: __SiteAdaptorContext__['getProfileURL'] -export let share: __SiteAdaptorContext__['share'] export let getUserIdentity: __SiteAdaptorContext__['getUserIdentity'] export let getPostIdFromNewPostToast: __SiteAdaptorContext__['getPostIdFromNewPostToast'] export let postMessage: __SiteAdaptorContext__['postMessage'] export let publishPost: __SiteAdaptorContext__['publishPost'] export let getSearchedKeyword: __SiteAdaptorContext__['getSearchedKeyword'] export let connectPersona: __SiteAdaptorContext__['connectPersona'] -export let requestLogin: __SiteAdaptorContext__['requestLogin'] export function __setSiteAdaptorContext__(value: __SiteAdaptorContext__) { ;({ lastRecognizedProfile, @@ -43,13 +39,11 @@ export function __setSiteAdaptorContext__(value: __SiteAdaptorContext__) { currentPersonaIdentifier, getPostURL, getProfileURL, - share, getUserIdentity, getPostIdFromNewPostToast, postMessage, publishPost, getSearchedKeyword, connectPersona, - requestLogin, } = value) } diff --git a/packages/plugins/RedPacket/package.json b/packages/plugins/RedPacket/package.json deleted file mode 100644 index c909bc285080..000000000000 --- a/packages/plugins/RedPacket/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "@masknet/plugin-redpacket", - "private": true, - "sideEffects": [ - "./src/register.ts" - ], - "type": "module", - "exports": { - ".": { - "mask-src": "./src/index.ts", - "default": "./dist/index.js" - }, - "./register": { - "mask-src": "./src/register.ts", - "default": "./dist/register.js" - } - }, - "dependencies": { - "@masknet/icons": "workspace:^", - "@masknet/plugin-infra": "workspace:^", - "@masknet/shared": "workspace:^", - "@masknet/shared-base": "workspace:^", - "@masknet/shared-base-ui": "workspace:^", - "@masknet/theme": "workspace:^", - "@masknet/typed-message-react": "workspace:^", - "@masknet/web3-contracts": "workspace:^", - "@masknet/web3-hooks-base": "workspace:^", - "@masknet/web3-hooks-evm": "workspace:^", - "@masknet/web3-providers": "workspace:^", - "@masknet/web3-shared-base": "workspace:^", - "@masknet/web3-shared-evm": "workspace:^", - "@tanstack/react-query": "^5.29.2", - "bignumber.js": "9.1.2", - "date-fns": "^2.30.0", - "react-use": "^17.5.1", - "urlcat": "^3.1.0", - "web3-core": "1.10.2", - "web3-utils": "1.10.2" - } -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/ClaimRequirementsDialog.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/ClaimRequirementsDialog.tsx deleted file mode 100644 index 6686ba7dc155..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/ClaimRequirementsDialog.tsx +++ /dev/null @@ -1,240 +0,0 @@ -import { Alert, SelectNonFungibleContractModal } from '@masknet/shared' -import { - Box, - Button, - Checkbox, - List, - ListItem, - ListItemIcon, - ListItemSecondaryAction, - ListItemText, - Typography, -} from '@mui/material' -import { useRedPacketTrans } from '../locales/index.js' -import { makeStyles } from '@masknet/theme' -import { useCallback, useState } from 'react' -import { Icons, type GeneratedIcon } from '@masknet/icons' -import { RequirementType, type FireflyRedpacketSettings } from '../types.js' -import { EMPTY_LIST, NetworkPluginID, PluginID } from '@masknet/shared-base' -import type { NonFungibleCollection } from '@masknet/web3-shared-base' -import { SchemaType, ChainId } from '@masknet/web3-shared-evm' -import { useChainContext } from '@masknet/web3-hooks-base' -import { Trans } from 'react-i18next' -import { getEnumAsArray } from '@masknet/kit' - -const useStyles = makeStyles()((theme) => ({ - container: { - padding: theme.spacing(2), - minHeight: 460, - }, - list: { - padding: theme.spacing(1.5, 0), - display: 'flex', - flexDirection: 'column', - rowGap: theme.spacing(1), - }, - icon: { - color: 'var(--color-light-main)', - minWidth: 20, - width: 20, - height: 20, - marginRight: theme.spacing(1), - }, - title: { - color: 'var(--color-light-main)', - fontSize: 16, - fontWeight: 700, - lineHeight: '22px', - margin: 0, - }, - checkbox: { - '& > .MuiBox-root': { - width: 20, - height: 20, - }, - }, - clear: { - color: '#8E96FF', - ':hover': { - background: 'transparent', - }, - }, - select: { - background: theme.palette.maskColor.input, - padding: theme.spacing(1.5), - borderRadius: 8, - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - color: theme.palette.maskColor.second, - cursor: 'pointer', - margin: theme.spacing(0, 1.5), - }, - selectText: { - color: theme.palette.maskColor.second, - fontSize: 14, - fontWeight: 300, - lineHeight: '22px', - }, - collection: { - display: 'flex', - alignItems: 'center', - columnGap: theme.spacing(1), - }, - collectionIcon: { - width: 24, - height: 24, - borderRadius: 500, - }, - collectionName: { - fontSize: 15, - color: 'var(--color-light-main)', - lineHeight: '20px', - fontWeight: 700, - }, - footer: { - bottom: 0, - position: 'sticky', - padding: theme.spacing(2), - boxSizing: 'border-box', - background: theme.palette.maskColor.secondaryBottom, - boxShadow: theme.palette.maskColor.bottomBg, - }, -})) - -interface ClaimRequirementsDialogProps { - onNext: (settings: FireflyRedpacketSettings) => void - origin?: RequirementType[] -} - -export const REQUIREMENT_ICON_MAP: Record = { - [RequirementType.Follow]: Icons.AddUser, - [RequirementType.Like]: Icons.Like, - [RequirementType.Repost]: Icons.Repost, - [RequirementType.Comment]: Icons.Comment, - [RequirementType.NFTHolder]: Icons.NFTHolder, -} - -export const REQUIREMENT_TITLE_MAP: Record = { - [RequirementType.Follow]: , - [RequirementType.Like]: , - [RequirementType.Repost]: , - [RequirementType.Comment]: , - [RequirementType.NFTHolder]: , -} - -export function ClaimRequirementsDialog(props: ClaimRequirementsDialogProps) { - const t = useRedPacketTrans() - const [selectedRules, setSelectedRules] = useState(props.origin ?? [RequirementType.Follow]) - const [selectedCollection, setSelectedCollection] = useState>() - const { classes } = useStyles() - const { chainId } = useChainContext() - - const hasNFTHolder = selectedRules.includes(RequirementType.NFTHolder) - - const handleClick = useCallback(() => { - SelectNonFungibleContractModal.open({ - pluginID: NetworkPluginID.PLUGIN_EVM, - schemaType: SchemaType.ERC721, - chainId, - onSubmit: (value: NonFungibleCollection) => setSelectedCollection(value), - collections: - chainId === ChainId.Base ? - [ - { - chainId: 8453, - name: 'Firefly (Base) Friends', - address: '0x577294402BA4679b6ba4A24B8e03Ce9d0C728e72', - slug: 'Firefly (Base) Friends', - symbol: '', - iconURL: - 'https://remote-image.decentralized-content.com/image?url=https%3A%2F%2Fipfs.decentralized-content.com%2Fipfs%2Fbafybeic5qugbigrxmb4vbyt4qk6cfyqlgmvembkwyrjj3go3lrt74aysci&w=1080&q=75', - }, - ] - : undefined, - }) - }, [chainId]) - - const disabled = selectedRules.includes(RequirementType.NFTHolder) && !selectedCollection - - return ( - <> - - {t.claim_requirements_tips()} - - {getEnumAsArray(RequirementType).map(({ value }) => { - const checked = selectedRules.includes(value) - const Icon = REQUIREMENT_ICON_MAP[value] - const title = REQUIREMENT_TITLE_MAP[value] - return ( - - - - - - - { - if (checked === false && value === RequirementType.NFTHolder) - setSelectedCollection(undefined) - setSelectedRules( - checked ? - [...selectedRules, value] - : selectedRules.filter((x) => x !== value), - ) - }} - /> - - - ) - })} - - {hasNFTHolder ? - - {selectedCollection ? - - {selectedCollection?.iconURL ? - - : null} - {selectedCollection?.name ? - - {selectedCollection.name} - - : null} - - : - {t.select_nft_collection_to_gate_access()} - - } - - - : null} - - - - - - - ) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/ClaimRequirementsRuleDialog.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/ClaimRequirementsRuleDialog.tsx deleted file mode 100644 index e0628097b0ea..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/ClaimRequirementsRuleDialog.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { makeStyles, usePortalShadowRoot } from '@masknet/theme' -import { Box, Dialog, DialogContent, DialogTitle, Typography } from '@mui/material' -import { memo } from 'react' -import { useRedPacketTrans } from '../locales/index.js' -import { Alert } from '@masknet/shared' -import { Icons } from '@masknet/icons' - -const useStyles = makeStyles()((theme) => ({ - paper: { - margin: 0, - background: theme.palette.maskColor.bottom, - maxWidth: 400, - }, - dialogTitle: { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - }, - title: { - fontSize: 18, - lineHeight: '18px', - fontWeight: 700, - margin: 'auto', - }, - subtitle: { - fontSize: 14, - lineHeight: '18px', - fontWeight: 700, - marginBottom: theme.spacing(1.5), - }, - description: { - fontSize: 14, - lineHeight: '18px', - }, -})) - -export interface ClaimRequirementsRuleDialogProps { - open: boolean - onClose: () => void -} - -export const ClaimRequirementsRuleDialog = memo(function ClaimRequirementsRuleDialog({ - open, - onClose, -}) { - const t = useRedPacketTrans() - const { classes } = useStyles() - - return usePortalShadowRoot((container) => ( - - - - {t.claim_requirements_title()} - - - {t.claim_requirements_rule_tips()} - - - {t.follow_me()} - {t.follow_me_description()} - - - {t.reaction_title()} - {t.reaction_description()} - - - {t.nft_holder()} - {t.nft_holder_description()} - - - - - )) -}) diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketAccountItem.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketAccountItem.tsx deleted file mode 100644 index b0f75fc77509..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketAccountItem.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { memo } from 'react' -import { Box, Typography } from '@mui/material' -import { ChainId, formatEthereumAddress, isValidAddress } from '@masknet/web3-shared-evm' -import { makeStyles } from '@masknet/theme' -import { Icons } from '@masknet/icons' -import { EVMExplorerResolver } from '@masknet/web3-providers' -import { openWindow } from '@masknet/shared-base-ui' - -const useStyles = makeStyles<{ isDarkFont?: boolean }>()((theme, { isDarkFont }) => ({ - linkIcon: { - color: isDarkFont ? theme.palette.maskColor.secondaryMainDark : '', - height: 16, - width: 16, - }, - linkButton: { - cursor: 'pointer', - background: 'none', - border: 'none', - padding: 0, - height: 16, - }, - creator: { - color: isDarkFont ? theme.palette.maskColor.secondaryMainDark : '', - }, -})) - -interface Props { - address: string - ens?: string - chainId?: ChainId - isDarkFont?: boolean -} - -export const FireflyRedPacketAccountItem = memo(function FireflyRedPacketAccountItem({ - address, - ens, - chainId = ChainId.Mainnet, - isDarkFont, -}: Props) { - const { classes } = useStyles({ isDarkFont }) - return ( - - {ens ? ens : formatEthereumAddress(address, 4)} - - - ) -}) diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketDetailsItem.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketDetailsItem.tsx deleted file mode 100644 index 1ee40989f049..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketDetailsItem.tsx +++ /dev/null @@ -1,434 +0,0 @@ -import { TokenIcon } from '@masknet/shared' -import { NetworkPluginID } from '@masknet/shared-base' -import { makeStyles } from '@masknet/theme' -import { useNetworkDescriptor, useChainContext } from '@masknet/web3-hooks-base' -import { formatBalance } from '@masknet/web3-shared-base' -import { Box, ListItem, Typography } from '@mui/material' -import { memo } from 'react' -import { RedPacketTrans, useRedPacketTrans } from '../locales/index.js' -import { format, fromUnixTime } from 'date-fns' -import { RedPacketActionButton } from './RedPacketActionButton.js' -import { FireflyRedPacketAPI } from '@masknet/web3-providers/types' -import { FireflyRedPacketAccountItem } from './FireflyRedPacketAccountItem.js' -import { Icons } from '@masknet/icons' -import urlcat from 'urlcat' - -const useStyles = makeStyles<{ listItemBackground?: string; listItemBackgroundIcon?: string }>()(( - theme, - { listItemBackground, listItemBackgroundIcon }, -) => { - const smallQuery = `@media (max-width: ${theme.breakpoints.values.sm}px)` - return { - message: { - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - [smallQuery]: { - whiteSpace: 'normal', - }, - }, - root: { - width: '100%', - padding: 0, - background: theme.palette.common.white, - marginBottom: theme.spacing(1.5), - borderRadius: 8, - '&:last-child': { - marginBottom: '80px', - }, - }, - contentItem: { - width: '100%', - borderRadius: 8, - position: 'static !important' as any, - height: 'auto !important', - padding: theme.spacing(1.5), - background: - listItemBackground ?? - 'linear-gradient(180deg, rgba(98, 126, 234, 0.15) 0%, rgba(98, 126, 234, 0.05) 100%)', - [smallQuery]: { - padding: theme.spacing(2, 1.5), - }, - '&:before': { - position: 'absolute', - content: '""', - bottom: 0, - left: 400, - zIndex: 0, - width: 114, - opacity: 0.2, - height: 61, - filter: 'blur(1.5px)', - background: listItemBackgroundIcon, - backgroundRepeat: 'no-repeat', - backgroundSize: '114px 114px', - }, - }, - box: { - display: 'flex', - width: '100%', - }, - content: { - transform: 'RedPacketTransY(-4px)', - width: '100%', - [smallQuery]: { - paddingLeft: theme.spacing(1.5), - width: 'auto', - }, - }, - section: { - display: 'flex', - width: '100%', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 15, - [smallQuery]: { - flexWrap: 'wrap', - }, - }, - div: { - maxWidth: 350, - }, - title: { - color: theme.palette.maskColor.dark, - fontWeight: 700, - fontSize: 14, - }, - info: { - color: theme.palette.maskColor.dark, - [smallQuery]: { - fontSize: 13, - }, - fontSize: 14, - }, - infoTitle: { - color: theme.palette.maskColor.secondaryDark, - marginRight: 4, - fontSize: 14, - [smallQuery]: { - fontSize: 13, - }, - }, - footer: { - width: '100%', - display: 'flex', - alignItems: 'center', - justifyContent: 'space-between', - flexWrap: 'nowrap', - marginTop: 15, - }, - footerInfo: { - fontSize: 14, - color: theme.palette.maskColor.dark, - '& span': { - color: theme.palette.maskColor.secondaryDark, - marginRight: 2, - }, - }, - claimFooterInfo: { - fontSize: 14, - color: theme.palette.maskColor.secondaryDark, - '& span': { - color: theme.palette.maskColor.dark, - marginRight: 2, - }, - }, - fullWidthBox: { - width: '100%', - display: 'flex', - }, - icon: { - width: 18, - height: 18, - marginLeft: 6, - }, - invisible: { - visibility: 'hidden', - }, - moreDetails: { - fontSize: 12, - fontStyle: 'normal', - fontWeight: 700, - lineHeight: '16px', - }, - icons: { - display: 'flex', - alignItems: 'center', - gap: '8px', - }, - button: { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - background: 'none', - cursor: 'pointer', - border: 'none', - padding: 0, - color: theme.palette.maskColor.secondaryMainDark, - zIndex: 10, - }, - } -}) - -const platformIconMap = { - [FireflyRedPacketAPI.PlatformType.twitter]: , - [FireflyRedPacketAPI.PlatformType.lens]: , - [FireflyRedPacketAPI.PlatformType.farcaster]: , -} - -const SITE_URL = 'https://firefly.mask.social' -interface HistoryInfo { - rp_msg: string - redpacket_id: string - received_time?: string - token_decimal: number - total_amounts?: string - token_symbol: string - token_amounts?: string - token_logo: string - chain_id: number - creator?: string - claim_numbers?: string - total_numbers?: string - claim_amounts?: string - create_time?: number - redpacket_status?: FireflyRedPacketAPI.RedPacketStatus - ens_name?: string - claim_strategy?: FireflyRedPacketAPI.StrategyPayload[] - share_from?: string - theme_id?: string - post_on?: Array<{ - platform: FireflyRedPacketAPI.PlatformType - postId: string - handle?: string - }> -} - -interface Props { - history: HistoryInfo - handleOpenDetails?: (rpid: string) => void - isDetail?: boolean -} - -const PlatformButton = memo(function PlatformButton(props: { - platform: FireflyRedPacketAPI.PlatformType - postId: string - className: string -}) { - const { platform, postId, className } = props - console.log('PlatformButton', platform, postId, className) - return ( - - {platformIconMap[platform]} - - ) -}) - -export const FireflyRedPacketDetailsItem = memo(function FireflyRedPacketDetailsItem(props: Props) { - const { history, handleOpenDetails, isDetail } = props - const { - rp_msg, - create_time, - claim_numbers, - total_numbers, - total_amounts, - token_decimal, - claim_amounts, - token_symbol, - token_logo, - chain_id, - creator, - redpacket_id, - token_amounts, - received_time, - redpacket_status, - ens_name, - claim_strategy, - share_from, - theme_id, - post_on, - } = history - const t = useRedPacketTrans() - - const { account } = useChainContext() - const networkDescriptor = useNetworkDescriptor(NetworkPluginID.PLUGIN_EVM, chain_id) - - const { classes, cx } = useStyles({ - listItemBackground: networkDescriptor?.backgroundGradient, - listItemBackgroundIcon: networkDescriptor ? `url("${networkDescriptor.icon}")` : undefined, - }) - const postReactionStrategy = claim_strategy?.find((x) => x.type === FireflyRedPacketAPI.StrategyType.postReaction) - return ( - -
- - -
-
-
- - {!rp_msg ? t.best_wishes() : rp_msg} - -
-
- - {create_time ? t.create_time() : t.received_time()} - - - {create_time ? - t.history_duration({ - time: format(fromUnixTime(create_time), 'M/d/yyyy HH:mm'), - }) - : null} - {received_time ? - t.history_duration({ - time: format( - fromUnixTime(Number.parseInt(received_time, 10)), - 'M/d/yyyy HH:mm', - ), - }) - : null} - -
- {creator ? -
- - {t.creator()} - - -
- : null} - {post_on?.length && isDetail ? -
- - {t.post_on()} - -
- {post_on - ?.sort((a, b) => { - if (a.platform === b.platform) return 0 - if (a.platform === FireflyRedPacketAPI.PlatformType.lens) return 1 - if (b.platform === FireflyRedPacketAPI.PlatformType.lens) return -1 - return 0 - }) - .map((x) => ( - - ))} -
-
- : null} -
- {( - redpacket_status && - redpacket_status !== FireflyRedPacketAPI.RedPacketStatus.View && - redpacket_status !== FireflyRedPacketAPI.RedPacketStatus.Send - ) ? - - : null} -
-
- {claim_numbers || total_numbers ? -
- - , - }} - values={{ - claimedShares: String(claim_numbers), - shares: String(total_numbers), - amount: formatBalance(total_amounts, token_decimal ?? 18, { - significant: 2, - isPrecise: true, - }), - claimedAmount: formatBalance(claim_amounts, token_decimal, { - significant: 2, - isPrecise: true, - }), - symbol: token_symbol, - }} - /> - - {token_logo ? - - : null} -
- : null} - {token_amounts ? -
- - {t.received()} - {formatBalance(token_amounts, token_decimal, { - significant: 2, - isPrecise: true, - })}{' '} - {token_symbol} - - {token_logo ? - - : null} -
- : null} - {handleOpenDetails ? - - : null} -
-
-
-
-
- ) -}) diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketHistoryDetails.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketHistoryDetails.tsx deleted file mode 100644 index e083b582400d..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketHistoryDetails.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { makeStyles } from '@masknet/theme' -import { Box, Typography } from '@mui/material' -import { memo, useMemo } from 'react' -import { FireflyRedPacketDetailsItem } from './FireflyRedPacketDetailsItem.js' -import { useSuspenseInfiniteQuery } from '@tanstack/react-query' -import { FireflyRedPacket } from '../../../../web3-providers/src/Firefly/RedPacket.js' -import { ElementAnchor } from '@masknet/shared' -import { createIndicator } from '@masknet/shared-base' -import { first } from 'lodash-es' -import { formatBalance } from '@masknet/web3-shared-base' -import { FireflyRedPacketAccountItem } from './FireflyRedPacketAccountItem.js' -import { useRedPacketTrans } from '../locales/index.js' - -const useStyles = makeStyles()((theme) => ({ - container: { - padding: '12px 16px', - height: 474, - '&::-webkit-scrollbar': { - display: 'none', - }, - }, - claimer: { - display: 'flex', - alignItems: 'center', - justifyContent: 'space-between', - marginTop: theme.spacing(1.5), - fontSize: 14, - fontWeight: 700, - lineHeight: '18px', - padding: '0 12px', - }, - claimerList: { - height: 324, - overflow: 'auto', - '&::-webkit-scrollbar': { - display: 'none', - }, - }, - noData: { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - width: '100%', - height: '318px', - fontSize: 14, - fontWeight: 700, - lineHeight: '24px', - color: theme.palette.maskColor.secondaryDark, - }, -})) - -interface Props { - rpid: string -} - -export const FireflyRedPacketHistoryDetails = memo(function FireflyRedPacketHistoryDetails({ rpid }: Props) { - const { classes } = useStyles() - const t = useRedPacketTrans() - const { data: claimData, fetchNextPage } = useSuspenseInfiniteQuery({ - queryKey: ['fireflyClaimHistory', rpid], - initialPageParam: '', - queryFn: async ({ pageParam }) => { - const res = await FireflyRedPacket.getClaimHistory(rpid, createIndicator(undefined, pageParam as string)) - return res - }, - getNextPageParam: (lastPage) => lastPage?.cursor, - }) - - const { claimInfo, claimList } = useMemo( - () => ({ claimList: claimData?.pages.flatMap((x) => x?.list) ?? [], claimInfo: first(claimData?.pages) }), - [claimData], - ) - - return ( -
- {claimInfo ? - - : null} - - {claimList.length ? - claimList.map((item) => ( -
- - - {formatBalance(item.token_amounts, item.token_decimal, { - significant: 6, - isPrecise: true, - })}{' '} - {item.token_symbol} - -
- )) - :
{t.no_claim_data()}
} - fetchNextPage()} height={10} /> -
-
- ) -}) diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketHistoryList.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketHistoryList.tsx deleted file mode 100644 index 231cafe2d2fa..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketHistoryList.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { ElementAnchor, EmptyStatus } from '@masknet/shared' -import { type NetworkPluginID } from '@masknet/shared-base' -import { makeStyles } from '@masknet/theme' -import { useChainContext } from '@masknet/web3-hooks-base' -import { FireflyRedPacketAPI } from '@masknet/web3-providers/types' -import { List } from '@mui/material' -import { memo, useMemo } from 'react' -import { RedPacketTrans, useRedPacketTrans } from '../locales/index.js' -import { FireflyRedPacketDetailsItem } from './FireflyRedPacketDetailsItem.js' -import { useRedPacketHistory } from './hooks/useRedPacketHistory.js' - -const useStyles = makeStyles()((theme) => { - const smallQuery = `@media (max-width: ${theme.breakpoints.values.sm}px)` - return { - root: { - display: 'flex', - padding: 0, - boxSizing: 'border-box', - flexDirection: 'column', - margin: '0 auto', - overflow: 'auto', - height: 474, - [smallQuery]: { - padding: 0, - }, - '&::-webkit-scrollbar': { - display: 'none', - }, - }, - placeholder: { - height: 474, - boxSizing: 'border-box', - width: '100%', - display: 'flex', - alignItems: 'center', - '& div': { - textAlign: 'center', - }, - }, - } -}) - -interface RedPacketHistoryListProps { - handleOpenDetails: (rpid: string) => void - historyType: FireflyRedPacketAPI.ActionType -} - -export const FireflyRedPacketHistoryList = memo(function RedPacketHistoryList({ - handleOpenDetails, - historyType, -}: RedPacketHistoryListProps) { - const t = useRedPacketTrans() - const { classes } = useStyles() - const { account } = useChainContext() - const { data: historiesData, fetchNextPage } = useRedPacketHistory(account, historyType) - const histories = useMemo(() => historiesData.pages.flatMap((page) => page.data), [historiesData]) - - if (!histories?.length) - return ( - - {historyType === FireflyRedPacketAPI.ActionType.Claim ? - t.no_claim_history_data() - : , - }} - /> - } - - ) - - return ( -
- - {histories.map((history) => ( - - ))} - - fetchNextPage()} /> -
- ) -}) diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketPast.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketPast.tsx deleted file mode 100644 index 3eb994e44358..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedPacketPast.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { PluginWalletStatusBar, LoadingStatus } from '@masknet/shared' -import { NetworkPluginID } from '@masknet/shared-base' -import { makeStyles } from '@masknet/theme' -import { FireflyRedPacketAPI } from '@masknet/web3-providers/types' -import { TabPanel } from '@mui/lab' -import { Box } from '@mui/material' -import { memo, Suspense } from 'react' -import { FireflyRedPacketHistoryList } from './FireflyRedPacketHistoryList.js' - -const useStyles = makeStyles()((theme) => ({ - tabWrapper: { - padding: '12px 16px', - }, - placeholder: { - height: 474, - boxSizing: 'border-box', - }, -})) - -interface Props { - tabs: Record<'sent' | 'claimed', 'sent' | 'claimed'> - handleOpenDetails: (rpid: string) => void -} - -export const FireflyRedPacketPast = memo(function FireflyRedPacketPast({ tabs, handleOpenDetails }: Props) { - const { classes } = useStyles() - - return ( - <> -
- - }> - - - - - }> - - - -
- - - - - ) -}) diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedpacketConfirmDialog.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedpacketConfirmDialog.tsx deleted file mode 100644 index f0d7c2ad46e9..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/FireflyRedpacketConfirmDialog.tsx +++ /dev/null @@ -1,465 +0,0 @@ -import { Box, Popover, Radio, Skeleton, Typography } from '@mui/material' -import { useRedPacketTrans } from '../locales/index.js' -import { compact, flatten, uniqBy } from 'lodash-es' -import { ActionButton, ShadowRootTooltip, makeStyles, usePortalShadowRoot } from '@masknet/theme' -import { type RedPacketSettings } from './hooks/useCreateCallback.js' -import { RequirementType, type FireflyContext, type FireflyRedpacketSettings } from '../types.js' -import { Alert, FormattedBalance, FormattedCurrency, TokenIcon } from '@masknet/shared' -import { useChainContext, useFungibleTokenPrice, useReverseAddress } from '@masknet/web3-hooks-base' -import { EMPTY_LIST, NetworkPluginID } from '@masknet/shared-base' -import { BigNumber } from 'bignumber.js' -import { formatBalance, formatCurrency, leftShift } from '@masknet/web3-shared-base' -import { REQUIREMENT_ICON_MAP, REQUIREMENT_TITLE_MAP } from './ClaimRequirementsDialog.js' -import { Icons } from '@masknet/icons' -import { useMemo, useState } from 'react' -import { useAsync, useStateList } from 'react-use' -import { FireflyRedPacket } from '@masknet/web3-providers' -import { FireflyRedPacketAPI, type RedPacketJSONPayload } from '@masknet/web3-providers/types' -import { formatEthereumAddress, isValidAddress, isValidDomain, type GasConfig } from '@masknet/web3-shared-evm' -import { useCreateFTRedpacketCallback } from './hooks/useCreateFTRedpacketCallback.js' - -const useStyles = makeStyles()((theme) => ({ - container: { - padding: theme.spacing(2), - }, - info: { - display: 'flex', - flexDirection: 'column', - rowGap: theme.spacing(2), - }, - item: { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - }, - title: { - fontSize: 14, - lineHeight: '18px', - fontWeight: 700, - }, - tips: { - fontSize: 14, - lineHeight: '18px', - fontWeight: 400, - }, - price: { - color: theme.palette.maskColor.third, - }, - requirements: { - display: 'flex', - alignItems: 'center', - columnGap: 8, - }, - question: { - color: theme.palette.maskColor.second, - }, - arrow: { - color: theme.palette.maskColor.second, - cursor: 'pointer', - }, - control: { - display: 'flex', - justifyContent: 'center', - columnGap: theme.spacing(1.5), - }, - alert: { - gap: 6, - }, - footer: { - width: '100%', - padding: theme.spacing(2), - boxSizing: 'border-box', - position: 'sticky', - bottom: 0, - background: theme.palette.maskColor.bottom, - boxShadow: theme.palette.maskColor.bottomBg, - }, - accountList: { - display: 'flex', - flexDirection: 'column', - rowGap: theme.spacing(1), - padding: theme.spacing(1, 0), - borderRadius: 8, - boxShadow: '0px 0px 16px 0px rgba(101, 119, 134, 0.20)', - minWidth: 288, - }, - accountListItem: { - padding: theme.spacing(0.5, 1.5), - display: 'flex', - columnGap: theme.spacing(1), - cursor: 'pointer', - alignItems: 'center', - }, - accountName: { - fontSize: 16, - lineHeight: '20px', - fontWeight: 700, - }, -})) - -export interface FireflyRedpacketConfirmDialogProps { - settings: RedPacketSettings - fireflySettings?: FireflyRedpacketSettings - fireflyContext: FireflyContext - gasOption?: GasConfig - onCreated: ( - payload: RedPacketJSONPayload, - payloadImage?: string, - claimRequirements?: FireflyRedPacketAPI.StrategyPayload[], - publicKey?: string, - ) => void - onClose: () => void -} - -function formatAccountName(account?: string) { - if (!account) return account - if (isValidAddress(account)) return formatEthereumAddress(account, 4) - if (isValidDomain(account)) return account - return `@${account}` -} - -export function FireflyRedpacketConfirmDialog({ - settings, - fireflySettings, - fireflyContext, - gasOption, - onCreated, - onClose, -}: FireflyRedpacketConfirmDialogProps) { - const { currentFarcasterProfile, currentLensProfile, currentTwitterProfile } = fireflyContext || {} - const t = useRedPacketTrans() - const { chainId, account } = useChainContext() - const { data: ensName } = useReverseAddress(NetworkPluginID.PLUGIN_EVM, account, true) - const { data: lensOwnerENS } = useReverseAddress(NetworkPluginID.PLUGIN_EVM, currentLensProfile?.ownedBy, true) - const { data: farcasterOwnerENS } = useReverseAddress( - NetworkPluginID.PLUGIN_EVM, - currentFarcasterProfile?.ownedBy, - true, - ) - const { classes, theme } = useStyles() - const snsHandle = currentLensProfile?.handle || currentFarcasterProfile?.handle || currentTwitterProfile?.handle - const [currentAccount, setCurrentAccount] = useState(snsHandle || ensName || account) - - const [anchorEl, setAnchorEl] = useState(null) - - const { data: price } = useFungibleTokenPrice(NetworkPluginID.PLUGIN_EVM, settings?.token?.address) - - const amount = useMemo( - () => leftShift(settings?.total || 0, settings?.token?.decimals), - [settings.total, settings.token?.decimals], - ) - - const { value: urls, loading: fetchUrlsLoading } = useAsync(async () => { - if (!currentAccount) return EMPTY_LIST - return FireflyRedPacket.getPayloadUrls( - isValidAddress(currentAccount) || isValidDomain(currentAccount) ? currentAccount : `@${currentAccount}`, - settings.total, - 'fungible', - settings.token?.symbol, - settings.token?.decimals, - ) - }, [currentAccount, settings.total, settings.token]) - - const { state, currentIndex, prev, next } = useStateList< - | { - themeId: string - url: string - } - | undefined - >(urls) - - const isFirst = currentIndex === 0 - const isLatest = urls?.length && currentIndex === urls.length - 1 - - const accounts = useMemo(() => { - const { currentFarcasterProfile, currentLensProfile, currentTwitterProfile } = fireflyContext - return uniqBy( - compact([ - currentLensProfile ? - { icon: , displayName: currentLensProfile.handle } - : undefined, - currentFarcasterProfile ? - { icon: , displayName: currentFarcasterProfile.handle } - : undefined, - currentLensProfile?.ownedBy ? - { icon: , displayName: lensOwnerENS || currentLensProfile.address } - : undefined, - currentTwitterProfile ? - { icon: , displayName: currentTwitterProfile.handle } - : undefined, - currentFarcasterProfile?.ownedBy ? - { - icon: , - displayName: farcasterOwnerENS || currentFarcasterProfile.ownedBy, - } - : undefined, - account ? { icon: , displayName: ensName || account } : undefined, - ]), - (x) => x.displayName?.toLowerCase(), - ) - }, [account, fireflyContext, farcasterOwnerENS, lensOwnerENS, ensName]) - - const { loading: imageLoading } = useAsync(async () => { - if (!state?.url) return - await fetch(state.url) - }, [state?.url]) - - const { value, loading } = useAsync(async () => { - if (!state?.themeId) return - const postReactions = fireflySettings?.requirements.filter( - (x) => x !== RequirementType.Follow && x !== RequirementType.NFTHolder, - ) - const payload = - fireflySettings ? - compact([ - fireflySettings.requirements.includes(RequirementType.Follow) ? - { - type: FireflyRedPacketAPI.StrategyType.profileFollow, - payload: compact([ - currentLensProfile ? - { - platform: FireflyRedPacketAPI.PlatformType.lens, - profileId: currentLensProfile.profileId, - } - : undefined, - currentFarcasterProfile ? - { - platform: FireflyRedPacketAPI.PlatformType.farcaster, - profileId: currentFarcasterProfile.profileId, - } - : undefined, - currentTwitterProfile ? - { - platform: FireflyRedPacketAPI.PlatformType.twitter, - profileId: currentTwitterProfile.profileId, - } - : undefined, - ]), - } - : undefined, - postReactions?.length ? - { - type: FireflyRedPacketAPI.StrategyType.postReaction, - payload: { - reactions: flatten( - postReactions.map((x) => { - if (x === RequirementType.Repost) return ['repost', 'quote'] - return x.toLowerCase() - }), - ), - }, - } - : undefined, - ( - fireflySettings.requirements.includes(RequirementType.NFTHolder) && - fireflySettings.nftHolderContract - ) ? - { - type: FireflyRedPacketAPI.StrategyType.nftOwned, - payload: [ - { - chainId: fireflySettings.nftChainId ?? chainId, - contractAddress: fireflySettings.nftHolderContract, - collectionName: fireflySettings.nftCollectionName, - }, - ], - } - : undefined, - ]) - : EMPTY_LIST - - return { - publicKey: await FireflyRedPacket.createPublicKey(state.themeId, currentAccount, payload), - claimRequirements: payload, - } - }, [ - state?.themeId, - currentLensProfile, - currentFarcasterProfile, - currentTwitterProfile, - fireflySettings, - chainId, - currentAccount, - ]) - - const { createRedpacket, isCreating } = useCreateFTRedpacketCallback( - value?.publicKey ?? '', - '', - settings, - gasOption, - (payload: RedPacketJSONPayload) => onCreated(payload, state?.url, value?.claimRequirements, value?.publicKey), - onClose, - currentAccount, - ) - - const popover = usePortalShadowRoot((container) => ( - setAnchorEl(null)} - anchorEl={anchorEl} - container={container} - disableScrollLock - disableRestoreFocus - anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }} - classes={{ paper: classes.accountList }}> - {accounts.map(({ displayName, icon }, index) => { - const isChecked = currentAccount && displayName?.toLowerCase() === currentAccount.toLowerCase() - - return ( - { - if (!displayName) return - setCurrentAccount(displayName) - setAnchorEl(null) - }}> - - {icon} - {formatAccountName(displayName)} - - {isChecked ? - - : null} - - ) - })} - - )) - - if (!settings) return null - - return ( - <> - - - - {t.drop_type()} - - {settings.isRandom ? t.random_amount() : t.identical_amount()} - - - - {t.number_of_winners()} - {settings.shares} - - - {t.amount()} - - - {settings.token ? - - : null} - - ( - - ) - - - - - {t.claim_requirements_title()} - {fireflySettings?.requirements.length ? - - {fireflySettings?.requirements.map((x) => { - const Icon = REQUIREMENT_ICON_MAP[x] - const title = REQUIREMENT_TITLE_MAP[x] - return ( - - - - ) - })} - - : {t.no()}} - - - - {t.share_from()} - - - - - - {formatAccountName(currentAccount)} - setAnchorEl(event.currentTarget)} - /> - - - - {t.image_preview()} - - - {state ? - - - {imageLoading || fetchUrlsLoading ? - - : null} - - : null} - - - - - - {t.unclaim_tips()} - - {t.create_redpacket_tips()} - - - - - - - {t.next_button()} - - - {popover} - - ) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacket/OperationFooter.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/RedPacket/OperationFooter.tsx deleted file mode 100644 index f1a44e68a450..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacket/OperationFooter.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import type { MouseEventHandler } from 'react' -import { useChainContext } from '@masknet/web3-hooks-base' -import { NetworkPluginID } from '@masknet/shared-base' -import { ChainId } from '@masknet/web3-shared-evm' -import { ActionButton, makeStyles } from '@masknet/theme' -import { Box, useTheme } from '@mui/material' -import { Icons } from '@masknet/icons' -import { ChainBoundary, WalletConnectedBoundary, SelectProviderModal } from '@masknet/shared' -import { useRedPacketTrans } from '../../locales/index.js' - -const useStyles = makeStyles()((theme) => { - return { - footer: { - width: '100%', - display: 'flex', - gap: theme.spacing(2), - justifyContent: 'center', - '& button': { - flexBasis: 'auto', - }, - [`@media (max-width: ${theme.breakpoints.values.sm}px)`]: { - flexDirection: 'column', - gap: theme.spacing(1), - }, - }, - } -}) - -interface OperationFooterProps { - chainId?: ChainId - canClaim: boolean - canRefund: boolean - /** Is claiming or checking claim status */ - isClaiming: boolean - isRefunding: boolean - onShare?(): void - onClaimOrRefund: () => void | Promise -} -export function OperationFooter({ - chainId, - canClaim, - canRefund, - isClaiming, - isRefunding, - onShare, - onClaimOrRefund, -}: OperationFooterProps) { - const { classes } = useStyles() - const t = useRedPacketTrans() - const { account, chainId: currentChainId } = useChainContext({ chainId }) - const theme = useTheme() - - function getObtainButton(onClick: MouseEventHandler) { - if (!account) { - return ( - SelectProviderModal.open()} variant="roundedDark"> - {t.plugin_wallet_connect_a_wallet()} - - ) - } - if (!canClaim && !canRefund) return null - if (!currentChainId) { - return ( - - {t.plugin_wallet_invalid_network()} - - ) - } - const isLoading = isClaiming || isRefunding - - return ( - - {canClaim ? - isClaiming ? - t.claiming() - : t.claim() - : isRefunding ? - t.refunding() - : t.refund()} - - ) - } - - return ( - - - {canRefund ? null : ( - } - onClick={onShare}> - {t.share()} - - )} - - {canClaim || canRefund || !account ? - - } - ActionButtonProps={{ variant: 'roundedDark' }}> - {getObtainButton(onClaimOrRefund)} - - - : null} - - - ) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacket/RequestLoginFooter.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/RedPacket/RequestLoginFooter.tsx deleted file mode 100644 index a7a4d8d5c21b..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacket/RequestLoginFooter.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { usePostInfoDetails } from '@masknet/plugin-infra/content-script' -import { ActionButton, makeStyles } from '@masknet/theme' -import { Box } from '@mui/material' -import { useRedPacketTrans } from '../../locales/index.js' - -const useStyles = makeStyles()((theme) => { - return { - footer: { - padding: theme.spacing(1.5), - }, - } -}) - -interface OperationFooterProps { - onRequest?(): void -} -export function RequestLoginFooter({ onRequest }: OperationFooterProps) { - const { classes } = useStyles() - const t = useRedPacketTrans() - const source = usePostInfoDetails.source() - - return ( - - - {t.connect_to_platform({ platform: source! })} - - - ) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacket/index.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/RedPacket/index.tsx deleted file mode 100644 index 2c3138cc3a49..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacket/index.tsx +++ /dev/null @@ -1,432 +0,0 @@ -import { useLastRecognizedIdentity, usePostInfoDetails, usePostLink } from '@masknet/plugin-infra/content-script' -import { requestLogin, share } from '@masknet/plugin-infra/content-script/context' -import { LoadingStatus, TransactionConfirmModal } from '@masknet/shared' -import { EMPTY_LIST, NetworkPluginID } from '@masknet/shared-base' -import { makeStyles, parseColor } from '@masknet/theme' -import type { HappyRedPacketV4 } from '@masknet/web3-contracts/types/HappyRedPacketV4.js' -import { useChainContext, useNetworkContext } from '@masknet/web3-hooks-base' -import { EVMChainResolver, FireflyRedPacket } from '@masknet/web3-providers' -import { RedPacketStatus, type FireflyRedPacketAPI, type RedPacketJSONPayload } from '@masknet/web3-providers/types' -import { TokenType, formatBalance, isZero } from '@masknet/web3-shared-base' -import { ChainId } from '@masknet/web3-shared-evm' -import { Card, Grow, Stack, Typography } from '@mui/material' -import { memo, useCallback, useMemo, useState } from 'react' -import { useRedPacketTrans } from '../../locales/index.js' -import { Requirements } from '../Requirements/index.js' -import { useAvailabilityComputed } from '../hooks/useAvailabilityComputed.js' -import { useClaimCallback } from '../hooks/useClaimCallback.js' -import { useRedPacketContract } from '../hooks/useRedPacketContract.js' -import { useRefundCallback } from '../hooks/useRefundCallback.js' -import { OperationFooter } from './OperationFooter.js' -import { RequestLoginFooter } from './RequestLoginFooter.js' -import { useRedPacketCover } from './useRedPacketCover.js' - -const useStyles = makeStyles<{ outdated: boolean }>()((theme, { outdated }) => { - return { - root: { - borderRadius: theme.spacing(2), - padding: theme.spacing(1.5, 2), - position: 'relative', - display: 'flex', - backgroundColor: 'transparent', - backgroundRepeat: 'no-repeat', - color: theme.palette.common.white, - flexDirection: 'column', - justifyContent: 'space-between', - marginBottom: outdated ? '12px' : 'auto', - marginLeft: 'auto', - marginRight: 'auto', - boxSizing: 'border-box', - width: 'calc(100% - 32px)', - [`@media (max-width: ${theme.breakpoints.values.sm}px)`]: { - padding: theme.spacing(1, 1.5), - width: 'calc(100% - 20px)', - }, - }, - fireflyRoot: { - aspectRatio: '10 / 7', - }, - maskRoot: { - marginTop: 'auto', - height: 335, - backgroundImage: `url(${new URL('../assets/cover.png', import.meta.url)})`, - backgroundSize: 'cover', - backgroundRepeat: 'no-repeat', - }, - cover: { - position: 'absolute', - width: '100%', - height: '100%', - objectFit: 'contain', - inset: 0, - margin: 'auto', - zIndex: 0, - }, - requirements: { - width: 407, - height: 'fit-content', - boxSizing: 'border-box', - position: 'absolute', - zIndex: 9, - inset: 0, - margin: 'auto', - [`@media (max-width: ${theme.breakpoints.values.md}px)`]: { - width: 'auto', - }, - }, - header: { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'flex-start', - }, - - content: { - display: 'flex', - flex: 1, - flexDirection: 'column', - alignItems: 'flex-start', - justifyContent: 'space-between', - }, - bottomContent: { - width: '100%', - display: 'flex', - justifyContent: 'space-between', - flexWrap: 'wrap', - }, - myStatus: { - fontSize: 12, - fontWeight: 600, - lineHeight: 1.8, - [`@media (max-width: ${theme.breakpoints.values.sm}px)`]: { - fontSize: 14, - left: 12, - bottom: 8, - }, - }, - from: { - fontSize: '14px', - color: theme.palette.common.white, - alignSelf: 'end', - fontWeight: 500, - [`@media (max-width: ${theme.breakpoints.values.sm}px)`]: { - fontSize: 14, - right: 12, - bottom: 8, - }, - }, - label: { - width: 76, - height: 27, - display: 'flex', - justifyContent: 'center', - fontSize: 12, - alignItems: 'center', - borderRadius: theme.spacing(1), - backgroundColor: parseColor(theme.palette.common.black).setAlpha(0.5).toString(), - textTransform: 'capitalize', - position: 'absolute', - right: 12, - top: 12, - }, - words: { - display: '-webkit-box', - WebkitLineClamp: 3, - WebkitBoxOrient: 'vertical', - color: theme.palette.common.white, - fontSize: 24, - fontWeight: 700, - wordBreak: 'break-all', - textOverflow: 'ellipsis', - overflow: 'hidden', - [`@media (max-width: ${theme.breakpoints.values.sm}px)`]: { - fontSize: 14, - }, - }, - messageBox: { - width: '100%', - }, - tokenLabel: { - width: 48, - height: 48, - position: 'absolute', - top: 0, - left: 0, - }, - } -}) - -export interface RedPacketProps { - payload: RedPacketJSONPayload -} - -export const RedPacket = memo(function RedPacket({ payload }: RedPacketProps) { - const t = useRedPacketTrans() - const token = payload.token - const { pluginID } = useNetworkContext() - const payloadChainId = token?.chainId ?? EVMChainResolver.chainId(payload.network ?? '') ?? ChainId.Mainnet - const { account } = useChainContext({ - chainId: payloadChainId, - account: pluginID === NetworkPluginID.PLUGIN_EVM ? undefined : '', - }) - - // #region token detailed - const { - availability, - computed: availabilityComputed, - checkAvailability, - claimStrategyStatus, - recheckClaimStatus, - checkingClaimStatus, - } = useAvailabilityComputed(account, payload) - - // #endregion - - const { canClaim, canRefund, listOfStatus } = availabilityComputed - - // #region remote controlled transaction dialog - const postLink = usePostLink() - - const [{ loading: isClaiming, value: claimTxHash }, claimCallback] = useClaimCallback(account, payload) - const source = usePostInfoDetails.source() - const platform = source?.toLowerCase() as 'lens' | 'farcaster' | 'twitter' - const postUrl = usePostInfoDetails.url() - const handle = usePostInfoDetails.handle() - const link = postLink.toString() || postUrl?.toString() - - const getShareText = useCallback( - (hasClaimed: boolean) => { - const context = hasClaimed ? (`${platform}_claimed` as const) : platform - return t.share_on_firefly({ - context, - sender: handle ?? '', - link: link!, - }) - }, - [link, t, platform, handle], - ) - const claimedShareText = useMemo(() => getShareText(true), [getShareText]) - const shareText = useMemo(() => { - const hasClaimed = listOfStatus.includes(RedPacketStatus.claimed) || claimTxHash - return getShareText(!!hasClaimed) - }, [getShareText, listOfStatus, claimTxHash]) - - const [{ loading: isRefunding }, _isRefunded, refundCallback] = useRefundCallback( - payload.contract_version, - account, - payload.rpid, - payloadChainId, - ) - - const redPacketContract = useRedPacketContract(payloadChainId, payload.contract_version) as HappyRedPacketV4 - const checkResult = useCallback(async () => { - const data = await redPacketContract.methods.check_availability(payload.rpid).call({ - // check availability is ok w/o account - from: account, - }) - if (isZero(data.claimed_amount)) return - TransactionConfirmModal.open({ - shareText: claimedShareText, - amount: formatBalance(data.claimed_amount, token?.decimals, { significant: 2 }), - token, - tokenType: TokenType.Fungible, - messageTextForNFT: t.claim_nft_successful({ - name: 'NFT', - }), - messageTextForFT: t.claim_token_successful({ - amount: formatBalance(data.claimed_amount, token?.decimals, { significant: 2 }), - name: `$${token?.symbol}`, - }), - title: t.lucky_drop(), - share: (text) => share?.(text, source ? source : undefined), - }) - }, [token, redPacketContract, payload.rpid, account, claimedShareText, source]) - - const [showRequirements, setShowRequirements] = useState(false) - const me = useLastRecognizedIdentity() - const myProfileId = me?.profileId - const myHandle = me?.identifier?.userId - const onClaimOrRefund = useCallback(async () => { - let hash: string | undefined - if (canClaim) { - const result = await recheckClaimStatus() - setShowRequirements(result === false) - if (result === false) return - hash = await claimCallback() - if (platform && myProfileId && myHandle && hash) { - await FireflyRedPacket.finishClaiming( - payload.rpid, - platform as FireflyRedPacketAPI.PlatformType, - myProfileId, - myHandle, - hash, - ) - } - checkResult() - } else if (canRefund) { - hash = await refundCallback() - } - if (typeof hash === 'string') { - checkAvailability() - } - }, [ - canClaim, - canRefund, - platform, - claimCallback, - checkResult, - recheckClaimStatus, - checkAvailability, - payload.rpid, - myProfileId, - myHandle, - ]) - - const myStatus = useMemo(() => { - if (!availability) return '' - if (token && listOfStatus.includes(RedPacketStatus.claimed)) - return t.description_claimed( - availability.claimed_amount ? - { - amount: formatBalance(availability.claimed_amount, token.decimals, { significant: 2 }), - symbol: token.symbol, - } - : { amount: '-', symbol: '-' }, - ) - return '' - }, [listOfStatus, t, token, availability?.claimed_amount]) - - const subtitle = useMemo(() => { - if (!availability || !token) return - - if (listOfStatus.includes(RedPacketStatus.expired) && canRefund) - return t.description_refund({ - balance: formatBalance(availability.balance, token.decimals, { significant: 2 }), - symbol: token.symbol ?? '-', - }) - if (listOfStatus.includes(RedPacketStatus.refunded)) return t.description_refunded() - if (listOfStatus.includes(RedPacketStatus.expired)) return t.description_expired() - if (listOfStatus.includes(RedPacketStatus.empty)) return t.description_empty() - if (!payload.password) return t.description_broken() - const i18nParams = { - total: formatBalance(payload.total, token.decimals, { significant: 2 }), - symbol: token.symbol ?? '-', - count: payload.shares.toString() ?? '-', - } - return payload.shares > 1 ? t.description_failover_other(i18nParams) : t.description_failover_one(i18nParams) - }, [availability, canRefund, token, t, payload, listOfStatus]) - - const handleShare = useCallback(() => { - if (shareText) share?.(shareText, source ? source : undefined) - }, [shareText, source]) - - const isEmpty = listOfStatus.includes(RedPacketStatus.empty) - const outdated = isEmpty || (!canRefund && listOfStatus.includes(RedPacketStatus.expired)) - - const { classes, cx } = useStyles({ outdated }) - - // RedPacket created from Mask has no cover settings - const cover = useRedPacketCover(payload, availability) - - // the red packet can fetch without account - if (!availability || !token) return - - const claimedOrEmpty = listOfStatus.includes(RedPacketStatus.claimed) || isEmpty - - return ( - <> - - {cover ? - - : null} - -
- {/* it might be fontSize: 12 on twitter based on theme? */} - {listOfStatus.length ? - { - if (claimedOrEmpty) setShowRequirements((v) => !v) - }}> - {resolveRedPacketStatus(listOfStatus)} - - : null} -
- {cover ? - - setShowRequirements(false)} - /> - - :
- -
- - {payload.sender.message} - -
-
-
- - {subtitle} - - - {myStatus} - -
- - {t.from({ name: payload.sender.name || '-' })} - -
-
- } -
- {outdated ? - null - : myHandle ? - - : { - requestLogin?.(source) - }} - /> - } - - ) -}) - -function resolveRedPacketStatus(listOfStatus: RedPacketStatus[]) { - if (listOfStatus.includes(RedPacketStatus.claimed)) return 'Claimed' - if (listOfStatus.includes(RedPacketStatus.refunded)) return 'Refunded' - if (listOfStatus.includes(RedPacketStatus.expired)) return 'Expired' - if (listOfStatus.includes(RedPacketStatus.empty)) return 'Empty' - return '' -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacket/useRedPacketCover.ts b/packages/plugins/RedPacket/src/SiteAdaptor/RedPacket/useRedPacketCover.ts deleted file mode 100644 index e9e0fac85607..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacket/useRedPacketCover.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { FireflyRedPacket } from '@masknet/web3-providers' -import type { RedPacketJSONPayload } from '@masknet/web3-providers/types' -import { minus, toFixed } from '@masknet/web3-shared-base' -import { isValidAddress, isValidDomain } from '@masknet/web3-shared-evm' -import { useQuery } from '@tanstack/react-query' -import type { useAvailability } from '../hooks/useAvailability.js' - -type Availability = ReturnType['data'] -export function useRedPacketCover(payload: RedPacketJSONPayload, availability: Availability) { - const token = payload.token - const { data } = useQuery({ - enabled: !!availability && !!payload.rpid && !!token?.symbol, - queryKey: ['red-packet', 'theme-id', payload.rpid, availability?.balance, availability?.claimed], - queryFn: async () => { - if (!token || !availability) return null - const name = payload.sender.name - - // Once a redpacket is refunded, its balance will be 0, that's not the remaining amount - const remainingAmount = toFixed(minus(payload.total, availability.claimed_amount)) - return FireflyRedPacket.getCoverUrlByRpid( - payload.rpid, - token.symbol, - token.decimals, - payload.shares, - payload.total, - [isValidAddress, isValidDomain, (n: string) => n.startsWith('@')].some((f) => f(name)) ? name : ( - `@${name}` - ), - payload.sender.message, - remainingAmount, - toFixed(minus(payload.shares, availability.claimed || 0)), - ) - }, - }) - return data -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketActionButton.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketActionButton.tsx deleted file mode 100644 index 296c01c4caef..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketActionButton.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import { memo, useCallback, useEffect, useState, useContext } from 'react' -import { ActionButton, makeStyles } from '@masknet/theme' -import { useMediaQuery, type Theme } from '@mui/material' -import { useRedPacketTrans } from '../locales/index.js' -import { FireflyRedPacketAPI } from '@masknet/web3-providers/types' -import { useRefundCallback } from './hooks/useRefundCallback.js' -import { openComposition } from './openComposition.js' -import { RedPacketMetaKey } from '../constants.js' -import { FireflyRedPacket } from '@masknet/web3-providers' -import type { ChainId } from '@masknet/web3-shared-evm' -import { useAsyncFn } from 'react-use' -import { CompositionTypeContext } from './RedPacketInjection.js' - -const useStyles = makeStyles()((theme) => { - const smallQuery = `@media (max-width: ${theme.breakpoints.values.sm}px)` - return { - actionButton: { - fontSize: 12, - width: 88, - height: 32, - background: `${theme.palette.maskColor.dark} !important`, - opacity: '1 !important', - color: theme.palette.maskColor.white, - borderRadius: '999px', - minHeight: 'auto', - [smallQuery]: { - marginTop: theme.spacing(1), - }, - '&:disabled': { - background: theme.palette.maskColor.primaryMain, - color: theme.palette.common.white, - }, - '&:hover': { - background: theme.palette.maskColor.dark, - color: theme.palette.maskColor.white, - opacity: 0.8, - }, - }, - } -}) - -interface TokenInfo { - symbol: string - decimals: number - amount?: string -} -interface Props { - rpid: string - account: string - redpacketStatus: FireflyRedPacketAPI.RedPacketStatus - claim_strategy?: FireflyRedPacketAPI.StrategyPayload[] - shareFrom?: string - themeId?: string - tokenInfo: TokenInfo - redpacketMsg?: string - chainId: ChainId - totalAmount?: string - createdAt?: number -} - -export const RedPacketActionButton = memo(function RedPacketActionButton(props: Props) { - const { - redpacketStatus: _redpacketStatus, - rpid, - account, - claim_strategy, - shareFrom, - themeId, - tokenInfo, - redpacketMsg, - chainId, - totalAmount, - createdAt, - } = props - const [updatedStatus, setUpdatedStatus] = useState() - const { classes, cx } = useStyles() - const isSmall = useMediaQuery((theme: Theme) => theme.breakpoints.down('sm')) - const t = useRedPacketTrans() - const compositionType = useContext(CompositionTypeContext) - - 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(), - } - - const [{ loading: isSharing }, shareCallback] = useAsyncFn(async () => { - if (!shareFrom || !themeId || !createdAt) return - - const payloadImage = await FireflyRedPacket.getPayloadUrlByThemeId( - themeId, - shareFrom, - tokenInfo.amount, - 'fungible', - tokenInfo.symbol, - Number(tokenInfo.decimals), - ) - openComposition( - RedPacketMetaKey, - { - contract_version: 4, - sender: { - address: account, - name: shareFrom, - message: redpacketMsg, - }, - creation_time: createdAt * 1000, - token: { - chainId, - symbol: tokenInfo.symbol, - decimals: tokenInfo.decimals, - }, - contract_address: rpid, - rpid, - shares: totalAmount, - total: tokenInfo.amount, - }, - compositionType, - { claimRequirements: claim_strategy, payloadImage }, - ) - }, []) - - const redpacketStatus = updatedStatus || _redpacketStatus - - const handleClick = useCallback(async () => { - if (redpacketStatus === FireflyRedPacketAPI.RedPacketStatus.Send) await shareCallback() - if (redpacketStatus === FireflyRedPacketAPI.RedPacketStatus.Refunding) await refundCallback() - }, [redpacketStatus, shareCallback, refundCallback]) - - useEffect(() => { - if (refunded) setUpdatedStatus(FireflyRedPacketAPI.RedPacketStatus.Refund) - }, [refunded]) - - return ( - { - handleClick() - }} - className={cx(classes.actionButton)} - disabled={ - redpacketStatus === FireflyRedPacketAPI.RedPacketStatus.Empty || - redpacketStatus === FireflyRedPacketAPI.RedPacketStatus.Expired || - redpacketStatus === FireflyRedPacketAPI.RedPacketStatus.Refund - } - size="large"> - {statusToTransMap[redpacketStatus]} - - ) -}) diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketConfirmDialog.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketConfirmDialog.tsx deleted file mode 100644 index 6e11b42a4282..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketConfirmDialog.tsx +++ /dev/null @@ -1,218 +0,0 @@ -import { useEffect, useMemo } from 'react' -import { Icons } from '@masknet/icons' -import { useChainContext, useNativeTokenPrice } from '@masknet/web3-hooks-base' -import { type GasConfig, type ChainId } from '@masknet/web3-shared-evm' -import { type RedPacketJSONPayload } from '@masknet/web3-providers/types' -import { Grid, Link, Paper, Typography } from '@mui/material' -import { makeStyles, ActionButton } from '@masknet/theme' -import { PluginWalletStatusBar, ChainBoundary, SelectGasSettingsToolbar } from '@masknet/shared' -import { NetworkPluginID } from '@masknet/shared-base' -import { Launch as LaunchIcon } from '@mui/icons-material' -import { EVMChainResolver, EVMExplorerResolver, EVMWeb3 } from '@masknet/web3-providers' -import { isZero } from '@masknet/web3-shared-base' -import { type RedPacketSettings } from './hooks/useCreateCallback.js' -import { useRedPacketTrans } from '../locales/index.js' -import { useCreateFTRedpacketCallback } from './hooks/useCreateFTRedpacketCallback.js' - -const useStyles = makeStyles()((theme) => ({ - link: { - display: 'flex', - marginLeft: theme.spacing(0.5), - }, - grid: { - paddingTop: theme.spacing(2), - paddingBottom: theme.spacing(2), - }, - gridWrapper: { - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(2), - }, - hit: { - display: 'flex', - alignItems: 'center', - maxWidth: 568, - fontWeight: 300, - borderRadius: 8, - backgroundColor: theme.palette.maskColor.bg, - color: theme.palette.text.primary, - padding: 12, - marginTop: 0, - marginBottom: 130, - marginLeft: 'auto', - marginRight: 'auto', - }, - ellipsis: { - fontSize: 24, - fontWeight: 700, - textOverflow: 'ellipsis', - overflow: 'hidden', - whiteSpace: 'nowrap', - }, - controller: { - position: 'sticky', - bottom: 0, - }, -})) - -interface ConfirmRedPacketFormProps { - onCreated: (payload: RedPacketJSONPayload) => void - onBack: () => void - onClose: () => void - settings: RedPacketSettings - gasOption?: GasConfig - onGasOptionChange?: (config: GasConfig) => void - expectedChainId: ChainId -} - -export function RedPacketConfirmDialog(props: ConfirmRedPacketFormProps) { - const t = useRedPacketTrans() - const { settings, onCreated, onClose, gasOption, onGasOptionChange, expectedChainId } = props - const { classes, cx } = useStyles() - const { chainId } = useChainContext({ chainId: expectedChainId }) - useEffect(() => { - if (settings?.token?.chainId !== chainId) onClose() - }, [chainId, onClose]) - - const { account: publicKey, privateKey = '' } = useMemo(() => EVMWeb3.createAccount(), []) - - const { - isBalanceInsufficient, - formatTotal, - estimateGasFee, - formatAvg, - gas, - isCreating, - isWaitGasBeMinus, - createRedpacket, - } = useCreateFTRedpacketCallback(publicKey, privateKey, settings, gasOption, onCreated, onClose) - const nativeTokenDetailed = useMemo(() => EVMChainResolver.nativeCurrency(chainId), [chainId]) - const { data: nativeTokenPrice = 0 } = useNativeTokenPrice(NetworkPluginID.PLUGIN_EVM, { chainId }) - - return ( - <> - - - - {settings?.message} - - - - - {t.split_mode()} - - - - - {settings?.isRandom ? t.random() : t.average()} - - - - - - {t.share()} - - - - - {settings?.shares} - - - - {settings?.isRandom ? null : ( - <> - - - {t.amount_per_share()} - - - - - - - - {isBalanceInsufficient ? '0' : formatAvg} {settings?.token?.symbol} - - - - )} - - - - {t.total_cost()} - - - - - - - - {formatTotal} {settings?.token?.symbol} - - - {estimateGasFee && !isZero(estimateGasFee) ? - - : null} - - - - - {t.hint()} - - - - - - - - {isCreating ? t.confirming() : t.confirm()} - - - - - ) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketDialog.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketDialog.tsx deleted file mode 100644 index 8b96f2481b67..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketDialog.tsx +++ /dev/null @@ -1,349 +0,0 @@ -import { Icons } from '@masknet/icons' -import { - useActivatedPluginSiteAdaptor, - useCurrentVisitingIdentity, - useLastRecognizedIdentity, - useSiteThemeMode, -} from '@masknet/plugin-infra/content-script' -import { InjectedDialog, LoadingStatus, useCurrentLinkedPersona } from '@masknet/shared' -import { CrossIsolationMessages, EMPTY_LIST, NetworkPluginID, PluginID } from '@masknet/shared-base' -import { makeStyles, MaskTabList, useTabs } from '@masknet/theme' -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 { TabContext } 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 { 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 { RedPacketERC20Form } from './RedPacketERC20Form.js' -import { CompositionTypeContext } from './RedPacketInjection.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 - const darkBackgroundColor = isDim ? '#38414b' : '#292929' - return { - dialogContent: { - padding: 0, - scrollbarWidth: 'none', - '::-webkit-scrollbar': { - display: 'none', - }, - - overflowX: 'hidden', - overflowY: scrollY ? 'auto' : 'hidden', - position: 'relative', - }, - abstractTabWrapper: { - width: '100%', - paddingBottom: theme.spacing(2), - }, - arrowButton: { - backgroundColor: theme.palette.mode === 'dark' ? darkBackgroundColor : undefined, - }, - placeholder: { - height: 474, - boxSizing: 'border-box', - }, - disabledTab: { - background: 'transparent !important', - color: `${theme.palette.maskColor.third} !important`, - }, - } -}) - -enum CreateRedPacketPageStep { - NewRedPacketPage = 'new', - ConfirmPage = 'confirm', - ClaimRequirementsPage = 'claim_requirements', -} - -interface RedPacketDialogProps { - open: boolean - onClose: () => void - isOpenFromApplicationBoard?: boolean - source?: PluginID - fireflyContext: FireflyContext -} - -export default function RedPacketDialog(props: RedPacketDialogProps) { - const t = useRedPacketTrans() - const [showHistory, setShowHistory] = useState(false) - const [showDetails, setShowDetails] = useState(false) - const [rpid, setRpid] = useState('') - const [showClaimRule, setShowClaimRule] = useState(false) - const [gasOption, setGasOption] = useState() - - const [step, setStep] = useState(CreateRedPacketPageStep.NewRedPacketPage) - - const { account, chainId: contextChainId, setChainId } = useChainContext() - const definition = useActivatedPluginSiteAdaptor.visibility.useAnyMode(PluginID.RedPacket) - const [currentHistoryTab, onChangeHistoryTab, historyTabs] = useTabs('claimed', 'sent') - const theme = useTheme() - const mode = useSiteThemeMode(theme) - - const { classes } = useStyles({ isDim: mode === 'dim', scrollY: !showHistory }) - - const chainIdList: ChainId[] = useMemo(() => { - return definition?.enableRequirement.web3?.[NetworkPluginID.PLUGIN_EVM]?.supportedChainIds ?? EMPTY_LIST - }, [definition?.enableRequirement.web3]) - const chainId = chainIdList.includes(contextChainId) ? contextChainId : ChainId.Mainnet - - // #region token lucky drop - const [settings, setSettings] = useState() - // #endregion - - // #region firefly redpacket - const [fireflyRpSettings, setFireflyRpSettings] = useState() - // #endregion - - // #region nft lucky drop - const [openNFTConfirmDialog, setOpenNFTConfirmDialog] = useState(false) - const [openSelectNFTDialog, setOpenSelectNFTDialog] = useState(false) - // #endregion - - const handleClose = useCallback(() => { - setStep(CreateRedPacketPageStep.NewRedPacketPage) - setSettings(undefined) - props.onClose() - }, [props.onClose, step]) - - const currentIdentity = useCurrentVisitingIdentity() - const lastRecognized = useLastRecognizedIdentity() - const linkedPersona = useCurrentLinkedPersona() - const senderName = - lastRecognized?.identifier?.userId ?? currentIdentity?.identifier?.userId ?? linkedPersona?.nickname - - const compositionType = useContext(CompositionTypeContext) - const onCreateOrSelect = useCallback( - async ( - payload: RedPacketJSONPayload, - payloadImage?: string, - claimRequirements?: FireflyRedPacketAPI.StrategyPayload[], - publicKey?: string, - ) => { - if (payload.password === '') { - if (payload.contract_version === 1) { - // eslint-disable-next-line no-alert - alert('Unable to share a lucky drop without a password. But you can still withdraw the lucky drop.') - // eslint-disable-next-line no-alert - payload.password = prompt('Please enter the password of the lucky drop:', '') ?? '' - } else if (payload.contract_version > 1 && payload.contract_version < 4) { - // just sign out the password if it is lost. - payload.password = await EVMWeb3.signMessage( - 'message', - web3_utils.sha3(payload.sender.message) ?? '', - { - account, - }, - ) - payload.password = payload.password.slice(2) - } - } - - openComposition(RedPacketMetaKey, reduceUselessPayloadInfo(payload), compositionType, { - payloadImage, - claimRequirements, - publicKey, - }) - handleClose() - }, - [senderName, handleClose, compositionType], - ) - - const onBack = useCallback(() => { - if (step === CreateRedPacketPageStep.ConfirmPage) { - setStep(CreateRedPacketPageStep.ClaimRequirementsPage) - } - if (step === CreateRedPacketPageStep.ClaimRequirementsPage) { - setStep(CreateRedPacketPageStep.NewRedPacketPage) - } - if (step === CreateRedPacketPageStep.NewRedPacketPage) { - handleClose() - if (props.source === PluginID.SmartPay) { - CrossIsolationMessages.events.smartPayDialogEvent.sendToAll({ open: true }) - } - } - }, [step, props.source === PluginID.SmartPay, handleClose]) - const isCreateStep = step === CreateRedPacketPageStep.NewRedPacketPage - const onNext = useCallback(() => { - if (!isCreateStep) return - setStep(CreateRedPacketPageStep.ClaimRequirementsPage) - }, [isCreateStep]) - const onDialogClose = useCallback(() => { - if (openSelectNFTDialog) return setOpenSelectNFTDialog(false) - if (openNFTConfirmDialog) return setOpenNFTConfirmDialog(false) - if (showDetails) return setShowDetails(false) - if (showHistory) return setShowHistory(false) - onBack() - }, [showHistory, openNFTConfirmDialog, openSelectNFTDialog, onBack, showDetails]) - - const _onChange = useCallback((val: Omit) => { - setSettings(val) - }, []) - - const handleCreated = useCallback( - ( - payload: RedPacketJSONPayload, - payloadImage?: string, - claimRequirements?: FireflyRedPacketAPI.StrategyPayload[], - publicKey?: string, - ) => { - onCreateOrSelect(payload, payloadImage, claimRequirements, publicKey) - setSettings(undefined) - }, - [onCreateOrSelect], - ) - - const title = useMemo(() => { - if (showDetails) return t.more_details() - if (showHistory) return t.history() - if (openSelectNFTDialog) return t.nft_select_collection() - if (openNFTConfirmDialog) return t.confirm() - if (step === CreateRedPacketPageStep.NewRedPacketPage) return t.display_name() - if (step === CreateRedPacketPageStep.ClaimRequirementsPage) return t.claim_requirements_title() - return t.details() - }, [showHistory, openSelectNFTDialog, openNFTConfirmDialog, step, showDetails]) - - const titleTail = useMemo(() => { - if ( - step === CreateRedPacketPageStep.NewRedPacketPage && - !openNFTConfirmDialog && - !showHistory && - !showDetails - ) { - return ( - { - if (!account) return - setShowHistory((history) => !history) - }} - /> - ) - } - - if (step === CreateRedPacketPageStep.ClaimRequirementsPage) { - return setShowClaimRule(true)} /> - } - return null - }, [step, openNFTConfirmDialog, showHistory, showDetails]) - - // #region gas config - const [defaultGasPrice] = useGasPrice(NetworkPluginID.PLUGIN_EVM, { chainId }) - const handleGasSettingChange = useCallback( - (gasConfig: GasConfig) => { - const editor = GasEditor.fromConfig(chainId, gasConfig) - setGasOption((config) => { - return editor.getGasConfig({ - gasPrice: defaultGasPrice, - maxFeePerGas: defaultGasPrice, - maxPriorityFeePerGas: defaultGasPrice, - ...config, - }) - }) - }, - [chainId, defaultGasPrice], - ) - // #endregion - - const handleOpenDetails = useCallback( - (redpacket_id: string) => { - setRpid(redpacket_id) - setShowDetails(true) - }, - [setShowDetails, setRpid, setShowHistory], - ) - const handleClaimRequirementsNext = useCallback((settings: FireflyRedpacketSettings) => { - setFireflyRpSettings(settings) - setStep(CreateRedPacketPageStep.ConfirmPage) - }, []) - - return ( - - - - - - : null - } - onClose={onDialogClose} - isOnBack={showHistory || step !== CreateRedPacketPageStep.NewRedPacketPage} - disableTitleBorder - titleBarIconStyle={ - step !== CreateRedPacketPageStep.NewRedPacketPage || showHistory || showDetails ? 'back' : 'close' - }> - - {step === CreateRedPacketPageStep.NewRedPacketPage ? - <> -
- -
- {showHistory && !showDetails ? - - : null} - - {showDetails ? - }> - - - : null} - - : null} - - {step === CreateRedPacketPageStep.ConfirmPage && settings ? - - : null} - {step === CreateRedPacketPageStep.ClaimRequirementsPage ? - <> - - setShowClaimRule(false)} /> - - : null} -
-
-
- ) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketERC20Form.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketERC20Form.tsx deleted file mode 100644 index 947dae408a1f..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketERC20Form.tsx +++ /dev/null @@ -1,426 +0,0 @@ -import { Icons } from '@masknet/icons' -import { useLastRecognizedIdentity } from '@masknet/plugin-infra/content-script' -import { - ChainBoundary, - EthereumERC20TokenApprovedBoundary, - FungibleTokenInput, - PluginWalletStatusBar, - SelectFungibleTokenModal, - SelectGasSettingsToolbar, - TokenValue, - useAvailableBalance, - useCurrentLinkedPersona, - WalletConnectedBoundary, -} from '@masknet/shared' -import { NetworkPluginID, PluginID } from '@masknet/shared-base' -import { ActionButton, makeStyles, MaskTextField, RadioIndicator } from '@masknet/theme' -import { useChainContext, useEnvironmentContext, useNativeTokenPrice } from '@masknet/web3-hooks-base' -import { useTransactionValue } from '@masknet/web3-hooks-evm' -import { EVMChainResolver, EVMWeb3 } from '@masknet/web3-providers' -import { - formatBalance, - type FungibleToken, - isGreaterThan, - isZero, - multipliedBy, - rightShift, - ZERO, -} from '@masknet/web3-shared-base' -import { type ChainId, type GasConfig, SchemaType, useRedPacketConstants } from '@masknet/web3-shared-evm' -import { Box, InputBase, Typography, useTheme } from '@mui/material' -import { BigNumber } from 'bignumber.js' -import { omit } from 'lodash-es' -import { type ChangeEvent, useCallback, useMemo, useState } from 'react' -import { useUpdateEffect } from 'react-use' -import { RED_PACKET_DEFAULT_SHARES, RED_PACKET_MAX_SHARES, RED_PACKET_MIN_SHARES } from '../constants.js' -import { useRedPacketTrans } from '../locales/index.js' -import { type RedPacketSettings, useCreateParams } from './hooks/useCreateCallback.js' -import { useDefaultCreateGas } from './hooks/useDefaultCreateGas.js' - -// seconds of 1 day -const duration = 60 * 60 * 24 - -const useStyles = makeStyles()((theme) => ({ - field: { - display: 'flex', - gap: 16, - margin: 16, - }, - input: { - flex: 1, - }, - button: { - margin: 0, - padding: 0, - height: 40, - maxWidth: 286, - }, - unlockContainer: { - margin: 0, - columnGap: 16, - flexFlow: 'unset', - ['& > div']: { - padding: '0px !important', - }, - }, - option: { - display: 'flex', - width: '50%', - alignItems: 'center', - color: theme.palette.maskColor.line, - }, - checkIconWrapper: { - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - cursor: 'pointer', - borderRadius: '50%', - marginRight: 5, - backgroundColor: 'transparent', - }, - tokenValue: { - flexGrow: 1, - }, - title: { - fontSize: 14, - fontWEight: 700, - lineHeight: '18px', - }, -})) - -interface RedPacketFormProps { - setERC721DialogHeight?: (height: number) => void - gasOption?: GasConfig - expectedChainId: ChainId - origin?: RedPacketSettings - onClose: () => void - onNext: () => void - onGasOptionChange?: (config: GasConfig) => void - onChange(settings: RedPacketSettings): void - onChainChange(newChainId: ChainId): void -} - -export function RedPacketERC20Form(props: RedPacketFormProps) { - const { origin, expectedChainId, gasOption, onChange, onNext, onGasOptionChange, onChainChange } = props - const t = useRedPacketTrans() - const { classes } = useStyles() - const theme = useTheme() - // context - const { pluginID } = useEnvironmentContext() - const { account, chainId } = useChainContext({ chainId: expectedChainId }) - const { HAPPY_RED_PACKET_ADDRESS_V4 } = useRedPacketConstants(chainId) - - // #region select token - const nativeTokenDetailed = useMemo(() => EVMChainResolver.nativeCurrency(chainId), [chainId]) - const { data: nativeTokenPrice = 0 } = useNativeTokenPrice(NetworkPluginID.PLUGIN_EVM, { chainId }) - const [token = nativeTokenDetailed, setToken] = useState | undefined>( - origin?.token, - ) - - const onSelectTokenChipClick = useCallback(async () => { - const picked = await SelectFungibleTokenModal.openAndWaitForClose({ - disableNativeToken: false, - selectedTokens: token ? [token.address] : [], - chainId, - networkPluginID: NetworkPluginID.PLUGIN_EVM, - pluginID: PluginID.RedPacket, - }) - if (!picked) return - if (chainId !== picked.chainId) { - onChainChange(picked.chainId as ChainId) - } - setToken(picked as FungibleToken) - }, [token?.address, chainId, onChainChange]) - // #endregion - - // #region packet settings - const [isRandom, setRandom] = useState( - !origin ? 1 - : origin.isRandom ? 1 - : 0, - ) - const [message, setMessage] = useState(origin?.message || '') - const myIdentity = useLastRecognizedIdentity() - const linkedPersona = useCurrentLinkedPersona() - - const senderName = myIdentity?.identifier?.userId || linkedPersona?.nickname || 'Unknown User' - - // shares - const [shares, setShares] = useState(origin?.shares || RED_PACKET_DEFAULT_SHARES) - const onShareChange = useCallback( - (ev: ChangeEvent) => { - const shares_ = ev.currentTarget.value.replaceAll(/[,.]/g, '') - if (shares_ === '') setShares('') - else if (/^[1-9]+\d*$/.test(shares_)) { - const parsed = Number.parseInt(shares_, 10) - if (parsed >= RED_PACKET_MIN_SHARES && parsed <= RED_PACKET_MAX_SHARES) { - setShares(Number.parseInt(shares_, 10)) - } else if (parsed > RED_PACKET_MAX_SHARES) { - setShares(RED_PACKET_MAX_SHARES) - } - } - }, - [RED_PACKET_MIN_SHARES, RED_PACKET_MAX_SHARES], - ) - - // amount - const [rawAmount, setRawAmount] = useState( - !origin ? '' - : origin.isRandom ? formatBalance(origin.total, origin.token?.decimals ?? 0) - : formatBalance(new BigNumber(origin.total ?? '0').div(origin.shares ?? 1), origin.token?.decimals ?? 0), - ) - const amount = rightShift(rawAmount || '0', token?.decimals) - const rawTotalAmount = useMemo( - () => (isRandom || !rawAmount ? rawAmount : multipliedBy(rawAmount, shares).toFixed()), - [rawAmount, isRandom, shares], - ) - - const totalAmount = useMemo(() => multipliedBy(amount, isRandom ? 1 : shares ?? '0'), [amount, shares, isRandom]) - const minTotalAmount = useMemo(() => new BigNumber(isRandom ? 1 : shares ?? 0), [shares, isRandom]) - const isDivisible = !totalAmount.dividedBy(shares).isLessThan(1) - - useUpdateEffect(() => { - setRawAmount('') - }, [token]) - - const creatingParams = useMemo( - () => ({ - duration, - isRandom: !!isRandom, - name: senderName, - message: message || t.best_wishes(), - shares: shares || 0, - token: - token ? - (omit(token, ['logoURI']) as FungibleToken) - : undefined, - total: totalAmount.toFixed(), - }), - [isRandom, senderName, message, t, shares, token, totalAmount], - ) - - const onClick = useCallback(() => { - onChange(creatingParams) - onNext() - }, [creatingParams, onChange, onNext]) - - // #region gas - const { account: publicKey } = useMemo(() => EVMWeb3.createAccount(), []) - const contract_version = 4 - const { value: params } = useCreateParams(chainId, creatingParams, contract_version, publicKey) - // #endregion - - // balance - const { value: defaultGas = ZERO } = useDefaultCreateGas( - { - duration, - isRandom: !!isRandom, - name: senderName, - message: message || t.best_wishes(), - shares: shares || 0, - token: - token ? - (omit(token, ['logoURI']) as FungibleToken) - : undefined, - total: rightShift(0.01, token?.decimals).toFixed(), - }, - contract_version, - publicKey, - ) - const { isAvailableBalance, balance, isGasSufficient } = useAvailableBalance( - NetworkPluginID.PLUGIN_EVM, - token?.address, - gasOption ? { ...gasOption, gas: new BigNumber(defaultGas).toString() } : undefined, - { - chainId, - }, - ) - - const { transactionValue, loading: loadingTransactionValue } = useTransactionValue( - origin?.total, - gasOption?.gas, - gasOption?.gasCurrency, - ) - // #endregion - - const validationMessage = useMemo(() => { - if (!token) return t.select_a_token() - if (!account) return t.plugin_wallet_connect_a_wallet() - if (isZero(shares || '0')) return t.enter_shares() - if (isGreaterThan(shares || '0', 255)) return t.max_shares() - if (isGreaterThan(minTotalAmount, balance) || isGreaterThan(totalAmount, balance)) - return t.insufficient_token_balance({ symbol: token?.symbol }) - if (isZero(amount)) { - return isRandom ? t.enter_total_amount() : t.enter_each_amount() - } - - if (!isDivisible) - return t.indivisible({ - symbol: token.symbol, - amount: formatBalance(1, token.decimals), - }) - return '' - }, [isRandom, account, amount, totalAmount, shares, token, balance, t, minTotalAmount]) - - const gasValidationMessage = useMemo(() => { - if (!token) return '' - if (!isGasSufficient) { - return t.no_enough_gas_fees() - } - if (!loadingTransactionValue && new BigNumber(transactionValue).isLessThanOrEqualTo(0)) - return t.insufficient_balance() - - return '' - }, [isAvailableBalance, balance, token?.symbol, transactionValue, loadingTransactionValue, isGasSufficient]) - - if (!token) return null - - return ( - <> -
-
-
- setRandom(1)} checked={!!isRandom} size={20} /> -
- - {t.random_amount()} - -
-
-
- setRandom(0)} checked={!isRandom} size={20} /> -
- - {t.identical_amount()} - -
-
-
- - - {t.winners()} - - - - ), - inputProps: { - autoComplete: 'off', - autoCorrect: 'off', - inputMode: 'decimal', - placeholder: t.enter_number_of_winners(), - spellCheck: false, - pattern: '^[0-9]+$', - }, - }} - /> -
-
- -
- - {t.message()} - - - setMessage(e.target.value)} - placeholder={t.blessing_words()} - value={message} - inputProps={{ - maxLength: 40, - }} - /> - - - {pluginID === NetworkPluginID.PLUGIN_EVM ? - - - - : null} - - {rawTotalAmount && !isZero(rawTotalAmount) ? - - : null} - - - - - - - - {validationMessage || gasValidationMessage || t.next()} - - - - - - - - ) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketHistoryList.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketHistoryList.tsx deleted file mode 100644 index faa84696b6a0..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketHistoryList.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { EmptyStatus, LoadingStatus, ElementAnchor } from '@masknet/shared' -import { type NetworkPluginID } from '@masknet/shared-base' -import { makeStyles } from '@masknet/theme' -import { useChainContext } from '@masknet/web3-hooks-base' -import { FireflyRedPacketAPI, type RedPacketJSONPayload } from '@masknet/web3-providers/types' -import { List } from '@mui/material' -import { memo, useMemo, type HTMLProps } from 'react' -import { useRedPacketTrans } from '../locales/index.js' -import { RedPacketInHistoryList } from './RedPacketInHistoryList.js' -import { useRedPacketHistory } from './hooks/useRedPacketHistory.js' - -const useStyles = makeStyles()((theme) => { - const smallQuery = `@media (max-width: ${theme.breakpoints.values.sm}px)` - return { - root: { - display: 'flex', - padding: 0, - height: 474, - boxSizing: 'border-box', - flexDirection: 'column', - margin: '0 auto', - overflow: 'auto', - [smallQuery]: { - padding: 0, - }, - scrollbarWidth: 'none', - '&::-webkit-scrollbar': { - display: 'none', - }, - }, - placeholder: { - height: 474, - boxSizing: 'border-box', - }, - } -}) - -interface RedPacketHistoryListProps extends Omit, 'onSelect'> { - onSelect: (payload: RedPacketJSONPayload) => void -} - -export const RedPacketHistoryList = memo(function RedPacketHistoryList({ - onSelect, - ...rest -}: RedPacketHistoryListProps) { - const t = useRedPacketTrans() - const { classes, cx } = useStyles() - const { account, chainId } = useChainContext() - const { - data: historyData, - isLoading, - fetchNextPage, - } = useRedPacketHistory(account, FireflyRedPacketAPI.ActionType.Send, FireflyRedPacketAPI.SourceType.MaskNetwork) - const histories = useMemo(() => historyData.pages.flatMap((page) => page.data), [historyData, chainId]) - - if (isLoading) return - - if (!histories?.length) return {t.search_no_result()} - - return ( -
- - {histories.map((history) => ( - - ))} - fetchNextPage()} /> - -
- ) -}) diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketInHistoryList.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketInHistoryList.tsx deleted file mode 100644 index 62888ccdb804..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketInHistoryList.tsx +++ /dev/null @@ -1,267 +0,0 @@ -import { TokenIcon } from '@masknet/shared' -import { NetworkPluginID } from '@masknet/shared-base' -import { makeStyles } from '@masknet/theme' -import { useChainContext, useFungibleToken, useNetworkDescriptor } from '@masknet/web3-hooks-base' -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 { Box, ListItem, Typography } from '@mui/material' -import { format, fromUnixTime } from 'date-fns' -import { memo } from 'react' -import { RedPacketTrans, useRedPacketTrans } from '../locales/index.js' -import { RedPacketActionButton } from './RedPacketActionButton.js' -import { useRedpacketToken } from './hooks/useRedpacketToken.js' -import { useEverSeen } from '@masknet/shared-base-ui' - -const DEFAULT_BACKGROUND = NETWORK_DESCRIPTORS.find((x) => x.chainId === ChainId.Mainnet)!.backgroundGradient! -const useStyles = makeStyles<{ listItemBackground?: string; listItemBackgroundIcon?: string }>()(( - theme, - { listItemBackground, listItemBackgroundIcon }, -) => { - const smallQuery = `@media (max-width: ${theme.breakpoints.values.sm}px)` - return { - message: { - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - [smallQuery]: { - whiteSpace: 'normal', - }, - }, - root: { - width: '100%', - padding: 0, - background: theme.palette.common.white, - marginBottom: theme.spacing(1.5), - borderRadius: 8, - '&:last-child': { - marginBottom: '80px', - }, - }, - contentItem: { - width: '100%', - borderRadius: 8, - position: 'static !important' as any, - height: 'auto !important', - padding: theme.spacing(1.5), - background: listItemBackground || DEFAULT_BACKGROUND, - [smallQuery]: { - padding: theme.spacing(2, 1.5), - }, - '&:before': { - position: 'absolute', - content: '""', - top: 45, - left: 400, - zIndex: 0, - width: 114, - opacity: 0.2, - height: 61, - filter: 'blur(1.5px)', - background: listItemBackgroundIcon, - backgroundRepeat: 'no-repeat', - backgroundSize: '114px 114px', - }, - }, - box: { - display: 'flex', - width: '100%', - }, - content: { - transform: 'RedPacketTransY(-4px)', - width: '100%', - [smallQuery]: { - paddingLeft: theme.spacing(1.5), - width: 'auto', - }, - }, - section: { - display: 'flex', - width: '100%', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 15, - [smallQuery]: { - flexWrap: 'wrap', - }, - }, - div: { - maxWidth: 350, - }, - title: { - color: theme.palette.maskColor.dark, - fontWeight: 700, - fontSize: 14, - }, - info: { - color: theme.palette.maskColor.dark, - [smallQuery]: { - fontSize: 13, - }, - fontSize: 14, - }, - infoTitle: { - color: theme.palette.maskColor.secondaryDark, - marginRight: 4, - fontSize: 14, - [smallQuery]: { - fontSize: 13, - }, - }, - footer: { - width: '100%', - display: 'flex', - alignItems: 'center', - flexWrap: 'nowrap', - marginTop: 15, - }, - footerInfo: { - fontSize: 14, - color: theme.palette.maskColor.secondaryDark, - '& span': { - color: theme.palette.maskColor.dark, - marginRight: 2, - }, - }, - fullWidthBox: { - width: '100%', - display: 'flex', - }, - icon: { - width: 18, - height: 18, - marginLeft: 6, - zIndex: -1, - }, - invisible: { - visibility: 'hidden', - }, - } -}) - -interface RedPacketInHistoryListProps { - history: FireflyRedPacketAPI.RedPacketSentInfo - onSelect: (payload: RedPacketJSONPayload) => void -} - -export const RedPacketInHistoryList = memo(function RedPacketInHistoryList(props: RedPacketInHistoryListProps) { - const { history } = props - const { - rp_msg, - create_time, - claim_numbers, - total_numbers, - total_amounts, - token_decimal, - claim_amounts, - token_symbol, - token_logo, - redpacket_id, - redpacket_status, - claim_strategy, - share_from, - theme_id, - } = history - const [seen, redpacketRef] = useEverSeen() - const chainId = history.chain_id - const t = useRedPacketTrans() - - const { account } = useChainContext() - const networkDescriptor = useNetworkDescriptor(NetworkPluginID.PLUGIN_EVM, chainId) - - const { classes, cx } = useStyles({ - listItemBackground: networkDescriptor?.backgroundGradient, - listItemBackgroundIcon: networkDescriptor ? `url("${networkDescriptor.icon}")` : undefined, - }) - - // Only concern about MATIC token which has been renamed to POL - 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 - - return ( - -
- - -
-
-
- - {!rp_msg ? t.best_wishes() : rp_msg} - -
-
- - {t.create_time()} - - - {t.history_duration({ - time: format(fromUnixTime(create_time), 'M/d/yyyy HH:mm'), - })} - -
-
- {redpacket_status && redpacket_status !== FireflyRedPacketAPI.RedPacketStatus.View ? - - : null} -
- -
- - , - }} - values={{ - claimedShares: String(claim_numbers), - shares: String(total_numbers), - amount: formatBalance(total_amounts, token_decimal ?? 18, { - significant: 2, - isPrecise: true, - }), - claimedAmount: formatBalance(claim_amounts, token_decimal, { - significant: 2, - isPrecise: true, - }), - symbol: tokenSymbol, - }} - /> - - {token_logo ? - - : null} -
-
-
-
-
- ) -}) diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketInPost.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketInPost.tsx deleted file mode 100644 index f3f5a1dd32b7..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketInPost.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { usePostLink } from '@masknet/plugin-infra/content-script' -import type { NetworkPluginID } from '@masknet/shared-base' -import { MaskLightTheme } from '@masknet/theme' -import { useChainContext } from '@masknet/web3-hooks-base' -import type { RedPacketRecord } from '@masknet/web3-providers/types' -import { ThemeProvider } from '@mui/material' -import { useEffect } from 'react' -import { RedPacketRPC } from '../messages.js' -import { RedPacket, type RedPacketProps } from './RedPacket/index.js' - -export function RedPacketInPost({ payload }: RedPacketProps) { - const { chainId } = useChainContext() - const fromUrl = usePostLink() - - useEffect(() => { - if (!fromUrl) return - if (!payload.txid && payload.contract_version !== 1) return - if (!payload.password) return - const record: RedPacketRecord = { - id: payload.contract_version === 1 ? payload.rpid : payload.txid, - from: fromUrl.toString(), - password: payload.password, - contract_version: payload.contract_version, - } - RedPacketRPC.addRedPacket(record, chainId) - }, [fromUrl, chainId]) - // #endregion - - return ( - - - - ) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketInjection.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketInjection.tsx deleted file mode 100644 index d797cf4cd4fb..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/RedPacketInjection.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { CrossIsolationMessages, type PluginID } from '@masknet/shared-base' -import { createContext, useCallback, useEffect, useState } from 'react' - -import type { CompositionType } from '@masknet/plugin-infra/content-script' -import { EVMWeb3ContextProvider } from '@masknet/web3-hooks-base' -import type { FireflyContext } from '../types.js' -import RedPacketDialog from './RedPacketDialog.js' - -export const CompositionTypeContext = createContext('timeline') - -export function RedPacketInjection() { - const [open, setOpen] = useState(false) - const [source, setSource] = useState() - const [compositionType, setCompositionType] = useState('timeline') - - const [fireflyContext, setFireflyContext] = useState() - useEffect(() => { - return CrossIsolationMessages.events.redpacketDialogEvent.on( - ({ open, source: pluginId, fireflyContext, compositionType = 'timeline' }) => { - setOpen(open) - setSource(pluginId) - setFireflyContext(fireflyContext) - setCompositionType(compositionType) - }, - ) - }, []) - - const handleClose = useCallback(() => { - setOpen(false) - }, []) - - if (!open || !fireflyContext) return null - return ( - - - - - - ) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/RedpacketMessagePanel.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/RedpacketMessagePanel.tsx deleted file mode 100644 index f7d41d527d6c..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/RedpacketMessagePanel.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { Box, InputBase, Typography } from '@mui/material' -import { makeStyles } from '@masknet/theme' -import { useRedPacketTrans } from '../locales/index.js' - -const useStyles = makeStyles()((theme) => { - return { - root: { - display: 'flex', - justifyContent: 'space-between', - flexDirection: 'column', - width: '100%', - }, - wrapper: { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - width: '100%', - }, - - input: { - flex: 1, - padding: theme.spacing(0.5), - }, - } -}) - -interface RedpacketMessagePanelProps { - message: string - onChange: (val: string) => void -} -export function RedpacketMessagePanel(props: RedpacketMessagePanelProps) { - const { onChange, message } = props - const { classes, cx } = useStyles() - const t = useRedPacketTrans() - - return ( - -
- {t.message_label()} -
-
- onChange(e.target.value)} - inputProps={{ maxLength: 100, placeholder: t.best_wishes() }} - value={message} - /> -
-
- ) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/Requirements/MentionLink.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/Requirements/MentionLink.tsx deleted file mode 100644 index 5f642407fef5..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/Requirements/MentionLink.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { LoadingBase, makeStyles } from '@masknet/theme' -import { FireflyTwitter } from '@masknet/web3-providers' -import { FireflyRedPacketAPI } from '@masknet/web3-providers/types' -import { Link } from '@mui/material' -import { useQuery } from '@tanstack/react-query' - -const useStyles = makeStyles()({ - textLink: { - color: '#8E96FF', - }, -}) - -function resolveProfileUrl(platform: FireflyRedPacketAPI.PlatformType, handle: string) { - switch (platform) { - case FireflyRedPacketAPI.PlatformType.farcaster: - return `/profile/farcaster/${handle}` - case FireflyRedPacketAPI.PlatformType.lens: - return `/profile/lens/${handle}` - case FireflyRedPacketAPI.PlatformType.twitter: - return `/${handle}` - } -} - -interface MentionLinkProps { - platform: FireflyRedPacketAPI.PlatformType - profileId: string - handle?: string -} - -export function MentionLink({ platform, profileId, handle }: MentionLinkProps) { - const { classes } = useStyles() - const isTwitter = platform === FireflyRedPacketAPI.PlatformType.twitter - const { data: twitterHandle, isLoading } = useQuery({ - enabled: isTwitter && !handle, - queryKey: ['twitter-user-info', profileId], - queryFn: async () => { - return FireflyTwitter.getUserInfoById(profileId) - }, - select(data) { - return data?.username - }, - }) - - if (isLoading) return - - if (!handle) return the creator - - return ( - - @{isTwitter ? twitterHandle || handle : handle} - - ) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/Requirements/index.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/Requirements/index.tsx deleted file mode 100644 index 985fa71bcb49..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/Requirements/index.tsx +++ /dev/null @@ -1,284 +0,0 @@ -import { Icons, type GeneratedIcon, type GeneratedIconProps } from '@masknet/icons' -import { usePostInfoDetails, usePostLink } from '@masknet/plugin-infra/content-script' -import { MaskColors, makeStyles } from '@masknet/theme' -import { useWeb3Utils } from '@masknet/web3-hooks-base' -import { NFTScanNonFungibleTokenEVM } from '@masknet/web3-providers' -import { FireflyRedPacketAPI } from '@masknet/web3-providers/types' -import { Box, IconButton, Link, List, ListItem, Typography, type BoxProps } from '@mui/material' -import { useQueries } from '@tanstack/react-query' -import { sortBy } from 'lodash-es' -import { forwardRef, useMemo } from 'react' -import { RedPacketTrans, useRedPacketTrans } from '../../locales/i18n_generated.js' -import { usePlatformType } from '../hooks/usePlatformType.js' -import { MentionLink } from './MentionLink.js' - -const useStyles = makeStyles()((theme) => ({ - box: { - backgroundColor: 'rgba(24,24,24,0.8)', - color: MaskColors.dark.text.primary, - borderRadius: 16, - padding: theme.spacing(2, 3), - [`@media (max-width: ${theme.breakpoints.values.sm}px)`]: { - padding: theme.spacing(1, 1), - borderRadius: 8, - }, - }, - header: { - fontSize: 16, - height: 20, - fontWeight: 700, - paddingBottom: theme.spacing(2), - borderBottom: `1px solid ${theme.palette.common.white}`, - display: 'flex', - alignItems: 'center', - [`@media (max-width: ${theme.breakpoints.values.sm}px)`]: { - paddingBottom: theme.spacing(1), - fontSize: 15, - }, - }, - closeButton: { - marginLeft: 'auto', - color: theme.palette.common.white, - padding: 0, - }, - list: { - padding: 0, - }, - item: { - minWidth: 0, - marginTop: theme.spacing(2), - padding: 0, - fontSize: 12, - display: 'flex', - alignItems: 'center', - height: 18, - }, - text: { - display: 'block', - marginRight: 10, - flexGrow: 1, - fontWeight: 'bold', - textOverflow: 'ellipsis', - overflow: 'hidden', - whiteSpace: 'nowrap', - '&::first-letter': { - textTransform: 'uppercase', - }, - }, - icon: { - marginRight: 10, - }, - textLink: { - color: '#8E96FF', - }, - link: { - display: 'inline-flex', - alignItems: 'center', - }, - linkIcon: { - opacity: 0.5, - color: theme.palette.common.white, - }, - state: { - marginLeft: 'auto', - }, -})) - -function ResultIcon({ result, ...props }: GeneratedIconProps & { result: boolean }) { - const Icon = result ? Icons.ResultYes : Icons.ResultNo - return -} - -interface Props extends BoxProps { - onClose?(): void - statusList: FireflyRedPacketAPI.ClaimStrategyStatus[] - showResults?: boolean -} - -const IconMap: Record = { - like: Icons.Heart, - repost: Icons.Repost, - quote: Icons.Repost, - comment: Icons.Comment, - collect: Icons.Heart, -} - -function resolveProfileUrl(platform: FireflyRedPacketAPI.PlatformType, handle: string) { - switch (platform) { - case FireflyRedPacketAPI.PlatformType.farcaster: - return `/profile/farcaster/${handle}` - case FireflyRedPacketAPI.PlatformType.lens: - return `/profile/lens/${handle}` - case FireflyRedPacketAPI.PlatformType.twitter: - return `/${handle}` - } -} -interface NFTListProps { - nfts: Array<{ - chainId: number - contractAddress: string - collectionName?: string - }> -} -function NFTList({ nfts }: NFTListProps) { - const { classes } = useStyles() - const queries = useQueries({ - queries: nfts.map((nft) => ({ - queryKey: ['nft-contract', nft.chainId, nft.contractAddress], - queryFn: async () => { - return NFTScanNonFungibleTokenEVM.getCollectionRaw(nft.contractAddress, { - chainId: nft.chainId, - }) - }, - })), - }) - const Utils = useWeb3Utils() - return ( - - {queries.map((query, index) => { - const { data } = query - const nft = nfts[index] - if (!data) return <>{nft.collectionName} - const url = Utils.explorerResolver.addressLink(nft.chainId, nft.contractAddress) - const name = nft.collectionName || data.name || data.symbol - return ( - - {name} - - ) - })} - - ) -} - -interface FollowProfileProps { - payload: Array - platform: FireflyRedPacketAPI.PlatformType -} - -function FollowProfile({ payload }: FollowProfileProps) { - return ( - - {payload.map((payload) => ( - - ))} - - ) -} - -export const Requirements = forwardRef(function Requirements( - { onClose, statusList, showResults = true, ...props }: Props, - ref, -) { - const t = useRedPacketTrans() - const { classes, cx } = useStyles() - const postLink = usePostLink() - const postUrl = usePostInfoDetails.url() - const link = postUrl?.href || postLink.toString() - const platform = usePlatformType() as FireflyRedPacketAPI.PlatformType - const requirements = useMemo(() => { - const orders = ['profileFollow', 'postReaction', 'nftOwned'] as const - const orderedStatusList = sortBy(statusList, (x) => orders.indexOf(x.type)) - return orderedStatusList.flatMap((status) => { - if (status.type === 'profileFollow') { - const payload = status.payload.filter((x) => x.platform === platform) - const handles = payload.map((x) => `@${x.handle}`) - return ( - - - - , - }} - /> - - {showResults ? - - : null} - - ) - } - if (status.type === 'postReaction') { - // discard `collect` for now - const conditions = status.result.conditions.filter((x) => x.key !== 'collect') - const hasRepost = !!conditions.find((x) => (x.key === 'quote' || x.key === 'repost') && x.value) - let hasRepostCondition = false - return conditions - .reduce((arr: typeof conditions, condition) => { - if (condition.key === 'quote' || condition.key === 'repost') { - if (hasRepostCondition) return arr - hasRepostCondition = true - return [...arr, { ...condition, key: 'repost', value: hasRepost }] as typeof conditions - } - return [...arr, condition] - }, []) - .map((condition) => { - const Icon = IconMap[condition.key] - return ( - - - - {condition.key === 'repost' ? t.repost({ context: platform }) : condition.key} - - - - - {showResults ? - - : null} - - ) - }) - } - if (status.type === 'nftOwned') { - const collectionNames = status.payload.map((x) => x.collectionName).join(', ') - return ( - - - - , - }} - /> - - {showResults ? - - : null} - - ) - } - return null - }) - }, [statusList, platform, showResults]) - return ( - - - {t.requirements()} - onClose?.()} - aria-label="Close"> - - - - {requirements} - - ) -}) diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/assets/background.png b/packages/plugins/RedPacket/src/SiteAdaptor/assets/background.png deleted file mode 100644 index 22e2e7d43d40..000000000000 Binary files a/packages/plugins/RedPacket/src/SiteAdaptor/assets/background.png and /dev/null differ diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/assets/cover.png b/packages/plugins/RedPacket/src/SiteAdaptor/assets/cover.png deleted file mode 100644 index 2ebdb8c453c1..000000000000 Binary files a/packages/plugins/RedPacket/src/SiteAdaptor/assets/cover.png and /dev/null differ diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/assets/maskFilledIcon.png b/packages/plugins/RedPacket/src/SiteAdaptor/assets/maskFilledIcon.png deleted file mode 100644 index a2f665862309..000000000000 Binary files a/packages/plugins/RedPacket/src/SiteAdaptor/assets/maskFilledIcon.png and /dev/null differ diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/assets/tokenLabel.png b/packages/plugins/RedPacket/src/SiteAdaptor/assets/tokenLabel.png deleted file mode 100644 index 445692830779..000000000000 Binary files a/packages/plugins/RedPacket/src/SiteAdaptor/assets/tokenLabel.png and /dev/null differ diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/emitter.ts b/packages/plugins/RedPacket/src/SiteAdaptor/emitter.ts deleted file mode 100644 index 8a0c1d68648a..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/emitter.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { CompositionType } from '@masknet/plugin-infra/content-script' -import { CrossIsolationMessages } from '@masknet/shared-base' - -export function openDialog(compositionType: CompositionType = 'timeline') { - CrossIsolationMessages.events.redpacketDialogEvent.sendToLocal({ open: true, compositionType }) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/helpers.ts b/packages/plugins/RedPacket/src/SiteAdaptor/helpers.ts deleted file mode 100644 index 776304b437bd..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/helpers.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { createRenderWithMetadata, createTypedMessageMetadataReader } from '@masknet/typed-message-react' -import { EVMChainResolver } from '@masknet/web3-providers' -import type { RedPacketJSONPayload } from '@masknet/web3-providers/types' -import { ChainId } from '@masknet/web3-shared-evm' -import { Ok, type Result } from 'ts-results-es' -import { RedPacketMetaKey } from '../constants.js' -import schema from '../schema.json' - -const reader = createTypedMessageMetadataReader(RedPacketMetaKey, schema) -export function RedPacketMetadataReader( - metadata: ReadonlyMap | undefined, -): Result { - const result = reader(metadata) - if (result.isOk()) { - const payload = result.value - // Hard code for legacy RedPacket - if (!payload.token && payload.contract_version === 1 && payload.token_type === 0) { - const chainId = payload.network === 'Mainnet' ? ChainId.Mainnet : undefined - if (!chainId) return result - - return Ok({ - ...payload, - token: EVMChainResolver.nativeCurrency(chainId), - }) - } - return result - } - return result -} -export const renderWithRedPacketMetadata = createRenderWithMetadata(RedPacketMetadataReader) diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useAvailability.ts b/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useAvailability.ts deleted file mode 100644 index 9ae82333f9d1..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useAvailability.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { ChainId, ProviderType, Transaction } from '@masknet/web3-shared-evm' -import type { BaseConnectionOptions } from '@masknet/web3-providers/types' -import type { HappyRedPacketV4 } from '@masknet/web3-contracts/types/HappyRedPacketV4.js' -import { useChainContext } from '@masknet/web3-hooks-base' -import type { NetworkPluginID } from '@masknet/shared-base' -import { useRedPacketContract } from './useRedPacketContract.js' -import { useQuery } from '@tanstack/react-query' - -export function useAvailability( - id: string, - version: number, - options?: BaseConnectionOptions, -) { - const { account, chainId } = useChainContext({ - account: options?.account, - chainId: options?.chainId, - }) - const redPacketContract = useRedPacketContract(chainId, version) as HappyRedPacketV4 - return useQuery({ - queryKey: ['red-packet', 'check-availability', chainId, version, id, account], - queryFn: async () => { - if (!id || !redPacketContract) return null - return redPacketContract.methods.check_availability(id).call({ - // check availability is ok w/o account - from: account, - }) - }, - refetchInterval(query) { - const { data } = query.state - if (!data) return 30_000 - if (data.expired || !data.balance) return false - return 30_000 - }, - }) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useAvailabilityComputed.ts b/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useAvailabilityComputed.ts deleted file mode 100644 index 6e82f3fb88c2..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useAvailabilityComputed.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { EMPTY_LIST } from '@masknet/shared-base' -import { EVMNetworkResolver } from '@masknet/web3-providers' -import { RedPacketStatus, type RedPacketJSONPayload } from '@masknet/web3-providers/types' -import { isSameAddress } from '@masknet/web3-shared-base' -import { ChainId, type NetworkType } from '@masknet/web3-shared-evm' -import type { QueryObserverResult, RefetchOptions } from '@tanstack/react-query' -import { compact } from 'lodash-es' -import { useCallback } from 'react' -import { useAvailability } from './useAvailability.js' -import { useClaimStrategyStatus } from './useClaimStrategyStatus.js' -import { useSignedMessage } from './useSignedMessage.js' -import { useParseRedPacket } from './useParseRedPacket.js' - -/** - * Fetch the red packet info from the chain - * @param payload - */ -export function useAvailabilityComputed(account: string, payload: RedPacketJSONPayload) { - const parsedChainId = - payload.token?.chainId ?? - EVMNetworkResolver.networkChainId((payload.network ?? '') as NetworkType) ?? - ChainId.Mainnet - - const { data: availability, refetch: recheckAvailability } = useAvailability( - payload.rpid, - payload.contract_version, - { - account, - chainId: parsedChainId, - }, - ) - const parsed = useParseRedPacket(parsedChainId) - const checkAvailability = recheckAvailability as ( - options?: RefetchOptions, - ) => Promise> - - const { data: password } = useSignedMessage(account, payload) - const { data, refetch, isFetching } = useClaimStrategyStatus(payload) - - const recheckClaimStatus = useCallback(async () => { - const { data } = await refetch() - return data?.data?.canClaim - }, [refetch]) - - if (!availability || (!payload.password && !data)) - return { - availability, - checkAvailability, - payload, - claimStrategyStatus: null, - checkingClaimStatus: isFetching, - recheckClaimStatus, - password, - computed: { - canClaim: !!data?.data?.canClaim, - canRefund: false, - listOfStatus: EMPTY_LIST as RedPacketStatus[], - }, - } - const isEmpty = availability.balance === '0' - const isExpired = availability.expired - const isClaimed = parsed?.redpacket?.isClaimed || availability.claimed_amount !== '0' - const isRefunded = isEmpty && availability.claimed < availability.total - const isCreator = isSameAddress(payload?.sender.address ?? '', account) - const isPasswordValid = !!(password && password !== 'PASSWORD INVALID') - // For a central RedPacket, we don't need to check about if the password is valid - const canClaimByContract = !isExpired && !isEmpty && !isClaimed - const canClaim = payload.password ? canClaimByContract && isPasswordValid : canClaimByContract - return { - availability, - checkAvailability, - claimStrategyStatus: data?.data, - recheckClaimStatus, - checkingClaimStatus: isFetching, - password, - computed: { - canClaim, - canRefund: isExpired && !isEmpty && isCreator, - canSend: !isEmpty && !isExpired && !isRefunded && isCreator, - isPasswordValid, - listOfStatus: compact([ - isClaimed ? RedPacketStatus.claimed : undefined, - isEmpty ? RedPacketStatus.empty : undefined, - isRefunded ? RedPacketStatus.refunded : undefined, - isExpired ? RedPacketStatus.expired : undefined, - ]), - }, - } -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useClaimCallback.ts b/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useClaimCallback.ts deleted file mode 100644 index 3b1e4facb420..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useClaimCallback.ts +++ /dev/null @@ -1,55 +0,0 @@ -import type { NetworkPluginID } from '@masknet/shared-base' -import type { HappyRedPacketV1 } from '@masknet/web3-contracts/types/HappyRedPacketV1.js' -import type { HappyRedPacketV4 } from '@masknet/web3-contracts/types/HappyRedPacketV4.js' -import { useChainContext } from '@masknet/web3-hooks-base' -import { EVMChainResolver, EVMWeb3 } from '@masknet/web3-providers' -import type { RedPacketJSONPayload } from '@masknet/web3-providers/types' -import { ContractTransaction } from '@masknet/web3-shared-evm' -import { useAsyncFn } from 'react-use' -import * as web3_utils from /* webpackDefer: true */ 'web3-utils' -import { useRedPacketContract } from './useRedPacketContract.js' -import { useSignedMessage } from './useSignedMessage.js' - -/** - * Claim fungible token red packet. - */ -export function useClaimCallback(account: string, payload: RedPacketJSONPayload = {} as RedPacketJSONPayload) { - const payloadChainId = payload.token?.chainId - const version = payload.contract_version - const rpid = payload.rpid - const { chainId: contextChainId } = useChainContext({ chainId: payloadChainId }) - const chainIdByName = EVMChainResolver.chainId('network' in payload ? payload.network! : '') - const chainId = payloadChainId || chainIdByName || contextChainId - const redPacketContract = useRedPacketContract(chainId, version) - const { refetch } = useSignedMessage(account, payload) - return useAsyncFn(async () => { - if (!redPacketContract || !rpid) return - const { data: signedMsg } = await refetch() - if (!signedMsg) return - const config = { - from: account, - } - // note: despite the method params type of V1 and V2 is the same, - // but it is more understandable to declare respectively - const contractTransaction = new ContractTransaction(redPacketContract) - const tx = - version === 4 ? - await contractTransaction.fillAll( - (redPacketContract as HappyRedPacketV4).methods.claim(rpid, signedMsg, account), - config, - ) - : await contractTransaction.fillAll( - (redPacketContract as HappyRedPacketV1).methods.claim( - rpid, - signedMsg, - account, - web3_utils.sha3(account)!, - ), - config, - ) - - return EVMWeb3.sendTransaction(tx, { - chainId, - }) - }, [rpid, account, chainId, redPacketContract, version, refetch]) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useClaimStrategyStatus.ts b/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useClaimStrategyStatus.ts deleted file mode 100644 index 9ddf515c43da..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useClaimStrategyStatus.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { useLastRecognizedIdentity } from '@masknet/plugin-infra/content-script' -import { NetworkPluginID } from '@masknet/shared-base' -import { useChainContext, useNetworkContext } from '@masknet/web3-hooks-base' -import { FireflyRedPacket } from '@masknet/web3-providers' -import type { RedPacketJSONPayload } from '@masknet/web3-providers/types' -import { useQuery } from '@tanstack/react-query' -import { usePlatformType } from './usePlatformType.js' - -export function useClaimStrategyStatus(payload: RedPacketJSONPayload) { - const platform = usePlatformType() - const { pluginID } = useNetworkContext() - const rpid = payload.rpid - - const { account } = useChainContext({ - chainId: payload.chainId, - account: pluginID === NetworkPluginID.PLUGIN_EVM ? undefined : '', - }) - const signedMessage = 'privateKey' in payload ? payload.privateKey : payload.password - const me = useLastRecognizedIdentity() - return useQuery({ - enabled: !signedMessage && !!platform, - queryKey: ['red-packet', 'claim-strategy', rpid, platform, account, me], - queryFn: async () => { - if (!platform || !account) return null - return FireflyRedPacket.checkClaimStrategyStatus({ - rpid, - profile: { - needLensAndFarcasterHandle: true, - platform, - profileId: me?.profileId, - lensToken: me?.lensToken, - farcasterMessage: me?.farcasterMessage as HexString, - farcasterSigner: me?.farcasterSigner as HexString, - farcasterSignature: me?.farcasterSignature as HexString, - }, - wallet: { - address: account, - }, - }) - }, - }) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useCreateCallback.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useCreateCallback.tsx deleted file mode 100644 index b77b7ff125cd..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useCreateCallback.tsx +++ /dev/null @@ -1,191 +0,0 @@ -import { useCallback } from 'react' -import { useAsync, useAsyncFn } from 'react-use' -import * as web3_utils from /* webpackDefer: true */ 'web3-utils' -import { omit } from 'lodash-es' -import type { NetworkPluginID } from '@masknet/shared-base' -import { useChainContext } from '@masknet/web3-hooks-base' -import type { HappyRedPacketV4 } from '@masknet/web3-contracts/types/HappyRedPacketV4.js' -import { type FungibleToken, isLessThan, toFixed } from '@masknet/web3-shared-base' -import { - type ChainId, - SchemaType, - useTokenConstants, - decodeEvents, - ContractTransaction, - type GasConfig, -} from '@masknet/web3-shared-evm' -import { EVMWeb3 } from '@masknet/web3-providers' -import { useRedPacketContract } from './useRedPacketContract.js' - -export interface RedPacketSettings { - shares: number - duration: number - isRandom: boolean - total: string - name: string - message: string - token?: FungibleToken -} - -export type ParamsObjType = { - publicKey: string - shares: number - isRandom: boolean - duration: number - seed: string - message: string - name: string - tokenType: number - tokenAddress: string - total: string - token?: FungibleToken -} - -export function checkParams(paramsObj: ParamsObjType) { - if (isLessThan(paramsObj.total, paramsObj.shares)) { - throw new Error('At least [number of lucky drops] tokens to your lucky drop.') - } - - if (paramsObj.shares <= 0) { - throw new Error('At least 1 person should be able to claim the lucky drop.') - } - - return true -} - -export type MethodParameters = Parameters -interface CreateParams { - gas: string | undefined - params: MethodParameters - paramsObj: ParamsObjType - gasError: Error | null -} - -function useCreateParamsCallback( - expectedChainId: ChainId, - redPacketSettings: RedPacketSettings | undefined, - version: number, - publicKey: string, -) { - const { account, chainId } = useChainContext({ chainId: expectedChainId }) - const { NATIVE_TOKEN_ADDRESS } = useTokenConstants(chainId) - const redPacketContract = useRedPacketContract(chainId, version) - const getCreateParams = useCallback(async (): Promise => { - if (!redPacketSettings || !redPacketContract || !publicKey) return null - const { duration, isRandom, message, name, shares, total, token } = redPacketSettings - const seed = Math.random().toString() - const tokenType = token!.schema === SchemaType.Native ? 0 : 1 - const tokenAddress = token!.schema === SchemaType.Native ? NATIVE_TOKEN_ADDRESS : token!.address - if (!tokenAddress) { - if (process.env.NODE_ENV === 'development' && !NATIVE_TOKEN_ADDRESS) { - console.error( - 'Not native token address for chain %s. Do you forget to configure it in token.json file?', - token!.chainId, - ) - } - return null - } - - const paramsObj: ParamsObjType = { - publicKey, - shares, - isRandom, - duration, - seed: web3_utils.sha3(seed)!, - message, - name, - tokenType, - tokenAddress, - total, - token, - } - - try { - checkParams(paramsObj) - } catch { - return null - } - - const params = Object.values(omit(paramsObj, ['token'])) as MethodParameters - - let gasError: Error | null = null - const value = toFixed(paramsObj.token?.schema === SchemaType.Native ? total : 0) - - const gas = await (redPacketContract as HappyRedPacketV4).methods - .create_red_packet(...params) - .estimateGas({ from: account, value }) - .catch((error: Error) => { - gasError = error - }) - - return { gas: gas ? toFixed(gas) : undefined, params, paramsObj, gasError } - }, [redPacketSettings, account, redPacketContract]) - - return getCreateParams -} - -export function useCreateParams( - expectedChainId: ChainId, - redPacketSettings: RedPacketSettings, - version: number, - publicKey: string, -) { - const getCreateParams = useCreateParamsCallback(expectedChainId, redPacketSettings, version, publicKey) - return useAsync(() => getCreateParams(), [JSON.stringify(redPacketSettings), version, publicKey]) -} - -export function useCreateCallback( - expectedChainId: ChainId, - redPacketSettings: RedPacketSettings, - version: number, - publicKey: string, - gasOption?: GasConfig, -) { - const { account, chainId } = useChainContext({ chainId: expectedChainId }) - const redPacketContract = useRedPacketContract(chainId, version) - const getCreateParams = useCreateParamsCallback(expectedChainId, redPacketSettings, version, publicKey) - - return useAsyncFn(async () => { - const { token } = redPacketSettings - const createParams = await getCreateParams() - if (!token || !redPacketContract || !createParams) return - - const { gas, params, paramsObj, gasError } = createParams - if (gasError) return - - try { - checkParams(paramsObj) - } catch (error) { - return - } - - // estimate gas and compose transaction - const tx = await new ContractTransaction(redPacketContract).fillAll( - redPacketContract.methods.create_red_packet(...params), - { - from: account, - value: toFixed(token.schema === SchemaType.Native ? paramsObj.total : 0), - gas, - chainId, - ...gasOption, - }, - ) - - const hash = await EVMWeb3.sendTransaction(tx, { - paymentToken: gasOption?.gasCurrency, - chainId, - gasOptionType: gasOption?.gasOptionType, - }) - const receipt = await EVMWeb3.getTransactionReceipt(hash, { chainId }) - if (receipt) { - const events = decodeEvents(redPacketContract.options.jsonInterface, receipt.logs) - - return { - hash, - receipt, - events, - } - } - return { hash, receipt } - }, [account, redPacketContract, redPacketSettings, gasOption, chainId]) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useCreateFTRedpacketCallback.ts b/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useCreateFTRedpacketCallback.ts deleted file mode 100644 index a4b1ad15fe48..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useCreateFTRedpacketCallback.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { isNativeTokenAddress, type GasConfig, useRedPacketConstants } from '@masknet/web3-shared-evm' -import { useCreateParams, type RedPacketSettings, useCreateCallback } from './useCreateCallback.js' -import { useBalance, useChainContext } from '@masknet/web3-hooks-base' -import { NetworkPluginID } from '@masknet/shared-base' -import { useTransactionValue } from '@masknet/web3-hooks-evm' -import { BigNumber } from 'bignumber.js' -import { EVMChainResolver } from '@masknet/web3-providers' -import type { RedPacketRecord, RedPacketJSONPayload } from '@masknet/web3-providers/types' -import { useCallback, useRef, useEffect } from 'react' -import { RedPacketRPC } from '../../messages.js' -import { formatBalance } from '@masknet/web3-shared-base' - -export function useCreateFTRedpacketCallback( - publicKey: string, - privateKey: string, - settings: RedPacketSettings, - gasOption?: GasConfig, - onCreated?: (payload: RedPacketJSONPayload) => void, - onClose?: () => void, - currentAccount?: string, -) { - // password should remain the same rather than change each time when createState change, - // otherwise password in database would be different from creating red-packet. - const contract_version = 4 - - const { chainId, networkType, account } = useChainContext() - const { value: createParams } = useCreateParams(chainId, settings, contract_version, publicKey) - const isNativeToken = isNativeTokenAddress(settings.token?.address) - const { transactionValue, estimateGasFee } = useTransactionValue( - settings.total, - createParams?.gas, - gasOption?.gasCurrency, - ) - - const { isPending: loadingBalance } = useBalance(NetworkPluginID.PLUGIN_EVM) - - const isWaitGasBeMinus = (!estimateGasFee || loadingBalance) && isNativeToken - - const isBalanceInsufficient = - isNativeTokenAddress(gasOption?.gasCurrency) && new BigNumber(transactionValue).isLessThanOrEqualTo(0) - - const total = - isNativeToken ? - isBalanceInsufficient ? '0' - : transactionValue - : (settings?.total as string) - - const formatTotal = formatBalance(total, settings?.token?.decimals ?? 18, { significant: isNativeToken ? 3 : 0 }) - const formatAvg = formatBalance( - new BigNumber(total).div(settings?.shares ?? 1).toFixed(0, 1), - settings?.token?.decimals ?? 18, - { significant: isNativeToken ? 3 : 0 }, - ) - - const [{ loading: isCreating }, createCallback] = useCreateCallback( - chainId, - { ...settings!, total, name: currentAccount || settings.name }, - contract_version, - publicKey, - gasOption, - ) - - const createRedpacket = useCallback(async () => { - const result = await createCallback() - const { hash, receipt, events } = result ?? {} - if (typeof hash !== 'string') return - if (typeof receipt?.transactionHash !== 'string') return - - // the settings is not available - if (!settings?.token) return - - const CreationSuccess = (events?.CreationSuccess?.returnValues ?? {}) as { - creation_time: string - creator: string - id: string - token_address: string - total: string - } - - // 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 record: RedPacketRecord = { - id: receipt.transactionHash, - from: '', - password: privateKey, - contract_version, - } - RedPacketRPC.addRedPacket(record, chainId) - - // output the redpacket as JSON payload - onCreated?.(payload.current) - }, [createCallback, settings, onCreated, currentAccount]) - - const payload = useRef({ - network: EVMChainResolver.chainName(chainId), - } as RedPacketJSONPayload) - - const { HAPPY_RED_PACKET_ADDRESS_V4 } = useRedPacketConstants(chainId) - - useEffect(() => { - const contractAddress = HAPPY_RED_PACKET_ADDRESS_V4 - if (!contractAddress) { - onClose?.() - return - } - payload.current.contract_address = contractAddress - payload.current.contract_version = contract_version - payload.current.network = EVMChainResolver.networkType(chainId) - }, [chainId, networkType, contract_version]) - - return { - createRedpacket, - isCreating, - formatAvg, - formatTotal, - isBalanceInsufficient, - isWaitGasBeMinus, - gas: createParams?.gas, - estimateGasFee, - } -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useDefaultCreateGas.ts b/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useDefaultCreateGas.ts deleted file mode 100644 index 21e17ba736c4..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useDefaultCreateGas.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { useAsync } from 'react-use' -import * as web3_utils from /* webpackDefer: true */ 'web3-utils' -import { omit } from 'lodash-es' -import type { NetworkPluginID } from '@masknet/shared-base' -import { ZERO, toFixed } from '@masknet/web3-shared-base' -import { useChainContext } from '@masknet/web3-hooks-base' -import type { HappyRedPacketV4 } from '@masknet/web3-contracts/types/HappyRedPacketV4.js' -import { SchemaType, useTokenConstants } from '@masknet/web3-shared-evm' -import { checkParams, type RedPacketSettings, type ParamsObjType, type MethodParameters } from './useCreateCallback.js' -import { useRedPacketContract } from './useRedPacketContract.js' - -export function useDefaultCreateGas( - redPacketSettings: RedPacketSettings | undefined, - version: number, - publicKey: string, -) { - const { account, chainId } = useChainContext() - const { NATIVE_TOKEN_ADDRESS } = useTokenConstants(chainId) - const redPacketContract = useRedPacketContract(chainId, version) - - return useAsync(async () => { - if (!redPacketSettings || !redPacketContract) return ZERO - const { duration, isRandom, message, name, shares, total, token } = redPacketSettings - if (!token) return ZERO - const seed = Math.random().toString() - const tokenType = token!.schema === SchemaType.Native ? 0 : 1 - const tokenAddress = token!.schema === SchemaType.Native ? NATIVE_TOKEN_ADDRESS : token!.address - if (!tokenAddress) { - return ZERO - } - - const paramsObj: ParamsObjType = { - publicKey, - shares, - isRandom, - duration, - seed: web3_utils.sha3(seed)!, - message, - name, - tokenType, - tokenAddress, - total, - token, - } - - try { - checkParams(paramsObj) - } catch { - return ZERO - } - - const params = Object.values(omit(paramsObj, ['token'])) as MethodParameters - - const value = toFixed(paramsObj.token?.schema === SchemaType.Native ? total : 0) - - return (redPacketContract as HappyRedPacketV4).methods - .create_red_packet(...params) - .estimateGas({ from: account, value }) - }, [JSON.stringify(redPacketSettings), account, redPacketContract, publicKey, version, NATIVE_TOKEN_ADDRESS]) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useParseRedPacket.ts b/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useParseRedPacket.ts deleted file mode 100644 index e00d49db29f2..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useParseRedPacket.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { useLastRecognizedIdentity, usePostInfoDetails } from '@masknet/plugin-infra/content-script' -import { EnhanceableSite, NetworkPluginID } from '@masknet/shared-base' -import { useChainContext, useNetworkContext } from '@masknet/web3-hooks-base' -import { FireflyRedPacket } from '@masknet/web3-providers' -import type { FireflyRedPacketAPI } from '@masknet/web3-providers/types' -import type { ChainId } from '@masknet/web3-shared-evm' -import { useQuery } from '@tanstack/react-query' - -/** - * Parse RedPacket with post info. - * Firefly only. - */ -export function useParseRedPacket(chainId: ChainId) { - const images = usePostInfoDetails.postMetadataImages() - const { pluginID } = useNetworkContext() - const { account } = useChainContext({ - chainId, - account: pluginID === NetworkPluginID.PLUGIN_EVM ? undefined : '', - }) - const source = usePostInfoDetails.source() - const me = useLastRecognizedIdentity() - const myProfileId = me?.profileId - const site = usePostInfoDetails.site() - const isOnFirefly = site === EnhanceableSite.Firefly - - const query = useQuery({ - enabled: images.length > 0 && isOnFirefly, - queryKey: ['red-packet', 'parse', source, images[0], account], - queryFn: async () => { - const platform = source?.toLowerCase() as FireflyRedPacketAPI.PlatformType - return FireflyRedPacket.parse({ - image: { - imageUrl: images[0], - }, - walletAddress: account, - platform, - profileId: myProfileId, - }) - }, - }) - return query.data -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/usePlatformType.ts b/packages/plugins/RedPacket/src/SiteAdaptor/hooks/usePlatformType.ts deleted file mode 100644 index 4e94abc96706..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/usePlatformType.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { usePostInfoDetails, type PostContextAuthor } from '@masknet/plugin-infra/content-script' -import { FireflyRedPacketAPI as F } from '@masknet/web3-providers/types' - -const map: Record, F.PlatformType> = { - Lens: F.PlatformType.lens, - Farcaster: F.PlatformType.farcaster, - Twitter: F.PlatformType.twitter, -} - -export function usePlatformType() { - const source = usePostInfoDetails.source?.() - if (!source) return '' - return map[source] -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useRedPacketContract.ts b/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useRedPacketContract.ts deleted file mode 100644 index 82c142824ec2..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useRedPacketContract.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { useContract } from '@masknet/web3-hooks-evm' -import HappyRedPacketV1ABI from '@masknet/web3-contracts/abis/HappyRedPacketV1.json' -import HappyRedPacketV2ABI from '@masknet/web3-contracts/abis/HappyRedPacketV2.json' -import HappyRedPacketV3ABI from '@masknet/web3-contracts/abis/HappyRedPacketV3.json' -import HappyRedPacketV4ABI from '@masknet/web3-contracts/abis/HappyRedPacketV4.json' -import type { HappyRedPacketV1 } from '@masknet/web3-contracts/types/HappyRedPacketV1.js' -import type { HappyRedPacketV2 } from '@masknet/web3-contracts/types/HappyRedPacketV2.js' -import type { HappyRedPacketV3 } from '@masknet/web3-contracts/types/HappyRedPacketV3.js' -import type { HappyRedPacketV4 } from '@masknet/web3-contracts/types/HappyRedPacketV4.js' -import { type ChainId, useRedPacketConstants } from '@masknet/web3-shared-evm' -import type { AbiItem } from 'web3-utils' - -export function useRedPacketContract(chainId: ChainId, version: number) { - const { - HAPPY_RED_PACKET_ADDRESS_V1: addressV1, - HAPPY_RED_PACKET_ADDRESS_V2: addressV2, - HAPPY_RED_PACKET_ADDRESS_V3: addressV3, - HAPPY_RED_PACKET_ADDRESS_V4: addressV4, - } = useRedPacketConstants(chainId) - const v1 = useContract(chainId, addressV1, HappyRedPacketV1ABI as AbiItem[]) - const v2 = useContract(chainId, addressV2, HappyRedPacketV2ABI as AbiItem[]) - const v3 = useContract(chainId, addressV3, HappyRedPacketV3ABI as AbiItem[]) - const v4 = useContract(chainId, addressV4, HappyRedPacketV4ABI as AbiItem[]) - const versions = [v1, v2, v3, v4] as const - return versions[version - 1] -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useRedPacketHistory.ts b/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useRedPacketHistory.ts deleted file mode 100644 index 484dab442eee..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useRedPacketHistory.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { FireflyRedPacketAPI } from '@masknet/web3-providers/types' -import { useSuspenseInfiniteQuery, type UseSuspenseInfiniteQueryResult, type InfiniteData } from '@tanstack/react-query' -import { createIndicator } from '@masknet/shared-base' -import { FireflyRedPacket } from '@masknet/web3-providers' -import type { Pageable, PageIndicator } from '@masknet/shared-base' - -export function useRedPacketHistory( - address: string, - historyType: FireflyRedPacketAPI.ActionType, - platform?: FireflyRedPacketAPI.SourceType, -): UseSuspenseInfiniteQueryResult< - InfiniteData< - Pageable - > -> { - return useSuspenseInfiniteQuery({ - queryKey: ['RedPacketHistory', address, historyType], - initialPageParam: createIndicator(undefined, ''), - queryFn: async ({ pageParam }) => { - const res = await FireflyRedPacket.getHistory( - historyType, - address as `0x${string}`, - platform ? platform : FireflyRedPacketAPI.SourceType.All, - pageParam, - ) - return res - }, - getNextPageParam: (lastPage) => lastPage.nextIndicator, - }) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useRedpacketToken.ts b/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useRedpacketToken.ts deleted file mode 100644 index 829ae464bd40..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useRedpacketToken.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { NetworkPluginID } from '@masknet/shared-base' -import HappyRedPacketV4ABI from '@masknet/web3-contracts/abis/HappyRedPacketV4.json' -import { useWeb3, useWeb3Connection } from '@masknet/web3-hooks-base' - -import { CREATE_LUCKY_DROP_TOPIC } from '@masknet/web3-providers' -import type { ChainId } from '@masknet/web3-shared-evm' -import { useQuery } from '@tanstack/react-query' - -/** - * Get redpacket token address from transaction logs - */ -export function useRedpacketToken(chainId: ChainId, hash: string, enabled?: boolean) { - const web3 = useWeb3(NetworkPluginID.PLUGIN_EVM, { chainId }) - const web3Conn = useWeb3Connection(NetworkPluginID.PLUGIN_EVM, { chainId }) - - const inputs = HappyRedPacketV4ABI!.find((x) => x.name === 'CreationSuccess' && x.type === 'event')?.inputs - return useQuery({ - enabled, - queryKey: ['redpacket', 'token', chainId, hash], - queryFn: async () => { - if (!web3) return - const receipt = await web3Conn.getTransactionReceipt(hash) - if (!receipt || !inputs) return null - const log = receipt.logs.find((x) => x.topics[0] === CREATE_LUCKY_DROP_TOPIC) - if (!log) return null - - const result = web3.eth.abi.decodeLog(inputs, log.data, log?.topics) - return result.token_address - }, - }) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useRefundCallback.ts b/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useRefundCallback.ts deleted file mode 100644 index ef43a68e089a..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useRefundCallback.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { useState } from 'react' -import { useAsyncFn } from 'react-use' -import { useChainContext } from '@masknet/web3-hooks-base' -import type { NetworkPluginID } from '@masknet/shared-base' -import { type ChainId, ContractTransaction } from '@masknet/web3-shared-evm' -import { EVMWeb3 } from '@masknet/web3-providers' -import { useRedPacketContract } from './useRedPacketContract.js' - -export function useRefundCallback(version: number, from: string, id?: string, expectedChainId?: ChainId) { - const { chainId } = useChainContext({ chainId: expectedChainId }) - const [isRefunded, setIsRefunded] = useState(false) - const redPacketContract = useRedPacketContract(chainId, version) - - const [state, refundCallback] = useAsyncFn(async () => { - if (!redPacketContract || !id) return - - setIsRefunded(false) - console.log(redPacketContract) - const tx = await new ContractTransaction(redPacketContract).fillAll(redPacketContract.methods.refund(id), { - from, - }) - const hash = await EVMWeb3.sendTransaction(tx, { - chainId, - }) - setIsRefunded(true) - return hash - }, [id, redPacketContract, chainId, from]) - - return [state, isRefunded, refundCallback] as const -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useSignedMessage.ts b/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useSignedMessage.ts deleted file mode 100644 index 97b3c6ed1ae3..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/hooks/useSignedMessage.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { useLastRecognizedIdentity } from '@masknet/plugin-infra/content-script' -import { FireflyRedPacket } from '@masknet/web3-providers' -import { type RedPacketJSONPayload } from '@masknet/web3-providers/types' -import { signMessage } from '@masknet/web3-shared-evm' -import { useQuery } from '@tanstack/react-query' -import { RedPacketRPC } from '../../messages.js' -import { usePlatformType } from './usePlatformType.js' - -export function useSignedMessage(account: string, payload: RedPacketJSONPayload = {} as RedPacketJSONPayload) { - const rpid = payload.rpid - const password = 'privateKey' in payload ? payload.privateKey : payload.password - const version = payload.contract_version - const platform = usePlatformType() - const me = useLastRecognizedIdentity() - const profile = - platform ? - { - needLensAndFarcasterHandle: true, - platform, - profileId: me?.profileId, - handle: me?.identifier?.userId, - lensToken: me?.lensToken, - farcasterMessage: me?.farcasterMessage as HexString, - farcasterSigner: me?.farcasterSigner as HexString, - farcasterSignature: me?.farcasterSignature as HexString, - } - : undefined - - return useQuery({ - queryKey: ['red-packet', 'signed-message', rpid, version, password, account, profile], - queryFn: async () => { - try { - const record = await RedPacketRPC.getRedPacketRecord(payload.txid) - if (record?.password) return record.password - } catch {} - if (version <= 3) return password as string - if (password) return signMessage(account, password as string).signature - if (!profile || !account) return '' - return FireflyRedPacket.createClaimSignature({ - rpid, - profile, - wallet: { - address: account, - }, - }) - }, - }) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/index.tsx b/packages/plugins/RedPacket/src/SiteAdaptor/index.tsx deleted file mode 100644 index 3abf2ecd59cd..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/index.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { Icons } from '@masknet/icons' -import { usePluginWrapper, type Plugin } from '@masknet/plugin-infra/content-script' -import { EnhanceableSite, PluginID, getEnhanceableSiteType } from '@masknet/shared-base' -import { memo } from 'react' -import { Trans } from 'react-i18next' -import { base } from '../base.js' -import { RedPacketInPost } from './RedPacketInPost.js' -import { RedPacketInjection } from './RedPacketInjection.js' -import { openDialog } from './emitter.js' -import { RedPacketMetadataReader, renderWithRedPacketMetadata } from './helpers.js' - -function Render( - props: React.PropsWithChildren<{ - name: string - }>, -) { - usePluginWrapper(true, { name: props.name }) - return <>{props.children} -} - -const isFirefly = getEnhanceableSiteType() === EnhanceableSite.Firefly -const PluginIcon = isFirefly ? Icons.Gift : Icons.RedPacket - -const site: Plugin.SiteAdaptor.Definition = { - ...base, - init(signal) {}, - DecryptedInspector: memo(function RedPacketInspector(props) { - const meta = props.message.meta - if (RedPacketMetadataReader(meta).isOk()) - return ( - - {renderWithRedPacketMetadata(meta, (r) => ( - - ))} - - ) - - return null - }), - GlobalInjection: RedPacketInjection, - CompositionDialogEntry: { - label: ( - <> - - - - ), - onClick: ({ compositionType }) => { - openDialog(compositionType) - }, - }, - wrapperProps: { - icon: , - backgroundGradient: - 'linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.2) 0%, rgba(249, 55, 55, 0.2) 100%), #FFFFFF', - }, -} - -export default site diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/openComposition.ts b/packages/plugins/RedPacket/src/SiteAdaptor/openComposition.ts deleted file mode 100644 index c217fcfb6ac5..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/openComposition.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { CrossIsolationMessages } from '@masknet/shared-base' - -export function openComposition( - metadataKey: string, - payload: unknown, - reason: 'popup' | 'timeline' = 'timeline', - extraMeta?: unknown, -) { - // Close the duplicated dialog if already opened by clicking the mask compose icon. - CrossIsolationMessages.events.compositionDialogEvent.sendToLocal({ reason: 'popup', open: false }) - CrossIsolationMessages.events.compositionDialogEvent.sendToLocal({ - reason, - open: true, - options: { - initialMetas: { - [metadataKey]: payload, - }, - pluginMeta: extraMeta, - }, - }) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/utils/formatDate.ts b/packages/plugins/RedPacket/src/SiteAdaptor/utils/formatDate.ts deleted file mode 100644 index 924364a5ca84..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/utils/formatDate.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { i18NextInstance } from '@masknet/shared-base' - -export function dateTimeFormat(date: Date, includeTime = true) { - return new Intl.DateTimeFormat( - i18NextInstance.language, - includeTime ? - { - year: 'numeric', - month: 'numeric', - day: 'numeric', - hour: 'numeric', - minute: 'numeric', - hourCycle: 'h23', - } - : { - year: 'numeric', - month: 'numeric', - day: 'numeric', - }, - ).format(date) -} diff --git a/packages/plugins/RedPacket/src/SiteAdaptor/utils/reduceUselessPayloadInfo.ts b/packages/plugins/RedPacket/src/SiteAdaptor/utils/reduceUselessPayloadInfo.ts deleted file mode 100644 index b8b3aa414826..000000000000 --- a/packages/plugins/RedPacket/src/SiteAdaptor/utils/reduceUselessPayloadInfo.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { FungibleToken } from '@masknet/web3-shared-base' -import type { ChainId, SchemaType } from '@masknet/web3-shared-evm' -import { type RedPacketJSONPayload } from '@masknet/web3-providers/types' -import { pick, omit } from 'lodash-es' - -export function reduceUselessPayloadInfo(payload: RedPacketJSONPayload): RedPacketJSONPayload { - const token = pick(payload.token, ['decimals', 'symbol', 'address', 'chainId']) as FungibleToken< - ChainId, - SchemaType.Native | SchemaType.ERC20 - > - return { ...omit(payload, ['block_number']), token } -} diff --git a/packages/plugins/RedPacket/src/Worker/database.ts b/packages/plugins/RedPacket/src/Worker/database.ts deleted file mode 100644 index a76e70523845..000000000000 --- a/packages/plugins/RedPacket/src/Worker/database.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { omit } from 'lodash-es' -import type { RedPacketRecord, RedPacketRecordInDatabase } from '@masknet/web3-providers/types' -import type { Plugin } from '@masknet/plugin-infra' - -export let RedPacketDatabase: Plugin.Worker.DatabaseStorage - -export function setupDatabase(x: typeof RedPacketDatabase) { - RedPacketDatabase = x -} - -export async function getAllRedpackets(ids: string[]) { - const records: RedPacketRecord[] = [] - for await (const record of RedPacketDatabase.iterate('red-packet')) { - if (ids.includes(record.value.id)) records.push(RedPacketRecordOutDB(record.value)) - } - return records -} - -export async function getRedPacket(id: string) { - const record = await RedPacketDatabase.get('red-packet', id) - return record ? RedPacketRecordOutDB(record) : undefined -} - -export async function addRedPacket(record: RedPacketRecord) { - return RedPacketDatabase.add(RedPacketRecordIntoDB(record)) -} - -function RedPacketRecordIntoDB(x: RedPacketRecord) { - const record = x as RedPacketRecordInDatabase - record.type = 'red-packet' - return record -} - -function RedPacketRecordOutDB(x: RedPacketRecordInDatabase): RedPacketRecord { - const record = x - return omit(record, ['type']) -} diff --git a/packages/plugins/RedPacket/src/Worker/index.ts b/packages/plugins/RedPacket/src/Worker/index.ts deleted file mode 100644 index 5e6d6cea27fc..000000000000 --- a/packages/plugins/RedPacket/src/Worker/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { Plugin } from '@masknet/plugin-infra' -import { base } from '../base.js' -import { setupDatabase } from './database.js' - -const worker: Plugin.Worker.Definition = { - ...base, - init(signal, context) { - context.startService(import('./services.js')) - setupDatabase(context.getDatabaseStorage()) - }, -} -export default worker diff --git a/packages/plugins/RedPacket/src/Worker/services.ts b/packages/plugins/RedPacket/src/Worker/services.ts deleted file mode 100644 index acc70238df17..000000000000 --- a/packages/plugins/RedPacket/src/Worker/services.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { type RedPacketJSONPayloadFromChain, type RedPacketRecord } from '@masknet/web3-providers/types' -import type { ChainId } from '@masknet/web3-shared-evm' -import * as database from './database.js' - -export async function addRedPacket(record: RedPacketRecord, chainId: ChainId) { - await database.addRedPacket(record) -} - -export async function getRedPacketRecord(txId: string) { - return database.getRedPacket(txId) -} - -export async function getRedPacketHistoryFromDatabase(redpacketsFromChain: RedPacketJSONPayloadFromChain[]) { - // #region Inject password from database - const redpacketsFromDatabase: RedPacketRecord[] = await database.getAllRedpackets( - redpacketsFromChain.map((x) => x.txid), - ) - return redpacketsFromChain.map((x) => { - const record = redpacketsFromDatabase.find((y) => y.id === x.txid) - if (!record) return x - return { - ...x, - password: record.password, - } - }) - // #endregion -} diff --git a/packages/plugins/RedPacket/src/base.ts b/packages/plugins/RedPacket/src/base.ts deleted file mode 100644 index 652975edb7a8..000000000000 --- a/packages/plugins/RedPacket/src/base.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { Plugin } from '@masknet/plugin-infra' -import { DEFAULT_PLUGIN_PUBLISHER, EnhanceableSite, NetworkPluginID, getSiteType } from '@masknet/shared-base' -import { ChainId } from '@masknet/web3-shared-evm' -import { RedPacketMetaKey, RedPacketPluginID } from './constants.js' -import { languages } from './locales/languages.js' - -export const base: Plugin.Shared.Definition = { - ID: RedPacketPluginID, - name: { fallback: 'Lucky Drop' }, - description: { - fallback: - 'Lucky drop is a special feature in Mask Network which was launched in early 2020. Once users have installed the Chrome/Firefox plugin, they can claim and give out cryptocurrencies on Twitter.', - }, - // Won't show publisher on Firefly - publisher: getSiteType() === EnhanceableSite.Firefly ? undefined : DEFAULT_PLUGIN_PUBLISHER, - enableRequirement: { - supports: { - type: 'opt-out', - sites: { - [EnhanceableSite.Localhost]: true, - }, - }, - target: 'stable', - web3: { - [NetworkPluginID.PLUGIN_EVM]: { - supportedChainIds: [ - ChainId.Mainnet, - ChainId.BSC, - ChainId.Polygon, - ChainId.Arbitrum, - ChainId.Base, - ChainId.xDai, - ChainId.Fantom, - ChainId.Optimism, - ChainId.Avalanche, - ChainId.Aurora, - ChainId.Conflux, - ChainId.Astar, - ChainId.Scroll, - ChainId.Metis, - ChainId.XLayer, - ], - }, - [NetworkPluginID.PLUGIN_SOLANA]: { supportedChainIds: [] }, - }, - }, - contribution: { - metadataKeys: new Set([RedPacketMetaKey]), - }, - i18n: languages, -} diff --git a/packages/plugins/RedPacket/src/constants.ts b/packages/plugins/RedPacket/src/constants.ts deleted file mode 100644 index cce294fc421f..000000000000 --- a/packages/plugins/RedPacket/src/constants.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { PluginID } from '@masknet/shared-base' - -// Note: if the latest version has been changed, please update packages/mask/content-script/components/CompositionDialog/useSubmit.ts -/** - * !! Change this key cause a breaking change in the red packet plugin. - * !! Please make sure it also be able to recognize the old key. - */ -export const RedPacketMetaKey = `${PluginID.RedPacket}:1` -/** - * !! This ID is used to identify the stored plugin data. Change it will cause data lost. - */ -export const RedPacketPluginID = PluginID.RedPacket - -export const RED_PACKET_DEFAULT_SHARES = 5 -export const RED_PACKET_MIN_SHARES = 1 -export const RED_PACKET_MAX_SHARES = 255 diff --git a/packages/plugins/RedPacket/src/index.ts b/packages/plugins/RedPacket/src/index.ts deleted file mode 100644 index db57130158f7..000000000000 --- a/packages/plugins/RedPacket/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { openDialog } from './SiteAdaptor/emitter.js' -export * from './constants.js' diff --git a/packages/plugins/RedPacket/src/locales/en-US.json b/packages/plugins/RedPacket/src/locales/en-US.json deleted file mode 100644 index 2ce15e04039e..000000000000 --- a/packages/plugins/RedPacket/src/locales/en-US.json +++ /dev/null @@ -1,183 +0,0 @@ -{ - "amount": "Amount", - "no": "No", - "promote": "🧧🧧🧧 Try sending Lucky Drop to your friends with tokens or NFTs to share the joy now! Install Mask.io to send your first Lucky Drop.", - "promote_short": "🧧🧧🧧 Try sending Lucky Drop to your friends with Mask.io.", - "nft_shift_select_tip": "You can also use {{text}} to select multiple NFTs.", - "collections": "Collections", - "select_a_token": "Select a Token", - "search": "Search", - "loading_token": "Loading token...", - "search_no_result": "No results", - "nfts": "NFTs", - "nft_already_added": "The collectible has already been added.", - "nft_invalid_owner": "The collectible does not belong to you.", - "nft_max_shares": "The maximum number of NFTs to be sold in NFT lucky drop contract is {{- amount}}.", - "nft_max_shares_tip": "The NFT lucky drop supports up to {{amount, number}} NFTs selected for one time.", - "nft_non_existed_tip": "Token ID does not exist or belong to you.", - "nft_select_collection": "Choose your collection", - "nft_select_amount_one": "{{count}} NFT", - "nft_select_amount_other": "{{count}} NFTs", - "completed": "Completed", - "expired": "Expired", - "nft_tip": "This is an NFT lucky drop.", - "account_promote$default": "", - "account_promote$twitter": "Follow @$t(mask:twitter_account) (mask.io) to claim NFT lucky drops.", - "account_promote$facebook": "Follow @$t(mask:facebook_account) (mask.io) to claim NFT lucky drops.", - "nft_share_foreshow_message": "@{{sender}} is sending an NFT lucky drop on {{network}} network. {{account_promote}}\n$t(promote_short)\n$t(mask:hash_tag) #LuckyDrop\n{{payload}}", - "nft_share_claimed_message": "I just claimed an NFT lucky drop from @{{sender}} on {{network}} network. {{account_promote}}\n$t(promote_short)\n$t(mask:hash_tag) #LuckyDrop\n{{payload}}", - "nft_total_amount": "Total Amount", - "nft_attached_message": "Attached Message", - "nft_account_name": "Wallet account", - "message_label": "Enclose a Message", - "claiming": "Claiming...", - "claim": "Claim", - "data_broken": "The Lucky Drop can’t be sent due to data damage. Please withdraw the assets after {{duration}}.", - "refund": "Refund", - "empty": "Empty", - "refunding": "Refunding", - "history_total_amount": "Total Amount: {{- amount}} {{symbol}}", - "history_split_mode": "Split Mode: {{mode}}", - "attached_message": "Attached Message", - "indivisible": "The minimum amount for each share is {{- amount}} {{symbol}}", - "name": "Lucky Drop", - "description": "Gift crypto or NFTs to any users, first come, first served.", - "next": "Create the Lucky Drop", - "nft_approve_all_tip": "Note: When you \"Unlock All\", all of the NFTs in the collection will be by default authorized for sale. This includes the NFTs transferred afterwards.", - "nft_select_partially_option": "Select partially", - "nft_select_all_option": "ALL ({{total}} NFT)", - "nft_search_placeholder": "Token ID separated by comma, e.g. 1224, 7873, 8948", - "erc721_insufficient_balance": "Insufficient Balance", - "erc721_create_lucky_drop": "Create the Lucky Drop", - "erc721_gas_cap": "When selecting too many NFTs, the total gas fee may exceed the MetaMask limit of 1 {{symbol}}. Please reduce the number of NFTs selected.", - "erc721_tab_title": "Collectibles", - "erc20_tab_title": "Tokens", - "sent_tab_title": "Sent", - "claimed_tab_title": "Claimed", - "claimed": "Claimed {{- amount}}", - "received": "Received", - "view": "View", - "creator": "Creator:", - "details": "Confirm the Lucky Drop", - "confirm": "Confirm", - "confirming": "Confirming", - "more_details": "More details", - "enter_each_amount": "Enter Amount Each", - "enter_total_amount": "Enter Total Amount", - "enter_shares": "Enter Number of Winners", - "max_shares": "At most 255 recipients", - "display_name": "Lucky Drop", - "select_existing": "History", - "create_new": "New", - "token_send_symbol": "Send {{- amount}} {{symbol}}", - "send_symbol_one": "Send {{count}} NFT", - "send_symbol_other": "Send {{count}} NFTs", - "insufficient_balance": "Insufficient Balance", - "insufficient_token_balance": "Insufficient {{symbol}} Balance", - "back": "Back", - "hint": "You can withdraw the rest of your balances back 24h later after sending them out.", - "total": "Total", - "total_cost": "Total cost", - "amount_per_share": "Amount per Share", - "amount_each": "Amount Each", - "estimate_gas_fee": "Transaction cost", - "shares": "Shares", - "average": "Identical", - "random": "Random", - "random_amount": "Random Amount", - "identical_amount": "Equal Amount", - "quantity": "Quantity", - "split_mode": "Split Mode", - "token": "Token", - "chain_not_supported": "Not supported on {{chain}} yet.", - "nft_no_history": "You haven't created any NFT lucky drop yet. Try to create and share lucky with your friends.", - "token_no_history": "You haven't created any Token lucky drop yet. Try to create and share lucky with your friends.", - "history_claimed": "Claimed: {{claimedShares}}/{{shares}} {{claimedAmount}}/{{amount}} {{symbol}}", - "history_claimed_firefly": "Claimed: {{claimedShares}}/{{shares}} {{claimedAmount}}/{{amount}} {{symbol}}", - "history_nft_claimed": "Claimed: {{claimedShares}}/{{shares}} {{symbol}}", - "send": "Send", - "history_duration": "{{- time}} (UTC+8)", - "best_wishes": "Best Wishes!", - "enter_quantity": "Enter quantity", - "enter_number_of_winners": "Enter number of winners", - "create_time": "Create time:", - "received_time": "Received time:", - "message": "Message", - "blessing_words": "Best Wishes", - "nft_data_broken": "The Lucky Drop can’t be sent due to data damage.", - "from": "From: @{{name}}", - "share_message_official_account": "I just claimed a lucky drop from @{{sender}} on {{network}} network. Follow @{{account}} (mask.io) to claim lucky drops.\n$t(promote_short)\n#mask_io #LuckyDrop\n{{payload}}", - "share_message_not_twitter": "I just claimed a lucky drop from @{{sender}} on {{network}} network.\n$t(promote_short)\n{{payload}}", - "share_unclaimed_message_official_account": "Hi friends, I just found a lucky drop sent by @{{sender}} on {{network}} network. Follow @{{account}} (mask.io) to claim lucky drops.\n$t(promote_short)\n#mask_io #LuckyDrop\n{{payload}}", - "share_unclaimed_message_not_twitter": "Hi friends, I just found a lucky drop sent by @{{sender}} on {{network}} network.\n$t(promote_short)\n{{payload}}", - "description_claimed": "You got {{- amount}} {{symbol}}", - "description_refund": "You could refund {{- balance}} {{symbol}}.", - "description_refunded": "The Lucky Drop has been refunded.", - "description_expired": "The Lucky Drop is expired.", - "description_broken": "The Lucky Drop is broken.", - "description_empty": "The Lucky Drop is empty.", - "description_failover_one": "{{count}} share / {{- total}} {{symbol}}", - "description_failover_other": "{{count}} shares / {{- total}} {{symbol}}", - "recommend_feature_description": "Send a surprise crypto giveaway. Tokens and NFTs on multiple chains are supported.", - "claim_token_successful": "You claimed {{- amount}} {{name}}.", - "claim_nft_successful": "Claimed 1 {{name}} successfully.", - "lucky_drop": "Lucky Drop", - "share": "Share", - "ok": "OK", - "got_nft": "You got 1 {{name}}", - "history": "History", - "twitter_account": "realMaskNetwork", - "winners": "Winners", - "facebook_account": "masknetwork", - "loading": "Loading", - "plugin_wallet_connect_a_wallet": "Connect Wallet", - "plugin_wallet_invalid_network": "Invalid Network", - "select_all": "Select All", - "retry": "Retry", - "go_wrong": "Something went wrong.", - "total_amount": "Total amount", - "random_amount_share_tips": "Total amount shared among all winners", - "equal_amount_share_tips": "Enter the amount that each winner can claim", - "claim_requirements_tips": "You can set one or multiple rules to be eligible to win a Lucky Drop.", - "claim_requirements_title": "Claim Requirements", - "claim_requirements_rule_tips": "Use Lucky Drop quests to grow your followers and engagement. Each requirement must be completed to be eligible to claim.", - "follow_me": "Follow me", - "follow_me_description": "User must follow your account. Note: When you cross-post a Lucky Drop to multiple social networks, following you on any social allows users to claim.", - "reaction_title": "Like / Repost / Comment", - "reaction_description": "Users must like, repost / quote tweet, or comment on your Lucky Drop post.", - "nft_holder": "NFT holder", - "nft_holder_description": "Users must hold one NFT from the collection you select.", - "repost": "Repost", - "repost$lens": "Mirror", - "repost$twitter": "Repost", - "repost$farcaster": "Repost", - "like": "Like", - "comment": "Comment", - "clear_all_requirements": "Clear all requirements", - "select_nft_collection_to_gate_access": "Select NFT collection to gate access", - "next_button": "Next", - "drop_type": "Drop Type", - "number_of_winners": "Number of Winners", - "share_from": "Share From", - "share_from_tips": "Customize Lucky Drop sender. Select either Lens or Forecaster usernames, or use the currently connected wallet.", - "image_preview": "Image Preview", - "unclaim_tips": "You can withdraw any unclaimed amount 24 hours after sending this lucky drop.", - "create_redpacket_tips": "By clicking \"Next\", you acknowledge the risk associated with decentralized networks and beta products.", - "no_enough_gas_fees": "Insufficient Balance for Gas Fee", - "infinite_unlock_tips": "Grant access to your {{ token }} for the Lucky Drop Smart contract. You only have to do this once per token.", - "requirements": "Requirements", - "follow_somebody_on_somewhere": "Follow {{handles}} on {{ platform }}", - "nft_holder_of": "NFT Holder of {{- names }}", - "share_on_firefly$default": "🤑 Check this Lucky Drop 🧧💰✨ sent by @{{- sender }} .\n\nGrow your followers and engagement with Lucky Drop on Firefly mobile app or http://firefly.mask.social !\n\nClaim on: {{- link }}", - "share_on_firefly$lens": "🤑 Check this Lucky Drop 🧧💰✨ sent by @{{- sender }} .\n\nGrow your followers and engagement with Lucky Drop on Firefly mobile app or http://firefly.mask.social !\n\nClaim on Lens: {{- link }}", - "share_on_firefly$farcaster": "🤑 Check this Lucky Drop 🧧💰✨ sent by @{{- sender }} .\n\nGrow your followers and engagement with Lucky Drop on Firefly mobile app or http://firefly.mask.social !\n\nClaim on Farcaster: {{- link }}", - "share_on_firefly$twitter": "🤑 Check this Lucky Drop 🧧💰✨ sent by @{{- sender }} .\n\nGrow your followers and engagement with Lucky Drop on Firefly mobile app or http://firefly.mask.social !\n\nClaim on Twitter: {{- link }}", - "share_on_firefly$lens_claimed": "🤑 Just claimed a #LuckyDrop 🧧💰✨ on https://firefly.mask.social from @{{- sender }} ! \n\nClaim on Lens: {{- link }}", - "share_on_firefly$farcaster_claimed": "🤑 Just claimed a #LuckyDrop 🧧💰✨ on https://firefly.mask.social from @{{- sender }} ! \n\nClaim on Farcaster: {{- link }}", - "share_on_firefly$twitter_claimed": "🤑 Just claimed a #LuckyDrop 🧧💰✨ on https://firefly.mask.social from @{{- sender }} ! \n\nClaim on Twitter: {{- link }}", - "no_claim_data": "No claims yet for this Lucky Drop", - "no_claim_history_data": "No Lucky Drops claimed", - "no_sent_history_data": "
No Lucky Drops created.
Select 🎁 when you compose a post to start your first drop.
", - "post_on": "Post on", - "connect_to_platform": "Connect to {{ platform }}" -} diff --git a/packages/plugins/RedPacket/src/locales/index.ts b/packages/plugins/RedPacket/src/locales/index.ts deleted file mode 100644 index 5d88b2e093aa..000000000000 --- a/packages/plugins/RedPacket/src/locales/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// This file is auto generated. DO NOT EDIT -// Run `npx gulp sync-languages` to regenerate. -// Default fallback language in a family of languages are chosen by the alphabet order -// To overwrite this, please overwrite packages/scripts/src/locale-kit-next/index.ts - -export * from './i18n_generated.js' diff --git a/packages/plugins/RedPacket/src/locales/ja-JP.json b/packages/plugins/RedPacket/src/locales/ja-JP.json deleted file mode 100644 index d3a8fe181e56..000000000000 --- a/packages/plugins/RedPacket/src/locales/ja-JP.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "account_promote$facebook": "@$t(mask:facebook_account) (mask.io) をフォローしてNFTラッキードロップを受け取ります。", - "nft_share_foreshow_message": "@{{sender}} は {{network}} ネットワークで NFT ラッキードロップを送信しています。 {{account_promote}}\n$t(promote_short)\n$t(mask:hash_tag) #ラッキードロップ\n{{payload}}", - "nft_share_claimed_message": " {{network}} ネットワーク上で{{sender}} からNFTラッキードロップを受け取りました。 {{account_promote}}\n$t(promote_short)\n$t(mask:hash_tag) #ラッキードロップ\n{{payload}}", - "nft_total_amount": "合計金額", - "nft_attached_message": "添付メッセージ", - "nft_account_name": "ウォレットアカウント", - "message_label": "メッセージを閉じる", - "claiming": "受け取り中..", - "claim": "受取る", - "data_broken": "データの損傷のためラッキードロップは送信できません。 {{duration}}後に資産を引き出してください。", - "refund": "返金", - "empty": "空です", - "refunding": "返金処理中", - "history_total_amount": "合計金額: {{- amount}} {{symbol}}", - "history_split_mode": "分割モード: {{mode}}", - "attached_message": "添付メッセージ", - "indivisible": "各株の最小額は {{- amount}} {{symbol}} です", - "name": "ラッキードロップ" -} diff --git a/packages/plugins/RedPacket/src/locales/ko-KR.json b/packages/plugins/RedPacket/src/locales/ko-KR.json deleted file mode 100644 index 0d5d7f4b4e03..000000000000 --- a/packages/plugins/RedPacket/src/locales/ko-KR.json +++ /dev/null @@ -1,124 +0,0 @@ -{ - "promote": "🧧🧧🧧 Mask.io 설치하여 행운 드랍으로 친구에게 토큰이나 NFT를 보내세요!", - "promote_short": "🧧🧧🧧 Mask.io로 친구에게 행운 드랍을 보내세요.", - "nft_shift_select_tip": "{{text}} 이용하여 다양한 NFT를 선택할 수 있습니다.", - "collections": "수집품", - "select_a_token": "토큰 선택", - "search": "검색", - "loading_token": "토큰 로딩...", - "search_no_result": "결과 없음", - "nft_already_added": "이미 추가된 수집품입니다.", - "nft_invalid_owner": "해당 수집품은 유저님의 것이 아닙니다.", - "nft_max_shares": "NFT 행운 드롭 컨트렉트에서 판매되는 NFT의 최대 개수: {{- amount}}", - "nft_max_shares_tip": "한번에 {{amount, number}} NFT를 선택할 수 있습니다.", - "nft_non_existed_tip": " 존재하지 않거나 유저님의 것이 아닙니다.", - "nft_select_collection": "수집품 선택", - "nft_select_amount_one": "{{count}} NFT", - "nft_select_amount_other": "{{count}} NFTs", - "completed": "완료됨", - "expired": "만료됨", - "nft_tip": "NFT 행운 드랍", - "account_promote$twitter": "@$t(mask:twitter_account) (mask.io) 팔로우하여 에어드랍을 수령합니다.", - "account_promote$facebook": "@$t(mask:facebook_account) (mask.io) 팔로우하여 행운 드랍을 수령합니다.", - "nft_share_foreshow_message": "@{{sender}} 님이 {{network}} 네트워크에서 행운 드랍을 발송하고 있습니다. {{account_promote}}\n$t(promote_short)\n$t(mask:hash_tag) #LuckyDrop\n{{payload}}", - "nft_share_claimed_message": "@{{sender}} 님이 {{network}} 네트워크에서 발송한 NFT행운 드랍을 수령했습니다. {{account_promote}}\n$t(promote_short)\n$t(mask:hash_tag) #LuckyDrop\n{{payload}}", - "nft_total_amount": "총액", - "nft_attached_message": "첨부 메시지", - "nft_account_name": "월렛 계정", - "message_label": "메시지 동봉", - "claiming": "수령 중...", - "claim": "수령", - "data_broken": "데이터 손상으로 인해 레드 패킷을 보낼 수 없습니다. {{duration}} 후 자산을 인출할 수 있습니다.", - "refund": "리펀", - "empty": "비어 있음", - "refunding": "환급 중", - "history_total_amount": "총액: {{- amount}} {{symbol}}", - "history_split_mode": "Split Mode: {{mode}}", - "attached_message": "첨부 메시지", - "indivisible": "한 지분의 최저 수액은 {{- amount}} {{symbol}} 입니다.", - "name": "행운 드랍", - "description": "크립토나 NFT를 다른 이용자에게 보낼 수 있습니다.", - "next": "다음", - "nft_approve_all_tip": "주의: \"모두 언락\"을 하면 컬렉션의 모든 NFT는 기본적으로 판매 승인을 받습니다. 여기에는 이후에 전송된 NFT가 포함됩니다.", - "nft_select_partially_option": "일부 선택", - "nft_select_all_option": "모든 ({{total}} NFT)", - "nft_search_placeholder": "토큰 ID는 쉽표로 분리됩니다. 예시: 1224, 7873, 8948", - "erc721_insufficient_balance": "잔액 부족", - "erc721_create_lucky_drop": "행운 드랍 만들기", - "erc721_gas_cap": "NFT를 너무 많이 선택할 경우 총 가스 요금이 MetaMask 한도인 1 {{symbol}} 을(를) 초과할 수 있습니다. 선택한 NFT 수를 줄이세요.", - "erc721_tab_title": "수집품", - "erc20_tab_title": "토큰", - "claimed": "{{- amount}} Claimed", - "details": "행운 드랍 디테일", - "confirm": "확인", - "confirming": "확인 중", - "enter_each_amount": "하나의 금액 입력", - "enter_total_amount": "총금액 입력", - "enter_shares": "공유 수량 입력", - "max_shares": "최대 255명까지 받을 수 있습니다", - "display_name": "행운 드랍", - "select_existing": "역사 기록", - "create_new": "새로", - "token_send_symbol": "{{- amount}} {{symbol}} 발송", - "send_symbol_one": "{{count}} NFT 발송", - "send_symbol_other": "{{count}} NFTs 발송", - "insufficient_balance": "잔액 부족", - "insufficient_token_balance": "{{symbol}} 잔액 부족", - "back": "뒤로", - "hint": "행운 드롭을 발송한 후 24시간 후에 남은 자금을 인출할 수 있습니다.", - "total": "전체", - "total_cost": "총 비용", - "amount_per_share": "한 지분 금액", - "amount_each": "하나의 금액", - "estimate_gas_fee": "예상 가스비", - "shares": "Shares", - "average": "평균", - "random": "렌덤", - "random_amount": "랜덤 금액", - "identical_amount": "동일한 금액", - "quantity": "수량", - "split_mode": "스플릿 모드", - "token": "토큰", - "chain_not_supported": "{{chain}} 아직 지원하지 않습니다.", - "nft_no_history": "생성된 NFT 행운 드랍이 없습니다. 행운 드랍을 만들고 친구들에게 행운을 공유하세요.", - "token_no_history": "생성된 토큰 행운 드랍이 없습니다. 행운 드랍을 만들고 친구들에게 행운을 공유하세요.", - "history_claimed": "수령됨: {{claimedShares}}/{{shares}} 공유", - "history_nft_claimed": "Claimed: {{claimedShares}}/{{shares}} {{symbol}}", - "send": "발송", - "history_duration": "시간: {{- startTime}} ~ {{- endTime}} (UTC+8)", - "best_wishes": "행운을 빌어요!", - "enter_quantity": "수량 입력", - "create_time": "생성 시간:", - "blessing_words": "덕담", - "nft_data_broken": "테이터 훼손때문에 행운 드랍을 보낼 수 없습니다.", - "from": "시작: @{{name}}", - "share_message_official_account": "{{network}} 네트워크에서 @{{sender}}의 행운 드랍을 받았어요. @{{account}} (mask.io) 팔로우하고 행운 드랍을 받으세요.\n$t(promote_short)\n#mask_io #LuckyDrop\n{{payload}}", - "share_message_not_twitter": "@{{sender}} 님이 {{network}} 네트워크에서 발송한 Nft행운 드랍을 수령했습니다. \n$t(promote_short)\n{{payload}}", - "share_unclaimed_message_official_account": "방금 {{network}} 네트워크에서 @{{sender}}님이 발송한 행운 드랍을 찾았어요. @{{account}} (mask.io) 팔로우하고 행운 드랍을 받으세요.\n$t(promote_short)\n#mask_io #LuckyDrop\n{{payload}}", - "share_unclaimed_message_not_twitter": "방금 {{network}} 네트워크에서 @{{sender}} 님이 발송한 행운 드랍을 찾았어요.\n$t(promote_short)\n{{payload}}", - "description_claimed": "{{- amount}} {{symbol}} 수령됨", - "description_refund": "{{- balance}} {{symbol}} 리펀 가능합니다.", - "description_refunded": "행운 드랍은 이미 리펀됩니다.", - "description_expired": "만료된 행운 드랍", - "description_broken": "훼손된 행운 드랍", - "description_empty": "비어 있는 행운 드랍", - "description_failover_one": "{{count}} 개 / {{- total}} {{symbol}}", - "description_failover_other": "{{count}} 개 / {{- total}} {{symbol}}", - "recommend_feature_description": "사프라이즈 트큰과 NFT 선물을 보내세요. 다양한 체인을 지원합니다.", - "claim_token_successful": "{{- amount}} {{name}} 수령되었습니다.", - "claim_nft_successful": "{{name}} 1 개가 수령되었습니다.", - "lucky_drop": "행운 드랍", - "share": "공유", - "ok": "확인", - "got_nft": "{{name}} 하나를 받았습니다.", - "history": "역사 기록", - "twitter_account": "realMaskNetwork", - "facebook_account": "masknetwork", - "loading": "로딩 중", - "plugin_wallet_connect_a_wallet": "월렛 연결", - "plugin_wallet_invalid_network": "잘못된 네트워크", - "select_all": "전체 선택", - "retry": "다시 시도", - "go_wrong": "오류가 발생합니다.", - "no_enough_gas_fees": "가스비 부족" -} diff --git a/packages/plugins/RedPacket/src/locales/languages.ts b/packages/plugins/RedPacket/src/locales/languages.ts deleted file mode 100644 index e8cd5a8b1cd5..000000000000 --- a/packages/plugins/RedPacket/src/locales/languages.ts +++ /dev/null @@ -1,34 +0,0 @@ -// This file is auto generated. DO NOT EDIT -// Run `npx gulp sync-languages` to regenerate. -// Default fallback language in a family of languages are chosen by the alphabet order -// To overwrite this, please overwrite packages/scripts/src/locale-kit-next/index.ts -import en_US from './en-US.json' -import ja_JP from './ja-JP.json' -import ko_KR from './ko-KR.json' -import qya_AA from './qya-AA.json' -import zh_CN from './zh-CN.json' -import zh_TW from './zh-TW.json' -export const languages = { - en: en_US, - ja: ja_JP, - ko: ko_KR, - qy: qya_AA, - 'zh-CN': zh_CN, - zh: zh_TW, -} -// @ts-ignore -if (import.meta.webpackHot) { - // @ts-ignore - import.meta.webpackHot.accept( - ['./en-US.json', './ja-JP.json', './ko-KR.json', './qya-AA.json', './zh-CN.json', './zh-TW.json'], - () => - globalThis.dispatchEvent?.( - new CustomEvent('MASK_I18N_HMR', { - detail: [ - 'com.maskbook.red_packet', - { en: en_US, ja: ja_JP, ko: ko_KR, qy: qya_AA, 'zh-CN': zh_CN, zh: zh_TW }, - ], - }), - ), - ) -} diff --git a/packages/plugins/RedPacket/src/locales/qya-AA.json b/packages/plugins/RedPacket/src/locales/qya-AA.json deleted file mode 100644 index c4353bc865f0..000000000000 --- a/packages/plugins/RedPacket/src/locales/qya-AA.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "promote": "crwdns16732:0crwdne16732:0", - "promote_short": "crwdns16734:0crwdne16734:0", - "nft_shift_select_tip": "crwdns16736:0{{text}}crwdne16736:0", - "collections": "crwdns16738:0crwdne16738:0", - "select_a_token": "crwdns16740:0crwdne16740:0", - "search": "crwdns16742:0crwdne16742:0", - "loading_token": "crwdns16744:0crwdne16744:0", - "search_no_result": "crwdns16746:0crwdne16746:0", - "nft_already_added": "crwdns16748:0crwdne16748:0", - "nft_invalid_owner": "crwdns16750:0crwdne16750:0", - "nft_max_shares": "crwdns16752:0{{- amount}}crwdne16752:0", - "nft_max_shares_tip": "crwdns16754:0amount={amount}crwdne16754:0", - "nft_non_existed_tip": "crwdns16756:0crwdne16756:0", - "nft_select_collection": "crwdns16758:0crwdne16758:0", - "nft_select_amount_one": "crwdns18544:0{{count}}crwdne18544:0", - "nft_select_amount_other": "crwdns18546:0{{count}}crwdne18546:0", - "completed": "crwdns16760:0crwdne16760:0", - "expired": "crwdns16762:0crwdne16762:0", - "nft_tip": "crwdns16764:0crwdne16764:0", - "account_promote$default": "crwdns17284:0crwdne17284:0", - "account_promote$twitter": "crwdns17286:0$t(mask:twitter_account)crwdne17286:0", - "account_promote$facebook": "crwdns17288:0$t(mask:facebook_account)crwdne17288:0", - "nft_share_foreshow_message": "crwdns16768:0{{sender}}crwdnd16768:0{{network}}crwdnd16768:0{{account_promote}}crwdnd16768:0$t(promote_short)crwdnd16768:0$t(mask:hash_tag)crwdnd16768:0{{payload}}crwdne16768:0", - "nft_share_claimed_message": "crwdns16772:0{{sender}}crwdnd16772:0{{network}}crwdnd16772:0{{account_promote}}crwdnd16772:0$t(promote_short)crwdnd16772:0$t(mask:hash_tag)crwdnd16772:0{{payload}}crwdne16772:0", - "nft_total_amount": "crwdns16774:0crwdne16774:0", - "nft_attached_message": "crwdns16776:0crwdne16776:0", - "nft_account_name": "crwdns16778:0crwdne16778:0", - "message_label": "crwdns16780:0crwdne16780:0", - "claiming": "crwdns16782:0crwdne16782:0", - "claim": "crwdns16784:0crwdne16784:0", - "data_broken": "crwdns16786:0{{duration}}crwdne16786:0", - "refund": "crwdns16788:0crwdne16788:0", - "empty": "crwdns16790:0crwdne16790:0", - "refunding": "crwdns16792:0crwdne16792:0", - "history_total_amount": "crwdns16796:0{{- amount}}crwdnd16796:0{{symbol}}crwdne16796:0", - "history_split_mode": "crwdns16798:0{{mode}}crwdne16798:0", - "attached_message": "crwdns16802:0crwdne16802:0", - "indivisible": "crwdns16804:0{{- amount}}crwdnd16804:0{{symbol}}crwdne16804:0", - "name": "crwdns16806:0crwdne16806:0", - "description": "crwdns16808:0crwdne16808:0", - "next": "crwdns16810:0crwdne16810:0", - "nft_approve_all_tip": "crwdns16812:0crwdne16812:0", - "nft_select_partially_option": "crwdns16816:0crwdne16816:0", - "nft_select_all_option": "crwdns16818:0{{total}}crwdne16818:0", - "nft_search_placeholder": "crwdns18548:0crwdne18548:0", - "erc721_insufficient_balance": "crwdns16820:0crwdne16820:0", - "erc721_create_lucky_drop": "crwdns19993:0crwdne19993:0", - "erc721_gas_cap": "crwdns19995:0{{symbol}}crwdne19995:0", - "erc721_tab_title": "crwdns16822:0crwdne16822:0", - "erc20_tab_title": "crwdns16824:0crwdne16824:0", - "claimed": "crwdns16826:0{{- amount}}crwdne16826:0", - "details": "crwdns16828:0crwdne16828:0", - "confirm": "crwdns20547:0crwdne20547:0", - "confirming": "crwdns20549:0crwdne20549:0", - "enter_each_amount": "crwdns20241:0crwdne20241:0", - "enter_total_amount": "crwdns20243:0crwdne20243:0", - "enter_shares": "crwdns20191:0crwdne20191:0", - "max_shares": "crwdns20193:0crwdne20193:0", - "display_name": "crwdns16830:0crwdne16830:0", - "select_existing": "crwdns16832:0crwdne16832:0", - "create_new": "crwdns16834:0crwdne16834:0", - "token_send_symbol": "crwdns18550:0{{- amount}}crwdnd18550:0{{symbol}}crwdne18550:0", - "send_symbol_one": "crwdns18552:0{{count}}crwdne18552:0", - "send_symbol_other": "crwdns18554:0{{count}}crwdne18554:0", - "insufficient_balance": "crwdns18176:0crwdne18176:0", - "insufficient_token_balance": "crwdns20195:0{{symbol}}crwdne20195:0", - "back": "crwdns16838:0crwdne16838:0", - "hint": "crwdns16840:0crwdne16840:0", - "total": "crwdns20245:0crwdne20245:0", - "total_cost": "crwdns20375:0crwdne20375:0", - "amount_per_share": "crwdns16844:0crwdne16844:0", - "amount_each": "crwdns20247:0crwdne20247:0", - "estimate_gas_fee": "crwdns18178:0crwdne18178:0", - "shares": "crwdns16846:0crwdne16846:0", - "average": "crwdns16848:0crwdne16848:0", - "random": "crwdns16850:0crwdne16850:0", - "random_amount": "crwdns20249:0crwdne20249:0", - "identical_amount": "crwdns20251:0crwdne20251:0", - "quantity": "crwdns20253:0crwdne20253:0", - "split_mode": "crwdns16852:0crwdne16852:0", - "token": "crwdns16854:0crwdne16854:0", - "chain_not_supported": "crwdns16856:0{{chain}}crwdne16856:0", - "nft_no_history": "crwdns16858:0crwdne16858:0", - "token_no_history": "crwdns18264:0crwdne18264:0", - "history_claimed": "crwdns16860:0{{claimedShares}}crwdnd16860:0{{shares}}crwdnd16860:0{{claimedAmount}}crwdnd16860:0{{amount}}crwdnd16860:0{{symbol}}crwdne16860:0", - "history_nft_claimed": "crwdns20255:0{{claimedShares}}crwdnd20255:0{{shares}}crwdnd20255:0{{symbol}}crwdne20255:0", - "send": "crwdns16862:0crwdne16862:0", - "history_duration": "crwdns16864:0{{- time}}crwdne16864:0", - "best_wishes": "crwdns16866:0crwdne16866:0", - "enter_quantity": "crwdns20275:0crwdne20275:0", - "create_time": "crwdns20257:0crwdne20257:0", - "blessing_words": "crwdns20259:0crwdne20259:0", - "nft_data_broken": "crwdns16868:0crwdne16868:0", - "from": "crwdns16870:0{{name}}crwdne16870:0", - "share_message_official_account": "crwdns16872:0{{sender}}crwdnd16872:0{{network}}crwdnd16872:0{{account}}crwdnd16872:0$t(promote_short)crwdnd16872:0{{payload}}crwdne16872:0", - "share_message_not_twitter": "crwdns16874:0{{sender}}crwdnd16874:0{{network}}crwdnd16874:0$t(promote_short)crwdnd16874:0{{payload}}crwdne16874:0", - "share_unclaimed_message_official_account": "crwdns16876:0{{sender}}crwdnd16876:0{{network}}crwdnd16876:0{{account}}crwdnd16876:0$t(promote_short)crwdnd16876:0{{payload}}crwdne16876:0", - "share_unclaimed_message_not_twitter": "crwdns16878:0{{sender}}crwdnd16878:0{{network}}crwdnd16878:0$t(promote_short)crwdnd16878:0{{payload}}crwdne16878:0", - "description_claimed": "crwdns16880:0{{- amount}}crwdnd16880:0{{symbol}}crwdne16880:0", - "description_refund": "crwdns16882:0{{- balance}}crwdnd16882:0{{symbol}}crwdne16882:0", - "description_refunded": "crwdns16884:0crwdne16884:0", - "description_expired": "crwdns16886:0crwdne16886:0", - "description_broken": "crwdns16888:0crwdne16888:0", - "description_empty": "crwdns16890:0crwdne16890:0", - "description_failover_one": "crwdns19873:0{{count}}crwdnd19873:0{{- total}}crwdnd19873:0{{symbol}}crwdne19873:0", - "description_failover_other": "crwdns19875:0{{count}}crwdnd19875:0{{- total}}crwdnd19875:0{{symbol}}crwdne19875:0", - "recommend_feature_description": "crwdns16894:0crwdne16894:0", - "claim_token_successful": "crwdns19839:0{{- amount}}crwdnd19839:0{{name}}crwdne19839:0", - "claim_nft_successful": "crwdns19841:0{{name}}crwdne19841:0", - "lucky_drop": "crwdns19843:0crwdne19843:0", - "share": "crwdns19845:0crwdne19845:0", - "ok": "crwdns19847:0crwdne19847:0", - "got_nft": "crwdns19849:0{{name}}crwdne19849:0", - "history": "crwdns20269:0crwdne20269:0", - "twitter_account": "crwdns21465:0crwdne21465:0", - "facebook_account": "crwdns21467:0crwdne21467:0", - "loading": "crwdns21469:0crwdne21469:0", - "plugin_wallet_connect_a_wallet": "crwdns21471:0crwdne21471:0", - "plugin_wallet_invalid_network": "crwdns21473:0crwdne21473:0", - "select_all": "crwdns21475:0crwdne21475:0", - "retry": "crwdns21477:0crwdne21477:0", - "go_wrong": "crwdns21479:0crwdne21479:0", - "no_enough_gas_fees": "crwdns21481:0crwdne21481:0" -} diff --git a/packages/plugins/RedPacket/src/locales/zh-CN.json b/packages/plugins/RedPacket/src/locales/zh-CN.json deleted file mode 100644 index 28c465f802f3..000000000000 --- a/packages/plugins/RedPacket/src/locales/zh-CN.json +++ /dev/null @@ -1,124 +0,0 @@ -{ - "promote": "🧧🧧🧧 尝试给你的好友发送代币或 NFT 红包,分享此时的喜悦吧! 安装 Mask.io 发送你的第一个红包。", - "promote_short": "🧧🧧🧧试着用Mask.io发送红包给你的朋友。", - "nft_shift_select_tip": "您也可以长按 {{text}} 来选择多个NFT。", - "collections": "NFT 系列", - "select_a_token": "选择代币", - "search": "搜索", - "loading_token": "正在加载代币...", - "search_no_result": "没有任何结果。", - "nft_already_added": "此 NFT 已被添加。", - "nft_invalid_owner": "此收藏品不属于您。", - "nft_max_shares": "NFT红包合约最多支持 {{amount}} 个NFT投放。", - "nft_max_shares_tip": "NFT红包合约最多支持 {{amount, number}} 个NFT投放。", - "nft_non_existed_tip": "Token ID 不存在或不属于您。", - "nft_select_collection": "选择您的 NFT 系列", - "nft_select_amount_one": "{{count}} NFT", - "nft_select_amount_other": "{{count}} NFTs", - "completed": "已完成", - "expired": "已过期", - "nft_tip": "这是一个 NFT 红包。", - "account_promote$twitter": "关注 @$t(mask:twitter_account) (mask.io) 来认领NFT红包。", - "account_promote$facebook": "关注 @$t(mask:facebook_account) (mask.io) 来认领NFT红包。", - "nft_share_foreshow_message": "@{{sender}} 正在 {{network}} 网络上发送一个 NFT 红包。{{account_promote}}\n$t(promote_short)\n$t(mask:hash_tag) #LuckyDrop\n{{payload}}", - "nft_share_claimed_message": "我刚从@{{sender}} 在 {{network}} 网络上认领了一个 NFT 红包。{{account_promote}}\n$t(promote_short)\n$t(mask:hash_tag) #LuckyDrop\n{{payload}}", - "nft_total_amount": "总数", - "nft_attached_message": "附加信息", - "nft_account_name": "钱包账户", - "message_label": "标题", - "claiming": "认领中...", - "claim": "认领", - "data_broken": "由于数据损坏,此红包无法发送。请在 {{duration}} 之后申请退款。", - "refund": "退款", - "empty": "空的", - "refunding": "退款中", - "history_total_amount": "总额: {{- amount}} {{symbol}}", - "history_split_mode": "分享模式:{{mode}}", - "attached_message": "附加信息", - "indivisible": "每个份额的最小金额为 {{- amount}} {{symbol}}", - "name": "红包", - "description": "给任意用户发送Token或者NFT,先到先得", - "next": "下一步", - "nft_approve_all_tip": "注意:在选择批准所有NFT时,合约中的所有NFT都将被授权默认销售,包括随后转移的NFT。", - "nft_select_partially_option": "选择部分", - "nft_select_all_option": "全部 ({{total}} NFT)", - "nft_search_placeholder": "Token ID可用逗号分隔,例如:1224, 7873", - "erc721_insufficient_balance": "余额不足", - "erc721_create_lucky_drop": "创建一个红包", - "erc721_gas_cap": "当选择过多的 NFT时,总气费可能超过 1 {{symbol}} 的 Metamask 限制。请减少选中的 NFT数量。", - "erc721_tab_title": "NFT", - "erc20_tab_title": "代币", - "claimed": "已认领 {{- amount}}", - "details": "红包详情", - "confirm": "确定", - "confirming": "确认中", - "enter_each_amount": "输入每个金额", - "enter_total_amount": "输入总数", - "enter_shares": "输入份数", - "max_shares": "最多255个领取者", - "display_name": "红包", - "select_existing": "历史", - "create_new": "新建", - "token_send_symbol": "发送 {{- amount}} {{symbol}}", - "send_symbol_one": "发送 {{count}} NFT", - "send_symbol_other": "发送 {{count}} NFT", - "insufficient_balance": "余额不足", - "insufficient_token_balance": "{{symbol}} 余额不足", - "back": "返回", - "hint": "您可以在发送红包24小时后提取红包余额。", - "total": "总额", - "total_cost": "总花费", - "amount_per_share": "单个红包数额", - "amount_each": "每个金额", - "estimate_gas_fee": "预估 Gas 费用", - "shares": "份额", - "average": "平分", - "random": "随机", - "random_amount": "随机金额", - "identical_amount": "等价金额", - "quantity": "数量", - "split_mode": "拆分模式", - "token": "代币", - "chain_not_supported": "尚未在 {{chain}} 上支持。", - "nft_no_history": "您还没有创建任何NFT红包。尝试创建红包并与您的朋友分享。", - "token_no_history": "您还没有创建任何代币红包。尝试创建红包并与您的朋友分享。", - "history_claimed": "已认领: {{claimedShares}}/{{shares}} 份额", - "history_nft_claimed": "已认领: {{claimedShares}}/{{shares}} {{symbol}}", - "send": "发送", - "history_duration": "{{- time}} (UTC+8)", - "best_wishes": "最好的祝福!", - "enter_quantity": "请输入红包个数", - "create_time": "创建时间:", - "blessing_words": "祝福语", - "nft_data_broken": "由于数据损坏,红包无法发送。", - "from": "来自:@{{name}}", - "share_message_official_account": "我刚从@{{sender}} 在 {{network}} 网络上认领了一个红包。关注@{{account}} (mask.io) 来获取红包。\n$t(promote_short)\n#mask_io #LuckyDrop\n{{payload}}", - "share_message_not_twitter": "我刚从@{{sender}} 在 {{network}} 网络上认领了一个红包。\n$t(promote_short)\n{{payload}}", - "share_unclaimed_message_official_account": "朋友们,我刚刚发现 @{{sender}} 在 {{network}} 网络发送了一个红包。 关注 @{{account}} (mask.io) 以获取红包。\n#mask_io #LuckyDrop\n{{payload}}", - "share_unclaimed_message_not_twitter": "我刚从@{{sender}} 在 {{network}} 网络上认领了一个红包。\n$t(promote_short)\n{{payload}}", - "description_claimed": "你获得了 {{- amount}} {{symbol}}", - "description_refund": "您可以退款 {{- balance}} {{symbol}}。", - "description_refunded": "此红包已退款。", - "description_expired": "此红包已过期。", - "description_broken": "此红包已被损坏。", - "description_empty": "此红包是空的。", - "description_failover_one": "{{count}} 分享 / {{- total}} {{symbol}}", - "description_failover_other": "{{count}} 分享 / {{- total}} {{symbol}}", - "recommend_feature_description": "发送一个惊喜的加密货币红包。支持多个链上的代币和 NFT。", - "claim_token_successful": "你领取了{{- amount}} {{name}}。", - "claim_nft_successful": "成功领取了 1 {{name}}。", - "lucky_drop": "红包", - "share": "分享", - "ok": "确定", - "got_nft": "你得到了 {{name}}", - "history": "历史", - "twitter_account": "realMaskNetwork", - "facebook_account": "masknetwork", - "loading": "加载中", - "plugin_wallet_connect_a_wallet": "连接钱包", - "plugin_wallet_invalid_network": "网络无效", - "select_all": "全选", - "retry": "重试", - "go_wrong": "出现了一些问题。", - "no_enough_gas_fees": "没有足够的 Gas 费" -} diff --git a/packages/plugins/RedPacket/src/locales/zh-TW.json b/packages/plugins/RedPacket/src/locales/zh-TW.json deleted file mode 100644 index 9d5477d36fb9..000000000000 --- a/packages/plugins/RedPacket/src/locales/zh-TW.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "search": "搜尋", - "nft_already_added": "此收藏品已被添加", - "nft_invalid_owner": "此藏品不屬於你", - "completed": "已完成", - "expired": "已過期", - "nft_tip": "這是一個NFT紅包", - "nft_total_amount": "總額", - "nft_attached_message": "附加的訊息", - "message_label": "標題", - "claiming": "認領中...", - "claim": "認領", - "refund": "退款", - "empty": "空的", - "refunding": "退款中", - "history_total_amount": "總額: {{amount}} {{symbol}}", - "history_split_mode": "分割模式: {{mode}}", - "attached_message": "附加的訊息", - "next": "下一步", - "erc721_insufficient_balance": "餘額不足", - "erc20_tab_title": "代幣", - "claimed": "已領取", - "details": "紅包詳情" -} diff --git a/packages/plugins/RedPacket/src/messages.ts b/packages/plugins/RedPacket/src/messages.ts deleted file mode 100644 index a6d159e1af59..000000000000 --- a/packages/plugins/RedPacket/src/messages.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { RedPacketPluginID } from './constants.js' -import { getPluginRPC } from '@masknet/plugin-infra' - -import.meta.webpackHot?.accept() -export const RedPacketRPC = getPluginRPC(RedPacketPluginID) diff --git a/packages/plugins/RedPacket/src/register.ts b/packages/plugins/RedPacket/src/register.ts deleted file mode 100644 index aa1f8a4cd9d5..000000000000 --- a/packages/plugins/RedPacket/src/register.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { registerPlugin } from '@masknet/plugin-infra' -import { base } from './base.js' - -registerPlugin({ - ...base, - SiteAdaptor: { - load: () => import('./SiteAdaptor/index.js'), - hotModuleReload: (hot) => - import.meta.webpackHot?.accept('./SiteAdaptor', () => hot(import('./SiteAdaptor/index.js'))), - }, - Worker: { - load: () => import('./Worker/index.js'), - hotModuleReload: (hot) => import.meta.webpackHot?.accept('./Worker', () => hot(import('./Worker/index.js'))), - }, -}) diff --git a/packages/plugins/RedPacket/src/schema.json b/packages/plugins/RedPacket/src/schema.json deleted file mode 100644 index 2afb36d69a08..000000000000 --- a/packages/plugins/RedPacket/src/schema.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "type": "object", - "additionalProperties": true, - "properties": { - "contract_address": { - "type": "string", - "title": "contract_address" - }, - "rpid": { - "type": "string", - "title": "rpid" - }, - "txid": { - "type": "string", - "title": "txid" - }, - "password": { - "type": "string", - "title": "password" - }, - "shares": { - "type": "number", - "title": "shares" - }, - "sender": { - "type": "object", - "additionalProperties": true, - "properties": { - "address": { - "type": "string", - "title": "address" - }, - "name": { - "type": "string", - "title": "name" - }, - "message": { - "type": "string", - "title": "message" - } - }, - "required": ["address", "message", "name"], - "title": "sender" - }, - "is_random": { - "type": "boolean", - "title": "is_random" - }, - "total": { - "type": "string", - "title": "total" - }, - "creation_time": { - "type": "number", - "title": "creation_time" - }, - "duration": { - "type": "number", - "title": "duration" - }, - "network": { - "type": "string", - "title": "network" - }, - "token": { - "type": "object", - "additionalProperties": true, - "properties": { - "address": { - "description": "token address", - "type": "string", - "title": "address" - }, - "name": { - "description": "token name", - "type": "string", - "title": "name" - }, - "decimals": { - "description": "token decimal", - "type": "number", - "title": "decimals" - }, - "symbol": { - "description": "token symbol", - "type": "string", - "title": "symbol" - } - }, - "required": ["address"], - "title": "token" - } - }, - "required": ["contract_address", "creation_time", "duration", "is_random", "rpid", "sender", "shares", "total"] -} diff --git a/packages/plugins/RedPacket/src/types.ts b/packages/plugins/RedPacket/src/types.ts deleted file mode 100644 index c06631ce6d98..000000000000 --- a/packages/plugins/RedPacket/src/types.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { ChainId } from '@masknet/web3-shared-evm' - -export enum NFTSelectOption { - All = 'All', - Partial = 'Partial', -} - -export enum RequirementType { - Follow = 'Follow', - Like = 'Like', - Repost = 'Repost', - Comment = 'Comment', - NFTHolder = 'NFTHolder', -} - -export type FireflyRedpacketSettings = { - requirements: RequirementType[] - nftHolderContract?: string - nftCollectionName?: string - nftChainId?: ChainId -} - -export type FireflySocialProfile = { - profileId: string - displayName: string - handle: string - fullHandle: string - pfp: string - address?: string - ownedBy?: string -} - -export interface FireflyContext { - currentLensProfile?: FireflySocialProfile | null - currentFarcasterProfile?: FireflySocialProfile | null - currentTwitterProfile?: FireflySocialProfile | null -} - -export enum FireflyAccountSource { - Lens = 'Lens', - Farcaster = 'Farcaster', - Wallet = 'Wallet', -} diff --git a/packages/plugins/RedPacket/tsconfig.json b/packages/plugins/RedPacket/tsconfig.json deleted file mode 100644 index 2cf6c74bcc6c..000000000000 --- a/packages/plugins/RedPacket/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "../tsconfig.used.json", - "compilerOptions": { - "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/.tsbuildinfo" - }, - "include": ["src", "src/**/*.json"], - "references": [ - { "path": "../../plugin-infra/tsconfig.json" }, - { "path": "../../shared-base/tsconfig.json" }, - { "path": "../../web3-hooks/evm/tsconfig.json" }, - { "path": "../../shared/tsconfig.json" } - ] -} diff --git a/packages/plugins/tsconfig.json b/packages/plugins/tsconfig.json index 5f1852fedd5f..14d75ddd1f18 100644 --- a/packages/plugins/tsconfig.json +++ b/packages/plugins/tsconfig.json @@ -1,4 +1,3 @@ { - "extends": "../../tsconfig.leaf.json", - "references": [{ "path": "./RedPacket/tsconfig.json" }] + "extends": "../../tsconfig.leaf.json" } diff --git a/packages/shared-base/src/types/PluginID.ts b/packages/shared-base/src/types/PluginID.ts index fd0a2dd1dc67..0e2f08f0a024 100644 --- a/packages/shared-base/src/types/PluginID.ts +++ b/packages/shared-base/src/types/PluginID.ts @@ -12,14 +12,5 @@ export enum NetworkPluginID { export enum PluginID { EVM = 'com.mask.evm', Solana = 'com.mask.solana', - Avatar = 'com.maskbook.avatar', - Collectible = 'com.maskbook.collectibles', - Handle = 'com.maskbook.handle', - NextID = 'com.mask.next_id', RedPacket = 'com.maskbook.red_packet', - Wallet = 'com.maskbook.wallet', - Web3Profile = 'io.mask.web3-profile', - Web3ProfileCard = 'io.mask.web3-profile-card', - SmartPay = 'com.mask.smart-pay', - WalletService = 'com.mask.WalletService', } diff --git a/packages/web3-providers/src/Chainbase/apis/RedPacketAPI.ts b/packages/web3-providers/src/Chainbase/apis/RedPacketAPI.ts deleted file mode 100644 index 9f0673bb3608..000000000000 --- a/packages/web3-providers/src/Chainbase/apis/RedPacketAPI.ts +++ /dev/null @@ -1,76 +0,0 @@ -import urlcat from 'urlcat' -import { type Transaction } from '@masknet/web3-shared-base' -import { - asyncIteratorToArray, - createIndicator, - createNextIndicator, - createPageable, - pageableToIterator, -} from '@masknet/shared-base' -import { ChainId, type SchemaType } from '@masknet/web3-shared-evm' -import { TRANSACTIONS_BY_CONTRACT_METHOD_ENDPOINT, MAX_SIZE_PER_PAGE } from '../constants.js' -import type { Tx } from '../types.js' -import { fetchJSON } from '../../helpers/fetchJSON.js' -import type { RedPacketBaseAPI } from '../../entry-types.js' - -export class ChainbaseRedPacketAPI implements RedPacketBaseAPI.Provider { - /** - * @see https://docs.chainbase.com/reference/supported-chains - */ - static isSupportedChain(chainId: ChainId) { - const supported = [ - ChainId.Mainnet, - ChainId.Polygon, - ChainId.BSC, - ChainId.Avalanche, - ChainId.Arbitrum, - ChainId.Base, - /** zkSync */ 324, - ].includes(chainId) - console.error('Unsupported chain by ChainBase, see https://docs.chainbase.com/reference/supported-chains') - return supported - } - static async getHistoryTransactions( - chainId: ChainId, - senderAddress: string, - contractAddress: string, - methodId: string, - ): Promise> | undefined> { - const txes = await asyncIteratorToArray( - pageableToIterator(async (indicator) => { - const { records } = await fetchJSON<{ records: { data: { result: Tx[] } } }>( - urlcat(TRANSACTIONS_BY_CONTRACT_METHOD_ENDPOINT, { - senderAddress, - contractAddress, - chainId, - methodId: `${methodId}%`, // '%' for sql string match. - size: MAX_SIZE_PER_PAGE, - offset: Number(indicator?.id ?? 0) * MAX_SIZE_PER_PAGE, - }), - ) - - return createPageable( - records.data.result, - createIndicator(indicator), - records.data.result.length === 0 ? undefined : createNextIndicator(indicator), - ) - }), - ) - - if (!txes?.length) return - - return txes - .sort((a, b) => new Date(b.block_timestamp).getTime() - new Date(a.block_timestamp).getTime()) - .map((x) => { - return { - input: x.input, - to: x.to_address, - from: x.from_address, - hash: x.transaction_hash, - chainId, - blockNumber: Number(x.block_number), - } as Transaction - }) - } -} -export const ChainbaseRedPacket = new ChainbaseRedPacketAPI() diff --git a/packages/web3-providers/src/Chainbase/index.ts b/packages/web3-providers/src/Chainbase/index.ts index 1643076ed899..f2d39bcf7ee2 100644 --- a/packages/web3-providers/src/Chainbase/index.ts +++ b/packages/web3-providers/src/Chainbase/index.ts @@ -1,4 +1,3 @@ export * from './apis/DomainAPI.js' export * from './apis/FungibleTokenAPI.js' export * from './apis/NonFungibleTokenAPI.js' -export * from './apis/RedPacketAPI.js' diff --git a/packages/web3-providers/src/Etherscan/apis/RedPacketAPI.ts b/packages/web3-providers/src/Etherscan/apis/RedPacketAPI.ts deleted file mode 100644 index e7fc5056a963..000000000000 --- a/packages/web3-providers/src/Etherscan/apis/RedPacketAPI.ts +++ /dev/null @@ -1,43 +0,0 @@ -import urlcat from 'urlcat' -import { isSameAddress, type Transaction } from '@masknet/web3-shared-base' -import { EtherscanURL } from '@masknet/web3-shared-evm' -import type { ChainId, SchemaType } from '@masknet/web3-shared-evm' -import { fetchJSON } from '../../helpers/fetchJSON.js' -import type { RedPacketBaseAPI } from '../../entry-types.js' - -class EtherscanRedPacketAPI implements RedPacketBaseAPI.Provider { - async getHistoryTransactions( - chainId: ChainId, - senderAddress: string, - contractAddress: string, - methodId: string, - startBlock: number, - endBlock: number, - ): Promise> | undefined> { - if (!senderAddress || !contractAddress || !startBlock || !endBlock || !methodId) return - - const { result } = await fetchJSON<{ result: Array> }>( - urlcat(EtherscanURL.from(chainId), { - action: 'txlist', - module: 'account', - sort: 'desc', - startBlock, - endBlock, - address: contractAddress, - chain_id: chainId, - }), - ) - - if (!result) return - - methodId = methodId.toLowerCase() - const methodIdLength = methodId.length - return result - .filter((x) => { - const txMethodId = x.methodId || x.input?.slice(0, methodIdLength) - return txMethodId?.toLowerCase() === methodId && isSameAddress(x.from, senderAddress) - }) - .map((x) => ({ ...x, chainId })) - } -} -export const EtherscanRedPacket = new EtherscanRedPacketAPI() diff --git a/packages/web3-providers/src/Etherscan/index.ts b/packages/web3-providers/src/Etherscan/index.ts index 9765a124e118..bbafc0610e7a 100644 --- a/packages/web3-providers/src/Etherscan/index.ts +++ b/packages/web3-providers/src/Etherscan/index.ts @@ -1,2 +1 @@ export * from './apis/ExplorerAPI.js' -export * from './apis/RedPacketAPI.js' diff --git a/packages/web3-providers/src/Firefly/RedPacket.ts b/packages/web3-providers/src/Firefly/RedPacket.ts deleted file mode 100644 index 0768a41ebbc3..000000000000 --- a/packages/web3-providers/src/Firefly/RedPacket.ts +++ /dev/null @@ -1,244 +0,0 @@ -import { - createIndicator, - createNextIndicator, - createPageable, - EMPTY_LIST, - type Pageable, - type PageIndicator, -} from '@masknet/shared-base' -import urlcat from 'urlcat' -import { fetchJSON } from '../entry-helpers.js' -import { FireflyRedPacketAPI } from '../entry-types.js' - -const SITE_URL = typeof location === 'undefined' ? '' : location.origin -let apiRoot = process.env.NEXT_PUBLIC_FIREFLY_API_URL || 'https://api.firefly.land' - -function fetchFireflyJSON(url: string, init?: RequestInit): Promise { - return fetchJSON(url, { - ...init, - headers: { - 'Content-Type': 'application/json', - ...init?.headers, - }, - }) -} - -export class FireflyRedPacket { - static async parse(options: FireflyRedPacketAPI.ParseOptions) { - const url = urlcat(apiRoot, '/v1/misc/redpacket/parse') - const { data } = await fetchFireflyJSON(url, { - method: 'POST', - body: JSON.stringify(options), - }) - return data - } - static async getPayloadUrls(from: string, amount?: string, type?: string, symbol?: string, decimals?: number) { - const url = urlcat(apiRoot, '/v1/redpacket/themeList') - const { data } = await fetchJSON(url) - - return data.list.map((theme) => ({ - themeId: theme.tid, - backgroundImageUrl: theme.cover.bg_image, - backgroundColor: theme.cover.bg_color, - url: urlcat(SITE_URL, '/api/rp', { - 'theme-id': theme.tid, - usage: 'payload', - from, - amount, - type, - symbol, - decimals, - }), - })) - } - - static async getPayloadUrlByThemeId( - themeId: string, - from: string, - amount?: string, - type?: string, - symbol?: string, - decimals?: number, - ) { - const url = urlcat(apiRoot, 'v1/redpacket/themeById', { - themeId, - }) - const { data } = await fetchJSON(url) - - return { - themeId, - url: urlcat(SITE_URL, '/api/rp', { - 'theme-id': themeId, - usage: 'payload', - from, - amount, - type, - symbol, - decimals, - }), - backgroundImageUrl: data.cover.bg_image, - backgroundColor: data.cover.bg_color, - } - } - - static async getCoverUrlByRpid( - rpid: string, - symbol?: string, - decimals?: number, - shares?: number, - amount?: string, - from?: string, - message?: string, - remainingAmount?: string, - remainingShares?: string, - ) { - const url = urlcat(apiRoot, 'v1/redpacket/themeById', { - rpid, - }) - const { data } = await fetchJSON(url) - // Just discard default theme, and this RedPacket will be treated as created from Mask - if (data.is_default) return null - - return { - themeId: data.tid, - backgroundImageUrl: data.normal.bg_image, - backgroundColor: data.normal.bg_color, - url: urlcat(SITE_URL, '/api/rp', { - 'theme-id': data.tid, - usage: 'cover', - symbol, - decimals, - shares, - amount, - from, - message, - 'remaining-amount': remainingAmount, - 'remaining-shares': remainingShares, - }), - } - } - - static async createPublicKey( - themeId: string, - shareFrom: string, - payloads: FireflyRedPacketAPI.StrategyPayload[], - ): Promise { - const url = urlcat(apiRoot, '/v1/redpacket/createPublicKey') - const { data } = await fetchFireflyJSON(url, { - method: 'POST', - body: JSON.stringify({ - themeId, - shareFrom, - claimFrom: FireflyRedPacketAPI.SourceType.FireflyPC, - claimStrategy: JSON.stringify(payloads), - }), - }) - return data.publicKey - } - - static async updateClaimStrategy( - rpid: string, - reactions: FireflyRedPacketAPI.PostReaction[], - claimPlatform: FireflyRedPacketAPI.ClaimPlatform[], - postOn: FireflyRedPacketAPI.PostOn[], - publicKey: string, - ): Promise { - const url = urlcat(apiRoot, '/v1/redpacket/updateClaimStrategy') - await fetchFireflyJSON(url, { - method: 'POST', - body: JSON.stringify({ - publicKey, - rpid, - postReaction: reactions, - postOn, - claimPlatform, - }), - }) - } - - static async createClaimSignature( - options: FireflyRedPacketAPI.CheckClaimStrategyStatusOptions, - ): Promise { - const url = urlcat(apiRoot, '/v1/redpacket/claim') - const { data } = await fetchFireflyJSON(url, { - method: 'POST', - body: JSON.stringify(options), - }) - return data.signedMessage - } - - static async getHistory< - T extends FireflyRedPacketAPI.ActionType, - R = T extends FireflyRedPacketAPI.ActionType.Claim ? FireflyRedPacketAPI.RedPacketClaimedInfo - : FireflyRedPacketAPI.RedPacketSentInfo, - >( - actionType: T, - from: HexString, - platform: FireflyRedPacketAPI.SourceType, - indicator?: PageIndicator, - ): Promise> { - if (!from) { - return createPageable(EMPTY_LIST, createIndicator(indicator)) - } - const url = urlcat(apiRoot, '/v1/redpacket/history', { - address: from, - redpacketType: actionType, - claimFrom: platform, - cursor: indicator?.id, - size: 20, - }) - const { data } = await fetchJSON(url, { - method: 'GET', - }) - return createPageable( - data.list.map((v) => ({ ...v, chain_id: Number(v.chain_id) })) as R[], - createIndicator(indicator), - data.cursor ? createNextIndicator(indicator, data.cursor.toString()) : undefined, - ) - } - - static async getClaimHistory( - redpacket_id: string, - indicator?: PageIndicator, - ): Promise { - const url = urlcat(apiRoot, '/v1/redpacket/claimHistory', { - redpacketId: redpacket_id, - cursor: indicator?.id, - size: 20, - }) - const { data } = await fetchJSON(url, { - method: 'GET', - }) - return { ...data, chain_id: Number(data.chain_id) } - } - - static async checkClaimStrategyStatus(options: FireflyRedPacketAPI.CheckClaimStrategyStatusOptions) { - const url = urlcat(apiRoot, '/v1/redpacket/checkClaimStrategyStatus') - return fetchFireflyJSON(url, { - method: 'POST', - body: JSON.stringify(options), - }) - } - static async finishClaiming( - rpid: string, - platform: FireflyRedPacketAPI.PlatformType, - profileId: string, - handle: string, - txHash: string, - ) { - const url = urlcat(apiRoot, '/v1/redpacket/finishClaiming') - return fetchFireflyJSON>(url, { - method: 'POST', - body: JSON.stringify({ - rpid, - claimPlatform: platform, - claimProfileId: profileId, - claimHandle: handle, - txHash, - }), - }) - } - static updateApiRoot(url: string) { - apiRoot = url - } -} diff --git a/packages/web3-providers/src/Firefly/index.ts b/packages/web3-providers/src/Firefly/index.ts index 34ef01c3db87..dd4f053e38e1 100644 --- a/packages/web3-providers/src/Firefly/index.ts +++ b/packages/web3-providers/src/Firefly/index.ts @@ -1,3 +1,2 @@ export * from './Config.js' -export * from './RedPacket.js' export * from './Twitter.js' diff --git a/packages/web3-providers/src/RedPacket/api.ts b/packages/web3-providers/src/RedPacket/api.ts deleted file mode 100644 index da6e8180746b..000000000000 --- a/packages/web3-providers/src/RedPacket/api.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { secondsToMilliseconds } from 'date-fns' -import { abiCoder, type ChainId, type SchemaType } from '@masknet/web3-shared-evm' -import { isSameAddress } from '@masknet/web3-shared-base' -import REDPACKET_ABI from '@masknet/web3-contracts/abis/HappyRedPacketV4.json' -import { EVMChainResolver } from '../Web3/EVM/apis/ResolverAPI.js' -import { EVMWeb3Readonly } from '../Web3/EVM/apis/ConnectionReadonlyAPI.js' -import type { RedPacketJSONPayloadFromChain } from './types.js' -import { CREATE_LUCKY_DROP_TOPIC } from './constants.js' -import type { RedPacketBaseAPI } from '../entry-types.js' - -const creationSuccessTopicInputs = REDPACKET_ABI.find((x) => x.name === 'CreationSuccess')?.inputs! - -class ContractRedPacketAPI implements RedPacketBaseAPI.Provider { - async getHistories( - chainId: ChainId, - senderAddress: string, - contractAddress: string, - methodId: string, - fromBlock: number, - toBlock: number, - ): Promise { - if (!senderAddress || !contractAddress || !fromBlock || !toBlock || !methodId) return - - const logs = await EVMWeb3Readonly.getWeb3({ chainId }).eth.getPastLogs({ - topics: [CREATE_LUCKY_DROP_TOPIC], - address: contractAddress, - fromBlock, - toBlock, - }) - - return logs - .map((log) => { - const result = abiCoder.decodeLog(creationSuccessTopicInputs, log.data, [ - CREATE_LUCKY_DROP_TOPIC, - ]) as unknown as { - creation_time: string // 10 - creator: string - duration: string // 86400 - id: string - ifrandom: boolean - message: string - name: string - number: string - token_address: string - total: string - } - - return { result, log } - }) - .filter((x) => isSameAddress(x.result.creator, senderAddress)) - .map( - (x) => - ({ - contract_address: contractAddress, - txid: x.log.transactionHash, - chainId, - shares: Number(x.result.number), - is_random: x.result.ifrandom, - total: x.result.total, - duration: secondsToMilliseconds(Number(x.result.duration)), - block_number: x.log.blockNumber, - contract_version: 4, - network: EVMChainResolver.networkType(chainId), - token_address: x.result.token_address, - sender: { - address: senderAddress, - name: x.result.name, - message: x.result.message, - }, - rpid: x.result.id, - creation_time: secondsToMilliseconds(Number(x.result.creation_time)), - // #region Retrieve at RedPacketInHistoryList component - total_remaining: '', - // #endregion - // #region Retrieve from database - password: '', - // #endregion - }) as RedPacketJSONPayloadFromChain, - ) - } -} - -export const ContractRedPacket = new ContractRedPacketAPI() diff --git a/packages/web3-providers/src/RedPacket/constants.ts b/packages/web3-providers/src/RedPacket/constants.ts deleted file mode 100644 index 154bb33df859..000000000000 --- a/packages/web3-providers/src/RedPacket/constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const CREATE_LUCKY_DROP_TOPIC = '0x86af556fd7cfab9462285ad44f2d5913527c539ff549f74731ca9997ca534018' diff --git a/packages/web3-providers/src/RedPacket/index.ts b/packages/web3-providers/src/RedPacket/index.ts deleted file mode 100644 index 6df1f7aa56f0..000000000000 --- a/packages/web3-providers/src/RedPacket/index.ts +++ /dev/null @@ -1,133 +0,0 @@ -import REDPACKET_ABI from '@masknet/web3-contracts/abis/HappyRedPacketV4.json' -import { attemptUntil, type Transaction } from '@masknet/web3-shared-base' -import { decodeFunctionParams, type ChainId, type SchemaType } from '@masknet/web3-shared-evm' -import { sortBy } from 'lodash-es' -import type { AbiItem } from 'web3-utils' -import { ChainbaseRedPacketAPI } from '../Chainbase/index.js' -import { EtherscanRedPacket } from '../Etherscan/index.js' -import { EVMChainResolver } from '../Web3/EVM/apis/ResolverAPI.js' -import type { RedPacketBaseAPI } from '../entry-types.js' -import { ContractRedPacket } from './api.js' -import { type RedPacketJSONPayloadFromChain } from './types.js' - -function toNumber(val: any) { - if (typeof val.toNumber === 'function') return val.toNumber() - return typeof val === 'string' ? Number.parseInt(val, 10) : val -} - -class RedPacketAPI implements RedPacketBaseAPI.Provider { - getHistories( - chainId: ChainId, - senderAddress: string, - contractAddress: string, - methodId: string, - fromBlock: number, - endBlock: number, - ): Promise { - return attemptUntil( - [ - async () => { - const transactions = await this.getHistoryTransactions( - chainId, - senderAddress, - contractAddress, - methodId, - fromBlock, - endBlock, - ) - return this.parseRedPacketCreationTransactions(transactions, senderAddress) - }, - async () => { - // block range might be too large - const results = await ContractRedPacket.getHistories( - chainId, - senderAddress, - contractAddress, - methodId, - fromBlock, - endBlock, - ) - return sortBy(results, (x) => -x.block_number!) - }, - ], - [], - ) - } - - async getHistoryTransactions( - chainId: ChainId, - senderAddress: string, - contractAddress: string, - methodId: string, - fromBlock: number, - endBlock: number, - ) { - const attempts = [ - () => { - return EtherscanRedPacket.getHistoryTransactions( - chainId, - senderAddress, - contractAddress, - methodId, - fromBlock, - endBlock, - ) - }, - ] - if (ChainbaseRedPacketAPI.isSupportedChain(chainId)) { - attempts.unshift(() => { - return ChainbaseRedPacketAPI.getHistoryTransactions(chainId, senderAddress, contractAddress, methodId) - }) - } - return attemptUntil(attempts, []) - } - - private parseRedPacketCreationTransactions( - transactions: Array> | undefined, - senderAddress: string, - ): RedPacketJSONPayloadFromChain[] { - if (!transactions) return [] - - return transactions.flatMap((tx) => { - try { - const decodedInputParam = decodeFunctionParams( - REDPACKET_ABI as AbiItem[], - tx.input ?? '', - 'create_red_packet', - ) - - const redpacketPayload: RedPacketJSONPayloadFromChain = { - contract_address: tx.to, - txid: tx.hash ?? '', - chainId: tx.chainId, - shares: toNumber(decodedInputParam._number), - is_random: decodedInputParam._ifrandom, - total: decodedInputParam._total_tokens.toString(), - duration: toNumber(decodedInputParam._duration) * 1000, - block_number: Number(tx.blockNumber), - contract_version: 4, - network: EVMChainResolver.networkType(tx.chainId), - token_address: decodedInputParam._token_addr, - sender: { - address: senderAddress, - name: decodedInputParam._name, - message: decodedInputParam._message, - }, - // #region Retrieve at RedPacketInHistoryList component - rpid: '', - creation_time: 0, - total_remaining: '', - // #endregion - // #region Retrieve from database - password: '', - // #endregion - } - return redpacketPayload - } catch { - return [] - } - }) - } -} -export const RedPacket = new RedPacketAPI() -export { CREATE_LUCKY_DROP_TOPIC } from './constants.js' diff --git a/packages/web3-providers/src/RedPacket/types.ts b/packages/web3-providers/src/RedPacket/types.ts deleted file mode 100644 index 9587961241d8..000000000000 --- a/packages/web3-providers/src/RedPacket/types.ts +++ /dev/null @@ -1,82 +0,0 @@ -import type { FungibleToken } from '@masknet/web3-shared-base' -import type { SchemaType, ChainId } from '@masknet/web3-shared-evm' -import type { BigNumber } from 'bignumber.js' - -// #region erc20 red packet -export interface RedPacketRecord { - id: string - /** From twitter/facebook url */ - from: string - password?: string - contract_version: number -} - -export interface RedPacketRecordInDatabase extends RedPacketRecord { - /** An unique record type in DB */ - type: 'red-packet' -} - -export enum RedPacketStatus { - claimed = 'claimed', - expired = 'expired', - empty = 'empty', - refunded = 'refunded', -} - -interface RedPacketBasic { - contract_address: string - rpid: string - txid: string - /** RedPacket created via Firefly app omits the password field */ - password?: string - shares: number - is_random: boolean - total: string - creation_time: number - duration: number - block_number?: number -} - -export interface RedPacketJSONPayload extends RedPacketBasic { - contract_version: number - sender: { - address: string - name: string - message: string - } - chainId?: ChainId - network?: string - token?: FungibleToken - /** - * For contract_version === 1, payload has no token but token_type - */ - token_type?: 0 | number - total_remaining?: string -} - -export interface RedPacketJSONPayloadFromChain extends Omit { - token_address: string -} - -export interface RedpacketAvailability { - token_address: string - balance: string - total: number - claimed: number - expired: boolean - claimed_amount: string -} -// #endregion - -export type CreateRedpacketParam = { - _duration: BigNumber - _ifrandom: boolean - _message: string - _name: string - _number: BigNumber - _public_key: string - _seed: string - _token_addr: string - _token_type: BigNumber - _total_tokens: BigNumber -} diff --git a/packages/web3-providers/src/TheGraph/apis/RedPacketAPI.ts b/packages/web3-providers/src/TheGraph/apis/RedPacketAPI.ts deleted file mode 100644 index 97f3b364e090..000000000000 --- a/packages/web3-providers/src/TheGraph/apis/RedPacketAPI.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { type ChainId } from '@masknet/web3-shared-evm' -import { REDPACKET_API_URL } from '../constants.js' -import { EVMChainResolver } from '../../Web3/EVM/apis/ResolverAPI.js' -import { fetchJSON } from '../../helpers/fetchJSON.js' -import type { RedPacketJSONPayloadFromChain } from '../../entry-types.js' - -type CreateSuccessRecord = { - creator: string - creation_time: string - duration: string - block_number: number - message: string - shares: string - name: string - token: { - address: string - } - total: string - txid: string - is_random: boolean - id: string -} - -export class TheGraphRedPacket { - static async getHistories(chainId: ChainId, senderAddress: string, contractAddress: string) { - if (!senderAddress || !contractAddress) return - - const response = await fetchJSON<{ - data: { - redPackets: CreateSuccessRecord[] - } - }>(REDPACKET_API_URL, { - method: 'POST', - body: JSON.stringify({ - query: `{ - redPackets(where: { creator_address: "${senderAddress}" }) { - creator { - address - } - message - block_number, - creation_time, - duration, - shares, - name, - token { - address - }, - total, - txid, - is_random - id, - } - }`, - }), - }) - - if (!response.data.redPackets.length) return - return response.data.redPackets.map( - (x) => - ({ - contract_address: contractAddress, - txid: x.txid, - id: x.id, - chainId, - shares: Number(x.shares), - total: x.total, - duration: Number(x.duration) * 1000, - block_number: Number(x.block_number), - contract_version: 4, - network: EVMChainResolver.networkType(chainId), - token_address: x.token.address, - sender: { - address: senderAddress, - name: x.name, - message: x.message, - }, - rpid: '', - creation_time: Number(x.creation_time), - total_remaining: '', - password: '', - is_random: x.is_random, - }) as RedPacketJSONPayloadFromChain, - ) - } -} diff --git a/packages/web3-providers/src/TheGraph/index.ts b/packages/web3-providers/src/TheGraph/index.ts index e8ee88dc3694..338f39382368 100644 --- a/packages/web3-providers/src/TheGraph/index.ts +++ b/packages/web3-providers/src/TheGraph/index.ts @@ -1,2 +1 @@ export * from './apis/DomainAPI.js' -export * from './apis/RedPacketAPI.js' diff --git a/packages/web3-providers/src/Web3/EVM/state/IdentityService.ts b/packages/web3-providers/src/Web3/EVM/state/IdentityService.ts index b6c346c5444e..467da07a99b2 100644 --- a/packages/web3-providers/src/Web3/EVM/state/IdentityService.ts +++ b/packages/web3-providers/src/Web3/EVM/state/IdentityService.ts @@ -1,7 +1,5 @@ import { NetworkPluginID, - NextIDPlatform, - PluginID, SocialAddressType, createLookupTableResolver, type SocialAddress, @@ -14,7 +12,6 @@ import { BaseMaskX } from '../../../entry-types.js' import * as Firefly from /* webpackDefer: true */ '../../../Firefly/index.js' import * as Lens from /* webpackDefer: true */ '../../../Lens/index.js' import * as MaskX from /* webpackDefer: true */ '../../../MaskX/index.js' -import * as NextIDStorageProvider from /* webpackDefer: true */ '../../../NextID/kv.js' import { IdentityServiceState } from '../../Base/state/IdentityService.js' const ENS_RE = /[^\s()[\]]{1,256}\.(eth|kred|xyz|luxe)\b/gi @@ -73,22 +70,6 @@ export class EVMIdentityService extends IdentityServiceState { return } - /** Read a social address from avatar NextID storage. */ - private async getSocialAddressFromAvatarNextID({ identifier, publicKey }: SocialIdentity) { - const userId = identifier?.userId - if (!userId || !publicKey) return - - const response = await NextIDStorageProvider.NextIDStorageProvider.getByIdentity<{ ownerAddress?: string }>( - publicKey, - NextIDPlatform.Twitter, - userId.toLowerCase(), - PluginID.Avatar, - ) - - if (!response.isOk() || !response.value.ownerAddress) return - return this.createSocialAddress(SocialAddressType.Mask, response.value.ownerAddress) - } - /** Read a social address from nickname, bio if them contain a ENS. */ private async getSocialAddressFromENS({ identifier, nickname = '', bio = '' }: SocialIdentity) { const names = getENSNames(identifier?.userId ?? '', nickname, bio) @@ -160,7 +141,6 @@ export class EVMIdentityService extends IdentityServiceState { const socialAddressFromMaskX = this.getSocialAddressesFromMaskX(identity) const allSettled = await Promise.allSettled([ this.getSocialAddressFromENS(identity), - this.getSocialAddressFromAvatarNextID(identity), socialAddressFromMaskX, this.getSocialAddressFromLens(identity), ]) diff --git a/packages/web3-providers/src/entry-types.ts b/packages/web3-providers/src/entry-types.ts index f8d58f7d25ca..b546407e50b0 100644 --- a/packages/web3-providers/src/entry-types.ts +++ b/packages/web3-providers/src/entry-types.ts @@ -20,7 +20,6 @@ export * from './types/SimpleHash.js' export * from './types/TokenIcon.js' export * from './types/TokenList.js' export * from './types/Trending.js' -export * from './types/RedPacket.js' export * from './types/NameService.js' export * from './types/Wallet.js' export * from './types/Lens.js' @@ -29,7 +28,6 @@ export * from './types/Store.js' // Provider Implementations export * from './DeBank/types.js' export * from './Web3/Router/types/index.js' -export * from './RedPacket/types.js' export type { BaseConnectionOptions } from './Web3/Base/apis/ConnectionOptions.js' export type { BaseHubOptions } from './Web3/Base/apis/HubOptions.js' diff --git a/packages/web3-providers/src/entry.ts b/packages/web3-providers/src/entry.ts index ddda2d49e779..0b52b4d90898 100644 --- a/packages/web3-providers/src/entry.ts +++ b/packages/web3-providers/src/entry.ts @@ -10,8 +10,6 @@ export { evm } from './Manager/registry.js' export { Multicall } from './Multicall/index.js' export { Lens } from './Lens/index.js' -export { RedPacket, CREATE_LUCKY_DROP_TOPIC } from './RedPacket/index.js' -export { TheGraphRedPacket } from './TheGraph/index.js' export { SimpleHashEVM, SimpleHashSolana, SPAM_SCORE } from './SimpleHash/index.js' // Web3 @@ -53,7 +51,7 @@ export { NFTScanNonFungibleTokenEVM, NFTScanNonFungibleTokenSolana } from './NFT export { ChainbaseDomain } from './Chainbase/index.js' // Firefly -export { FireflyConfig, FireflyRedPacket, FireflyTwitter } from './Firefly/index.js' +export { FireflyConfig, FireflyTwitter } from './Firefly/index.js' // FiatCurrencyRate export { FiatCurrencyRate } from './FiatCurrencyRate/index.js' diff --git a/packages/web3-providers/src/types/RedPacket.ts b/packages/web3-providers/src/types/RedPacket.ts deleted file mode 100644 index 039eeb80a53c..000000000000 --- a/packages/web3-providers/src/types/RedPacket.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { Pageable, PageIndicator } from '@masknet/shared-base' -import type { RedPacketJSONPayloadFromChain } from '../RedPacket/types.js' -import type { Transaction, NonFungibleCollection } from '@masknet/web3-shared-base' -import type { BaseHubOptions } from '../entry-types.js' - -export namespace RedPacketBaseAPI { - export interface Provider { - getHistories?: ( - chainId: ChainId, - senderAddress: string, - contractAddress: string, - methodId: string, - startBlock: number, - endBlock: number, - ) => Promise - - getHistoryTransactions?: ( - chainId: ChainId, - senderAddress: string, - contractAddress: string, - methodId: string, - startBlock: number, - endBlock: number, - ) => Promise> | undefined> - - /** Get non-fungible collections owned by the given account. */ - getCollectionsByOwner?: ( - account: string, - options?: BaseHubOptions, - ) => Promise, PageIndicator>> - } -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8391a471381b..abb7629fe026 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -330,69 +330,6 @@ importers: specifier: ^1.0.2 version: 1.0.2 - packages/plugins/RedPacket: - dependencies: - '@masknet/icons': - specifier: workspace:^ - version: link:../../icons - '@masknet/plugin-infra': - specifier: workspace:^ - version: link:../../plugin-infra - '@masknet/shared': - specifier: workspace:^ - version: link:../../shared - '@masknet/shared-base': - specifier: workspace:^ - version: link:../../shared-base - '@masknet/shared-base-ui': - specifier: workspace:^ - version: link:../../shared-base-ui - '@masknet/theme': - specifier: workspace:^ - version: link:../../theme - '@masknet/typed-message-react': - specifier: workspace:^ - version: link:../../typed-message/react - '@masknet/web3-contracts': - specifier: workspace:^ - version: link:../../web3-contracts - '@masknet/web3-hooks-base': - specifier: workspace:^ - version: link:../../web3-hooks/base - '@masknet/web3-hooks-evm': - specifier: workspace:^ - version: link:../../web3-hooks/evm - '@masknet/web3-providers': - specifier: workspace:^ - version: link:../../web3-providers - '@masknet/web3-shared-base': - specifier: workspace:^ - version: link:../../web3-shared/base - '@masknet/web3-shared-evm': - specifier: workspace:^ - version: link:../../web3-shared/evm - '@tanstack/react-query': - specifier: ^5.29.2 - version: 5.29.2(react@0.0.0-experimental-8039e6d0b-20231026) - bignumber.js: - specifier: 9.1.2 - version: 9.1.2 - date-fns: - specifier: ^2.30.0 - version: 2.30.0 - react-use: - specifier: ^17.5.1 - version: 17.5.1(patch_hash=jdgfodh3ixpexpgf3fwrwvcmtq)(react-dom@0.0.0-experimental-8039e6d0b-20231026)(react@0.0.0-experimental-8039e6d0b-20231026) - urlcat: - specifier: ^3.1.0 - version: 3.1.0(patch_hash=5r5xyq4zgcnqugwsrx4lxq2i4e) - web3-core: - specifier: 1.10.2 - version: 1.10.2(patch_hash=7c6knffilb7dxuf3r2r5ttgbem) - web3-utils: - specifier: 1.10.2 - version: 1.10.2 - packages/polyfills: dependencies: '@types/webextension-polyfill':