diff --git a/apps/dashboard/src/@/components/blocks/charts/area-chart.tsx b/apps/dashboard/src/@/components/blocks/charts/area-chart.tsx index afc6a22d283..d22a737fd5c 100644 --- a/apps/dashboard/src/@/components/blocks/charts/area-chart.tsx +++ b/apps/dashboard/src/@/components/blocks/charts/area-chart.tsx @@ -29,6 +29,7 @@ type ThirdwebAreaChartProps = { title: string; description?: string; titleClassName?: string; + headerClassName?: string; }; customHeader?: React.ReactNode; // chart config @@ -52,6 +53,12 @@ type ThirdwebAreaChartProps = { toolTipLabelFormatter?: (label: string, payload: unknown) => React.ReactNode; toolTipValueFormatter?: (value: unknown) => React.ReactNode; emptyChartState?: React.ReactElement; + margin?: { + top?: number; + right?: number; + bottom?: number; + left?: number; + }; }; export function ThirdwebAreaChart( @@ -62,7 +69,7 @@ export function ThirdwebAreaChart( return ( {props.header && ( - + {props.header.title} @@ -85,7 +92,16 @@ export function ThirdwebAreaChart( {props.emptyChartState} ) : ( - + {props.yAxis && } ); diff --git a/apps/dashboard/src/@/components/ui/background-patterns.tsx b/apps/dashboard/src/@/components/ui/background-patterns.tsx index e9d0cbd0484..dce537223b1 100644 --- a/apps/dashboard/src/@/components/ui/background-patterns.tsx +++ b/apps/dashboard/src/@/components/ui/background-patterns.tsx @@ -1,3 +1,4 @@ +import { useId } from "react"; import { cn } from "@/lib/utils"; export function DotsBackgroundPattern(props: { className?: string }) { @@ -16,3 +17,70 @@ export function DotsBackgroundPattern(props: { className?: string }) { /> ); } + +interface GridPatternProps extends React.SVGProps { + width?: number; + height?: number; + x?: number; + y?: number; + squares?: Array<[x: number, y: number]>; + strokeDasharray?: string; + className?: string; + [key: string]: unknown; +} + +export function GridPattern({ + width = 40, + height = 40, + x = -1, + y = -1, + strokeDasharray = "0", + squares, + className, + ...props +}: GridPatternProps) { + const id = useId(); + + return ( + + ); +} diff --git a/apps/dashboard/src/@/components/ui/card.tsx b/apps/dashboard/src/@/components/ui/card.tsx index 4927d2439e0..ae7a0598ea6 100644 --- a/apps/dashboard/src/@/components/ui/card.tsx +++ b/apps/dashboard/src/@/components/ui/card.tsx @@ -8,7 +8,7 @@ const Card = React.forwardRef< >(({ className, ...props }, ref) => (
+
; +}; + +export async function getTokenPriceData(params: { + chainId: number; + contractAddress: string; +}) { + try { + const url = new URL( + `https://insight.${isProd ? "thirdweb" : "thirdweb-dev"}.com/v1/tokens/price`, + ); + + url.searchParams.set("include_historical_prices", "true"); + url.searchParams.set("chain_id", params.chainId.toString()); + url.searchParams.set("address", params.contractAddress); + url.searchParams.set("include_holders", "true"); + + const res = await fetch(url, { + headers: { + "x-secret-key": DASHBOARD_THIRDWEB_SECRET_KEY, + }, + }); + if (!res.ok) { + console.error("Failed to fetch token price data", await res.text()); + return undefined; + } + + const json = await res.json(); + const priceData = json.data[0] as TokenPriceData | undefined; + + return priceData; + } catch { + return undefined; + } +} diff --git a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractCreatorBadge.tsx b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractCreatorBadge.tsx deleted file mode 100644 index 7bef42d4f05..00000000000 --- a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractCreatorBadge.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import type { ThirdwebContract } from "thirdweb"; -import { WalletAddress } from "@/components/blocks/wallet-address"; - -export function ContractCreatorBadge(props: { - contractCreator: string; - clientContract: ThirdwebContract; -}) { - return ( -
- By - -
- ); -} diff --git a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractHeader.tsx b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractHeader.tsx index 28bb90f2014..0c926fa4a3a 100644 --- a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractHeader.tsx +++ b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractHeader.tsx @@ -1,4 +1,9 @@ -import { ExternalLinkIcon, GlobeIcon, Settings2Icon } from "lucide-react"; +import { + ExternalLinkIcon, + GlobeIcon, + Settings2Icon, + UserIcon, +} from "lucide-react"; import Link from "next/link"; import { useMemo } from "react"; import { type ThirdwebContract, ZERO_ADDRESS } from "thirdweb"; @@ -19,7 +24,6 @@ import { YoutubeIcon } from "@/icons/brand-icons/YoutubeIcon"; import { ChainIconClient } from "@/icons/ChainIcon"; import { cn } from "@/lib/utils"; import { resolveSchemeWithErrorHandler } from "@/utils/resolveSchemeWithErrorHandler"; -import { ContractCreatorBadge } from "./ContractCreatorBadge"; const platformToIcons: Record> = { discord: DiscordIcon, @@ -44,6 +48,7 @@ export function ContractHeaderUI(props: { socialUrls: object; imageClassName?: string; contractCreator: string | null; + className?: string; }) { const socialUrls = useMemo(() => { const socialUrlsValue: { name: string; href: string }[] = []; @@ -64,41 +69,45 @@ export function ContractHeaderUI(props: { ?.replace("Mainnet", "") .trim(); - const explorersToShow = getExplorersToShow(props.chainMetadata); + const validBlockExplorer = getExplorerToShow(props.chainMetadata); return ( -
- {props.image && ( - - {props.name[0]} -
- } - src={ - props.image - ? resolveSchemeWithErrorHandler({ - client: props.clientContract.client, - uri: props.image, - }) - : "" - } - /> +
+
+
+ + {props.name[0]} +
+ } + src={ + props.image + ? resolveSchemeWithErrorHandler({ + client: props.clientContract.client, + uri: props.image, + }) + : "" + } + /> +
+
-
+
{/* top row */}
-

+

{props.name}

-
+
- + {props.contractCreator && + validBlockExplorer && + props.contractCreator !== ZERO_ADDRESS && ( + + )} {socialUrls .toSorted((a, b) => { @@ -148,13 +160,14 @@ export function ContractHeaderUI(props: {
{/* bottom row */} -
- {props.contractCreator && props.contractCreator !== ZERO_ADDRESS && ( - - )} +
+ - {explorersToShow?.map((validBlockExplorer) => ( + {validBlockExplorer && ( - ))} + )} {/* TODO - render social links here */}
@@ -204,19 +217,22 @@ function isValidUrl(url: string) { } } -function getExplorersToShow(chainMetadata: ChainMetadata) { - const validBlockExplorers = chainMetadata.explorers - ?.filter((e) => e.standard === "EIP3091") - ?.slice(0, 2); +function getExplorerToShow(chainMetadata: ChainMetadata) { + const validBlockExplorers = chainMetadata.explorers?.filter( + (e) => e.standard === "EIP3091", + ); - return validBlockExplorers?.slice(0, 1); + return validBlockExplorers?.[0]; } -function BadgeLink(props: { name: string; href: string }) { +function BadgeLink(props: { name: string; href: string; className?: string }) { return (