Skip to content
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
6 changes: 0 additions & 6 deletions apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,6 @@ export interface WalletStats {
walletType: string;
}

export interface InAppWalletStats {
date: string;
authenticationMethod: string;
uniqueWalletsConnected: number;
}

export interface UserOpStats {
date: string;
successful: number;
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { redirect } from "next/navigation";
import { EmbeddedWallets } from "../../../../../../components/embedded-wallets";
import { getAuthToken } from "../../../../../api/lib/getAuthToken";
import { PageHeader } from "../PageHeader";
import { getInAppWalletSupportedAPIKeys } from "../getInAppWalletSupportedAPIKeys";
import { InAppWalletsAPIKeysMenu } from "../inAppWalletsAPIKeysMenu";

export default async function Page(props: {
params: {
Expand All @@ -8,7 +13,44 @@ export default async function Page(props: {
tab?: string;
};
}) {
const authToken = getAuthToken();
const { clientId } = props.params;

redirect(`/dashboard/connect/in-app-wallets/${clientId}/analytics`);
if (!authToken) {
redirect(
`/login?next=${encodeURIComponent(`/dashboard/connect/in-app-wallets/${clientId}`)}`,
);
}

const apiKeys = await getInAppWalletSupportedAPIKeys();
const apiKey = apiKeys.find((key) => key.key === clientId);

if (!apiKey) {
redirect("/dashboard/connect/in-app-wallets");
}

return (
<div>
{/* header */}
<div className="flex flex-col gap-4 lg:flex-row lg:justify-between">
<PageHeader />
<div>
<InAppWalletsAPIKeysMenu
apiKeys={apiKeys.map((x) => ({
name: x.name,
key: x.key,
}))}
selectedAPIKey={apiKey}
/>
</div>
</div>

<div className="h-8" />
<EmbeddedWallets
apiKey={apiKey}
trackingCategory="embedded-wallet"
defaultTab={props.searchParams.tab === "1" ? 1 : 0}
/>
</div>
);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AnalyticsCallout } from "../../../../team/[team_slug]/[project_slug]/connect/in-app-wallets/_components/AnalyticsCallout";
import { InAppWaletFooterSection } from "../../../../team/[team_slug]/[project_slug]/connect/in-app-wallets/_components/footer";

export default function Layout(props: {
Expand All @@ -8,6 +9,7 @@ export default function Layout(props: {
{props.children}
<div className="h-16" />
{/* Footer */}
<AnalyticsCallout trackingCategory="embedded-wallet" />
<div className="h-5" />
<InAppWaletFooterSection trackingCategory="embedded-wallet" />
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"use client";

import { Button } from "@/components/ui/button";
import { TrackedLinkTW } from "@/components/ui/tracked-link";
import { useAccountUsage } from "@3rdweb-sdk/react/hooks/useApi";
import { UsageCard } from "components/settings/Account/UsageCard";
import { ArrowRightIcon } from "lucide-react";
import { useMemo } from "react";
import { toNumber, toPercent } from "utils/number";

type AnalyticsCalloutProps = {
trackingCategory: string;
};

export const AnalyticsCallout: React.FC<AnalyticsCalloutProps> = ({
trackingCategory,
}) => {
const usageQuery = useAccountUsage();

const walletsMetrics = useMemo(() => {
if (!usageQuery?.data) {
return undefined;
}

const usageData = usageQuery.data;

const numOfWallets = usageData.usage.embeddedWallets.countWalletAddresses;
const limitWallets = usageData.limits.embeddedWallets;
const percent = toPercent(numOfWallets, limitWallets);

return {
total: `${toNumber(numOfWallets)} / ${toNumber(
limitWallets,
)} (${percent}%)`,
progress: percent,
...(usageData.billableUsd.embeddedWallets > 0
? {
overage: usageData.billableUsd.embeddedWallets,
}
: {}),
};
}, [usageQuery]);

return (
<div className="flex flex-col gap-6 rounded-lg border border-border bg-muted/50 p-4 md:px-10 md:py-12 lg:flex-row lg:justify-between">
{/* Left */}
<div>
<p className="mb-3 text-muted-foreground text-xs">Analytics</p>
<h2 className="mb-5 max-w-[500px] font-semibold text-2xl tracking-tight">
View more insights about how users are interacting with your
application
</h2>

<Button asChild variant="outline" size="sm">
<TrackedLinkTW
href="/dashboard/connect/analytics"
category={trackingCategory}
label="view-analytics"
className="mt-auto min-w-[150px] gap-2"
>
View Analytics
<ArrowRightIcon className="size-4" />
</TrackedLinkTW>
</Button>
</div>

{/* Right */}
<div className="min-w-[280px]">
{walletsMetrics && (
<UsageCard
{...walletsMetrics}
name="Monthly Active Users"
tooltip="Email wallet (with managed recovery code) usage is calculated by monthly active wallets (i.e. active as defined by at least 1 user log-in via email or social within the billing period month)."
/>
)}
</div>
</div>
);
};
Loading