Skip to content

Commit

Permalink
feat: mf-6358 migrate finance feed source to debank
Browse files Browse the repository at this point in the history
  • Loading branch information
swkatmask committed Oct 24, 2024
1 parent 861edb0 commit 52a5703
Show file tree
Hide file tree
Showing 7 changed files with 236 additions and 4 deletions.
37 changes: 37 additions & 0 deletions packages/plugins/RSS3/src/SiteAdaptor/FinanceFeeds/FeedSummary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Select, Trans } from '@lingui/macro'
import { type Transaction } from '@masknet/web3-shared-base'
import { Typography, type TypographyProps } from '@mui/material'
import { memo } from 'react'
import { makeStyles } from '@masknet/theme'
import type { ChainId, SchemaType } from '@masknet/web3-shared-evm'
import { AccountLabel } from '../components/common.js'

const useStyles = makeStyles<{ size: number }>()((theme) => ({
summary: {
display: 'flex',
gap: theme.spacing(0.5),
alignItems: 'center',
},
}))

interface Props extends TypographyProps {
transaction: Transaction<ChainId, SchemaType>
}
export const FeedSummary = memo<Props>(function FeedSummary({ transaction, ...rest }) {
const { classes, cx } = useStyles({ size: 20 })

return (
<Typography {...rest} className={cx(classes.summary, rest.className)}>
<Select
value={transaction.type}
other={
<Trans>
<AccountLabel address={transaction.from} />
transferred to
<AccountLabel address={transaction.to} />
</Trans>
}
/>
</Typography>
)
})
64 changes: 64 additions & 0 deletions packages/plugins/RSS3/src/SiteAdaptor/FinanceFeeds/FinanceFeed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { makeStyles, ShadowRootTooltip } from '@masknet/theme'
import type { ChainId, SchemaType } from '@masknet/web3-shared-evm'
import { formatTimestamp } from '../components/share.js'
import { type Transaction } from '@masknet/web3-shared-base'
import { format as formatDateTime } from 'date-fns'
import { memo, type HTMLProps } from 'react'
import { NetworkIcon } from '@masknet/shared'
import { NetworkPluginID } from '@masknet/shared-base'
import { Typography } from '@mui/material'
import { FeedSummary } from './FeedSummary.js'

const useStyles = makeStyles()((theme) => ({
verbose: {},
inspectable: {
cursor: 'pointer',
padding: theme.spacing(1.5),
'&:hover': {
backgroundColor: theme.palette.maskColor.bg,
},
},
header: {
display: 'flex',
alignItems: 'center',
gap: theme.spacing(1),
},
timestamp: {
fontSize: 14,
fontWeight: 400,
color: theme.palette.maskColor.third,
},
body: {},
}))

export interface FinanceFeedProps extends HTMLProps<HTMLDivElement> {
transaction: Transaction<ChainId, SchemaType>
verbose?: boolean
}
export const FinanceFeed = memo<FinanceFeedProps>(function FinanceFeed({ transaction, verbose, className, ...rest }) {
const { classes, cx } = useStyles()
return (
<article
{...rest}
className={cx(className, verbose ? classes.verbose : classes.inspectable)}
onClick={() => {
//
}}>
<div className={classes.header}>
<NetworkIcon pluginID={NetworkPluginID.PLUGIN_EVM} chainId={transaction.chainId} size={18} />
{transaction.timestamp ?
<ShadowRootTooltip
title={formatDateTime(new Date(transaction.timestamp), 'yyyy-MM-dd HH:mm:ss')}
placement="right">
<Typography className={classes.timestamp}>{formatTimestamp(transaction.timestamp)}</Typography>
</ShadowRootTooltip>
: null}
</div>
<FeedSummary transaction={transaction} mt={0.5} />
<div className={classes.body}>
{transaction.type}
{transaction.cateName}
</div>
</article>
)
})
96 changes: 96 additions & 0 deletions packages/plugins/RSS3/src/SiteAdaptor/FinanceFeeds/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { Trans } from '@lingui/macro'
import { ElementAnchor, EmptyStatus, ReloadStatus } from '@masknet/shared'
import { EMPTY_LIST } from '@masknet/shared-base'
import { LoadingBase, makeStyles } from '@masknet/theme'
import { ScopedDomainsContainer, useReverseAddress, useWeb3Utils } from '@masknet/web3-hooks-base'
import { Box, Skeleton, Typography } from '@mui/material'
import { range } from 'lodash-es'
import { memo, useMemo, type HTMLProps } from 'react'
import { FeedOwnerContext, type FeedOwnerOptions } from '../contexts/FeedOwnerContext.js'
import { FinanceFeed } from './FinanceFeed.js'
import { useFinanceFeeds } from './useFinanceFeeds.js'

const useStyles = makeStyles()((theme) => ({
loading: {
color: theme.palette.maskColor.main,
},
skeleton: {
borderRadius: theme.spacing(1),
},
}))

export interface FinanceFeedsProps extends HTMLProps<HTMLDivElement> {
address?: string
}
export const FinanceFeeds = memo<FinanceFeedsProps>(function FinanceFeeds({ address, ...rest }) {
const { classes } = useStyles()
const {
error,
data: feeds = EMPTY_LIST,
isPending: loading,
isLoading: isInitialLoading,
hasNextPage,
fetchNextPage,
} = useFinanceFeeds({ address })

const Utils = useWeb3Utils()
const { data: reversedName } = useReverseAddress(undefined, address)
const { getDomain } = ScopedDomainsContainer.useContainer()
const name = address ? getDomain(address) || reversedName : reversedName
const feedOwner: FeedOwnerOptions | undefined = useMemo(() => {
if (!address) return
return {
address,
name,
ownerDisplay: name ? Utils.formatDomainName(name) : Utils.formatAddress(address, 4) ?? address,
}
}, [address, name, Utils.formatDomainName, Utils.formatAddress])

if (error && !feeds.length)
return (
<Box p={2} boxSizing="border-box">
<Box mt="100px" color={(theme) => theme.palette.maskColor.main}>
<ReloadStatus onRetry={fetchNextPage} />
</Box>
</Box>
)

if (isInitialLoading || (loading && !feeds.length) || !feedOwner) {
return (
<Box p={2} boxSizing="border-box">
{range(3).map((i) => (
<Box mb={1} key={i}>
<Skeleton animation="wave" variant="rectangular" height={90} className={classes.skeleton} />
</Box>
))}
</Box>
)
}
if (!feeds?.length && !loading) {
return (
<EmptyStatus height={260}>
<Trans>There's no feed associated with this address.</Trans>
</EmptyStatus>
)
}
return (
<FeedOwnerContext value={feedOwner}>
<div {...rest}>
{feeds.map((tx) => (
<FinanceFeed key={tx.hash} transaction={tx} />
))}

{hasNextPage ?
<ElementAnchor height={10} callback={() => fetchNextPage()}>
{loading ?
<LoadingBase className={classes.loading} />
: null}
</ElementAnchor>
: <Typography color={(theme) => theme.palette.maskColor.second} textAlign="center" py={2}>
<Trans>No more data available.</Trans>
</Typography>
}
</div>
</FeedOwnerContext>
)
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { DeBankHistory } from '@masknet/web3-providers'
import { skipToken, useInfiniteQuery } from '@tanstack/react-query'

interface Options {
address: string | undefined
}

export function useFinanceFeeds({ address }: Options) {
return useInfiniteQuery({
initialPageParam: undefined as any,
queryKey: ['debank', 'all-history-list', address],
queryFn:
address ?
async ({ pageParam }) => {
return DeBankHistory.getAllTransactions(address, { indicator: pageParam })
}
: skipToken,
getNextPageParam: (lp) => lp.nextIndicator,
select(data) {
return data.pages.flatMap((page) => page.data)
},
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { LoadingBase, makeStyles } from '@masknet/theme'
import { Box, Skeleton, Typography } from '@mui/material'
import { range } from 'lodash-es'
import { memo, type HTMLProps } from 'react'
import { useSocialFeeds } from '../hooks/useSocialFeeds.js'
import { useSocialFeeds } from './useSocialFeeds.js'
import { SocialFeed } from './SocialFeed.js'

const useStyles = makeStyles()((theme) => ({
Expand Down
18 changes: 15 additions & 3 deletions packages/plugins/RSS3/src/SiteAdaptor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { toggleFilter, useInsideFeedsTab, useIsTabActionEnabled } from './emitte
import { type FeedsPageProps, FeedsPage } from './FeedsPage.js'
import { Modals } from './modals/index.js'
import { SocialFeeds } from './SocialFeeds/index.js'
import { FinanceFeeds } from './FinanceFeeds/index.js'

function shouldDisplay(_?: SocialIdentity, socialAccount?: SocialAccount<Web3Helper.ChainIdAll>) {
return socialAccount?.pluginID === NetworkPluginID.PLUGIN_EVM
Expand Down Expand Up @@ -92,7 +93,18 @@ const createSearchTabConfig = ({
}

const FinanceTags = [RSS3BaseAPI.Tag.Exchange, RSS3BaseAPI.Tag.Transaction]
const FinanceTabConfig: Plugin.SiteAdaptor.ProfileTab = createProfileTabConfig({
const FinanceTabConfig: Plugin.SiteAdaptor.ProfileTab = {
ID: `${PLUGIN_ID}_finance_feeds`,
label: 'Finance',
priority: 2,
UI: {
TabContent({ socialAccount }) {
return <FinanceFeeds address={socialAccount?.address} />
},
},
}

const LegacyFinanceTabConfig = createProfileTabConfig({
slot: 'profile-page',
label: 'Finance',
feedsPageProps: { tags: FinanceTags },
Expand Down Expand Up @@ -177,7 +189,7 @@ const SocialTabConfigInSearchResult: Plugin.SiteAdaptor.SearchResultTab = {
supportedAddressTypes: [SocialAddressType.ENS],
}
return (
<Box style={{ minHeight: 300 }}>
<Box minHeight={300} sx={{ scrollbarWidth: 'none' }}>
<EVMWeb3ContextProvider>
<SocialFeeds key={socialAccount.address} address={socialAccount.address} />
</EVMWeb3ContextProvider>
Expand Down Expand Up @@ -206,7 +218,7 @@ const site: Plugin.SiteAdaptor.Definition = {
/>
)
}),
ProfileTabs: [FinanceTabConfig, SocialTabConfig],
ProfileTabs: [LegacyFinanceTabConfig, FinanceTabConfig, SocialTabConfig],
ProfileCardTabs: [FinanceTabConfigInProfileCard, SocialTabConfigInProfileCard],
SearchResultTabs: [FinanceTabConfigInSearchResult, SocialTabConfigInSearchResult],
}
Expand Down

0 comments on commit 52a5703

Please sign in to comment.