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; +}