diff --git a/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/onramp/countries/components/client/provider.tsx b/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/onramp/countries/components/client/provider.tsx
new file mode 100644
index 00000000000..d654e5b952c
--- /dev/null
+++ b/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/onramp/countries/components/client/provider.tsx
@@ -0,0 +1,43 @@
+"use client";
+
+import { Button } from "@/components/ui/button";
+import { useDashboardRouter } from "@/lib/DashboardRouter";
+import { usePathname, useSearchParams } from "next/navigation";
+import { useCallback } from "react";
+
+export type OnrampProvider = "stripe" | "coinbase" | "transak";
+
+export const ProviderSelector: React.FC<{ activeProvider: OnrampProvider }> = ({
+ activeProvider,
+}) => {
+ const pathname = usePathname();
+ const searchParams = useSearchParams();
+ const router = useDashboardRouter();
+
+ const createPageURL = useCallback(
+ (provider: OnrampProvider) => {
+ const params = new URLSearchParams(searchParams || undefined);
+ params.set("provider", provider);
+ return `${pathname}?${params.toString()}`;
+ },
+ [pathname, searchParams],
+ );
+
+ const providers: OnrampProvider[] = ["coinbase", "stripe", "transak"];
+
+ return (
+
+ {providers.map((p) => (
+
+ ))}
+
+ );
+};
diff --git a/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/onramp/countries/components/server/countries-table.tsx b/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/onramp/countries/components/server/countries-table.tsx
new file mode 100644
index 00000000000..afb72b61e82
--- /dev/null
+++ b/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/onramp/countries/components/server/countries-table.tsx
@@ -0,0 +1,43 @@
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableContainer,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table";
+import { getOnrampCountrySupport } from "../../../../utils";
+import type { OnrampProvider } from "../client/provider";
+
+export async function CountriesTable(props: { provider: OnrampProvider }) {
+ const data = await getOnrampCountrySupport(props.provider);
+ const countries = data.supportedCountries;
+
+ return (
+
+
+
+
+
+ Country
+
+
+ Currencies
+
+
+
+
+ {countries.map((country) => (
+
+ {country.name}
+
+ {country.currencies.join(", ")}
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/onramp/countries/page.tsx b/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/onramp/countries/page.tsx
new file mode 100644
index 00000000000..263e34ce14f
--- /dev/null
+++ b/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/onramp/countries/page.tsx
@@ -0,0 +1,47 @@
+import type { Metadata } from "next";
+import {
+ type OnrampProvider,
+ ProviderSelector,
+} from "./components/client/provider";
+import { CountriesTable } from "./components/server/countries-table";
+
+const title = "Onramp Country Support";
+const description = "Countries and currencies supported by onramp providers.";
+
+export const metadata: Metadata = {
+ title,
+ description,
+ openGraph: {
+ title,
+ description,
+ },
+};
+
+export default async function OnrampCountriesPage(props: {
+ searchParams: Promise<{ provider?: OnrampProvider }>;
+}) {
+ const searchParams = await props.searchParams;
+ const activeProvider: OnrampProvider =
+ (searchParams.provider as OnrampProvider) || "coinbase";
+
+ return (
+
+
+
+
+
+ Onramp Countries
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/types/onramp-country.ts b/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/types/onramp-country.ts
new file mode 100644
index 00000000000..cdcbd6c07fd
--- /dev/null
+++ b/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/types/onramp-country.ts
@@ -0,0 +1,17 @@
+export type OnrampCountryToken = {
+ chainId: number;
+ address: string;
+ symbol: string;
+};
+
+export type OnrampCountryDetails = {
+ code: string;
+ name: string;
+ currencies: string[];
+ tokens: OnrampCountryToken[];
+};
+
+export type OnrampCountrySupport = {
+ provider: "stripe" | "coinbase" | "transak";
+ supportedCountries: OnrampCountryDetails[];
+};
diff --git a/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/utils.ts b/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/utils.ts
index cdeadfba530..639a119a6e5 100644
--- a/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/utils.ts
+++ b/apps/dashboard/src/app/(app)/(dashboard)/(bridge)/utils.ts
@@ -68,3 +68,25 @@ export async function getRoutes({
return routes;
}
+
+export async function getOnrampCountrySupport(
+ provider: "stripe" | "coinbase" | "transak",
+) {
+ const url = new URL(
+ `${NEXT_PUBLIC_THIRDWEB_BRIDGE_HOST}/v1/onramp/countries`,
+ );
+ url.searchParams.set("provider", provider);
+ const res = await fetch(url.toString(), {
+ headers: {
+ "x-secret-key": DASHBOARD_THIRDWEB_SECRET_KEY,
+ },
+ next: { revalidate: 60 * 60 },
+ });
+
+ if (!res.ok) {
+ throw new Error("Failed to fetch onramp countries");
+ }
+
+ const json = await res.json();
+ return json.data as import("./types/onramp-country").OnrampCountrySupport;
+}