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
7 changes: 5 additions & 2 deletions apps/dashboard/src/@/api/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ export async function getEcosystemWalletUsage(args: {
searchParams.append("period", period);
}
const res = await fetchAnalytics(
`v2/wallets/connects/${ecosystemSlug}?${searchParams.toString()}`,
`v2/wallet/connects?${searchParams.toString()}`,
{
method: "GET",
headers: {
Expand All @@ -356,7 +356,10 @@ export async function getEcosystemWalletUsage(args: {
);

if (res?.status !== 200) {
console.error("Failed to fetch ecosystem wallet stats");
const reason = await res?.text();
console.error(
`Failed to fetch ecosystem wallet stats: ${res?.status} - ${res.statusText} - ${reason}`,
);
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
getLastNDaysRange,
} from "components/analytics/date-range-selector";
import { RangeSelector } from "components/analytics/range-selector";
import type { Partner } from "../../../../types";
import { EcosystemWalletUsersChartCard } from "./EcosystemWalletUsersChartCard";
import { EcosystemWalletsSummary } from "./Summary";

Expand All @@ -12,11 +13,13 @@ export async function EcosystemAnalyticsPage({
teamId,
interval,
range,
partners,
}: {
ecosystemSlug: string;
teamId: string;
interval: "day" | "week";
range?: Range;
partners: Partner[];
}) {
if (!range) {
range = getLastNDaysRange("last-120");
Expand Down Expand Up @@ -69,6 +72,14 @@ export async function EcosystemAnalyticsPage({
<EcosystemWalletUsersChartCard
ecosystemWalletStats={stats || []}
isPending={false}
groupBy="authenticationMethod"
partners={partners}
/>
<EcosystemWalletUsersChartCard
ecosystemWalletStats={stats || []}
isPending={false}
groupBy="ecosystemPartnerId"
partners={partners}
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function ecosystemWalletStatsStub(
date: formattedDate,
authenticationMethod: authMethod || "MetaMask",
uniqueWalletsConnected: Math.floor(Math.random() * 1000) + 1,
ecosystemPartnerId: "123",
});
}
}
Expand All @@ -65,6 +66,7 @@ export const EmptyData: Story = {
args: {
ecosystemWalletStats: [],
isPending: false,
groupBy: "authenticationMethod",
},
};

Expand All @@ -73,6 +75,7 @@ export const Loading: Story = {
args: {
ecosystemWalletStats: [],
isPending: true,
groupBy: "authenticationMethod",
},
};

Expand All @@ -81,6 +84,7 @@ export const ThirtyDaysData: Story = {
args: {
ecosystemWalletStats: ecosystemWalletStatsStub(30),
isPending: false,
groupBy: "authenticationMethod",
},
};

Expand All @@ -89,6 +93,7 @@ export const SixtyDaysData: Story = {
args: {
ecosystemWalletStats: ecosystemWalletStatsStub(60),
isPending: false,
groupBy: "authenticationMethod",
},
};

Expand All @@ -97,6 +102,7 @@ export const OneHundredTwentyDaysData: Story = {
args: {
ecosystemWalletStats: ecosystemWalletStatsStub(120),
isPending: false,
groupBy: "authenticationMethod",
},
};

Expand All @@ -114,6 +120,7 @@ export const ManyAuthMethods: Story = {
}));
})(),
isPending: false,
groupBy: "authenticationMethod",
},
};

Expand All @@ -125,5 +132,6 @@ export const ZeroValues: Story = {
uniqueWalletsConnected: 0,
})),
isPending: false,
groupBy: "authenticationMethod",
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { formatDate } from "date-fns";
import { useMemo } from "react";
import type { EcosystemWalletStats } from "types/analytics";
import { formatTickerNumber } from "../../../../../../../../../../lib/format-utils";
import type { Partner } from "../../../../types";

type ChartData = Record<string, number> & {
time: string; // human readable date
Expand All @@ -19,8 +20,10 @@ const defaultLabel = "Unknown Auth";
export function EcosystemWalletUsersChartCard(props: {
ecosystemWalletStats: EcosystemWalletStats[];
isPending: boolean;
groupBy: "ecosystemPartnerId" | "authenticationMethod";
partners?: Partner[];
}) {
const { ecosystemWalletStats } = props;
const { ecosystemWalletStats, groupBy, partners } = props;

const topChainsToShow = 10;

Expand All @@ -31,25 +34,40 @@ export function EcosystemWalletUsersChartCard(props: {
// for each stat, add it in _chartDataMap
for (const stat of ecosystemWalletStats) {
const chartData = _chartDataMap.get(stat.date);
const { authenticationMethod } = stat;
const { authenticationMethod, ecosystemPartnerId } = stat;

// if no data for current day - create new entry
if (!chartData) {
_chartDataMap.set(stat.date, {
time: stat.date,
[authenticationMethod || defaultLabel]: stat.uniqueWalletsConnected,
[groupBy === "ecosystemPartnerId"
? ecosystemPartnerId
: authenticationMethod || defaultLabel]:
stat.uniqueWalletsConnected,
} as ChartData);
} else if (chartData) {
chartData[authenticationMethod || defaultLabel] =
(chartData[authenticationMethod || defaultLabel] || 0) +
stat.uniqueWalletsConnected;
chartData[
groupBy === "ecosystemPartnerId"
? ecosystemPartnerId
: authenticationMethod || defaultLabel
] =
(chartData[
groupBy === "ecosystemPartnerId"
? ecosystemPartnerId
: authenticationMethod || defaultLabel
] || 0) + stat.uniqueWalletsConnected;
}

authMethodToVolumeMap.set(
authenticationMethod || defaultLabel,
groupBy === "ecosystemPartnerId"
? ecosystemPartnerId
: authenticationMethod || defaultLabel,
stat.uniqueWalletsConnected +
(authMethodToVolumeMap.get(authenticationMethod || defaultLabel) ||
0),
(authMethodToVolumeMap.get(
groupBy === "ecosystemPartnerId"
? ecosystemPartnerId
: authenticationMethod || defaultLabel,
) || 0),
);
}

Expand All @@ -72,7 +90,12 @@ export function EcosystemWalletUsersChartCard(props: {

authMethodsToShow.forEach((walletType, i) => {
_chartConfig[walletType] = {
label: authMethodsToShow[i],
label:
groupBy === "ecosystemPartnerId"
? partners?.find((p) => p.id === walletType)?.name ||
authMethodsToShow[i] ||
"none"
: authMethodsToShow[i],
color: `hsl(var(--chart-${(i % 10) + 1}))`,
};
});
Expand All @@ -92,7 +115,7 @@ export function EcosystemWalletUsersChartCard(props: {
),
chartConfig: _chartConfig,
};
}, [ecosystemWalletStats]);
}, [ecosystemWalletStats, groupBy, partners]);

const uniqueAuthMethods = Object.keys(chartConfig);
const disableActions =
Expand All @@ -108,7 +131,8 @@ export function EcosystemWalletUsersChartCard(props: {
customHeader={
<div className="relative px-6 pt-6">
<h3 className="mb-1 font-semibold text-xl tracking-tight md:text-2xl">
Unique Users
Unique Users by{" "}
{groupBy === "ecosystemPartnerId" ? "Partner" : "Auth Method"}
</h3>
<p className="mb-3 text-muted-foreground text-sm">
The total number of active users in your ecosystem for each period.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { redirect } from "next/navigation";
import { getTeamBySlug } from "../../../../../../../../../@/api/team";
import { getAuthToken } from "../../../../../../../../api/lib/getAuthToken";
import { fetchEcosystem } from "../../../utils/fetchEcosystem";
import { fetchPartners } from "../configuration/hooks/fetchPartners";
import { EcosystemAnalyticsPage } from "./components/EcosystemAnalyticsPage";

export default async function Page(props: {
Expand Down Expand Up @@ -40,11 +41,18 @@ export default async function Page(props: {
redirect("/team");
}

const partners = await fetchPartners({
ecosystem,
authToken,
teamId: team.id,
});

return (
<EcosystemAnalyticsPage
ecosystemSlug={ecosystem.slug}
teamId={team.id}
interval={searchParams.interval || "week"}
partners={partners}
range={
searchParams.from && searchParams.to
? {
Expand Down
4 changes: 3 additions & 1 deletion apps/dashboard/src/types/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ export interface InAppWalletStats {
uniqueWalletsConnected: number;
}

export interface EcosystemWalletStats extends InAppWalletStats {}
export interface EcosystemWalletStats extends InAppWalletStats {
ecosystemPartnerId: string;
}

export interface UserOpStats {
date: string;
Expand Down