Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trending DApps #5974

Merged
merged 5 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions src/components/DappBrowser/Homepage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import { analyticsV2 } from '@/analytics';
import haptics from '@/utils/haptics';
import * as i18n from '@/languages';
import { getNameFromFormattedUrl } from './utils';
import { useTrendingDApps } from '@/resources/metadata/trendingDapps';
import { DApp } from '@/graphql/__generated__/metadata';

const HORIZONTAL_PAGE_INSET = 24;
const MAX_RECENTS_TO_DISPLAY = 6;
Expand Down Expand Up @@ -73,9 +75,9 @@ export const Homepage = () => {
};

const Trending = ({ goToUrl }: { goToUrl: (url: string) => void }) => {
const { dapps } = useDapps({ select: dapps => dapps.filter(dapp => dapp.trending).slice(0, 8) });
const { data } = useTrendingDApps();

if (dapps.length === 0) {
if (!data?.dApps?.length) {
return null;
}

Expand All @@ -95,13 +97,15 @@ const Trending = ({ goToUrl }: { goToUrl: (url: string) => void }) => {
decelerationRate="fast"
disableIntervalMomentum
showsHorizontalScrollIndicator={false}
snapToOffsets={dapps.map((_, index) => index * (CARD_WIDTH + CARD_PADDING))}
snapToOffsets={data.dApps.map((_, index) => index * (CARD_WIDTH + CARD_PADDING))}
>
<Inset space="24px">
<Box flexDirection="row" gap={CARD_PADDING}>
{dapps.map((site, index) => (
<Card goToUrl={goToUrl} index={index} key={site.url} site={{ ...site, image: site.iconUrl }} />
))}
{data.dApps
.filter((dApp): dApp is DApp => dApp !== null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be handled in useTrendingDApps?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typescript tings.. but essentially yes

.map((dApp, index) => (
<Card goToUrl={goToUrl} index={index} key={dApp.url} site={{ ...dApp, image: dApp.iconURL }} />
))}
</Box>
</Inset>
</ScrollView>
Expand Down
20 changes: 20 additions & 0 deletions src/graphql/queries/metadata.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -604,3 +604,23 @@ mutation claimUserRewards($address: String!) {
txHash
}
}

query trendingDApps($period: DAppRankingPeriod) {
dApps(trending: true, period: $period) {
name
shortName
description
url
iconURL
colors {
primary
fallback
shadow
}
status
report {
url
}
trending
}
}
47 changes: 47 additions & 0 deletions src/resources/metadata/trendingDapps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { metadataClient } from '@/graphql';
import { DAppRankingPeriod, DAppStatus, TrendingDAppsQuery } from '@/graphql/__generated__/metadata';
import { createQueryKey, QueryConfigWithSelect } from '@/react-query';
import { QueryFunction, useQuery } from '@tanstack/react-query';

const trendingDAppsQueryKey = ({ period }: { period: DAppRankingPeriod }) =>
createQueryKey('trendingDApps', { period }, { persisterVersion: 1 });

type TrendingDAppsQueryKey = ReturnType<typeof trendingDAppsQueryKey>;

const fetchTrendingDApps: QueryFunction<TrendingDAppsQuery, TrendingDAppsQueryKey> = async ({ queryKey }) => {
const [{ period }] = queryKey;

return metadataClient.trendingDApps({
period,
});
};

export function selectValidNonScamDApps(data: TrendingDAppsQuery): TrendingDAppsQuery {
if (!data.dApps?.length) return { ...data, dApps: [] };
return {
...data,
dApps: data.dApps.filter(d => Boolean(d) && d?.status !== DAppStatus.Scam),
};
}
walmat marked this conversation as resolved.
Show resolved Hide resolved

export function selectFirstEightDApps(data: TrendingDAppsQuery): TrendingDAppsQuery {
if (!data.dApps?.length) return { ...data, dApps: [] };
return {
...data,
dApps: data.dApps.slice(0, 8),
};
}

export function useTrendingDApps(
period = DAppRankingPeriod.Day,
config: QueryConfigWithSelect<TrendingDAppsQuery, unknown, ReturnType<typeof selectFirstEightDApps>, TrendingDAppsQueryKey> = {}
) {
return useQuery(trendingDAppsQueryKey({ period }), fetchTrendingDApps, {
staleTime: 1000 * 60 * 20, // 20 minutes
cacheTime: 1000 * 60 * 60 * 24 * 2, // 2 days
retry: 3,
keepPreviousData: true,
select: data => selectFirstEightDApps(selectValidNonScamDApps(data)),
...config,
});
}
Loading