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
Binary file added apps/playground-web/public/ub.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions apps/playground-web/src/app/connect/pay/backend/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type React from "react";
import { APIHeader } from "../../../../components/blocks/APIHeader";

export default function Layout(props: {
children: React.ReactNode;
}) {
return (
<div>
<APIHeader
title="Universal Bridge API"
description={
<>HTTP API to bridge, swap and onramp to and from any currency</>
}
docsLink="https://portal.thirdweb.com/connect/pay/overview"
heroLink="/ub.png"
/>

{props.children}
</div>
);
}
79 changes: 79 additions & 0 deletions apps/playground-web/src/app/connect/pay/backend/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Table, TableBody, TableCell, TableRow } from "@/components/ui/table";
import Link from "next/link";
import { getBridgePaths } from "./utils";

export default async function Page() {
try {
const paths = await getBridgePaths();
return (
<div className="pb-20">
<h2 className="mb-2 font-semibold text-2xl tracking-tight">
Universal Bridge REST API
</h2>
<p className="mb-5 text-muted-foreground">
Directly interact with the Universal Bridge API from your backend,
using standard REST api.
</p>

<div className="flex flex-col gap-8">
<BlueprintSection
title="Available endpoints"
blueprints={paths.map(([pathName, pathObj]) => {
if (!pathObj) {
throw new Error(`Path not found: ${pathName}`);
}
return {
name: pathName,
description: pathObj.get?.description || "",
link: `/connect/pay/backend/reference?route=${pathName}`,
};
})}
/>
</div>
</div>
);
} catch (error) {
console.error(error);
return <div>Error fetching API spec</div>;
}
}

function BlueprintSection(props: {
title: string;
blueprints: { name: string; description: string; link: string }[];
}) {
return (
<div className="overflow-hidden rounded-lg border bg-card">
<div className="flex items-center gap-2 border-b bg-accent/20 px-6 py-4">
<h2 className="font-semibold text-lg tracking-tight">{props.title}</h2>
</div>
<Table>
<TableBody>
{props.blueprints.map((item) => (
<TableRow
key={item.link}
className="group hover:bg-accent/50"
linkBox
>
<TableCell>
<span className="flex items-center gap-3">
<Link
href={item.link}
className="before:absolute before:inset-0"
>
<div className="flex flex-col">
<p className="font-semibold text-md">{item.name}</p>
<p className="text-muted-foreground text-sm">
{item.description}
</p>
</div>
</Link>
</span>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb";
import { redirect } from "next/navigation";
import { THIRDWEB_CLIENT } from "../../../../../lib/client";
import { isProd } from "../../../../../lib/env";
import { BlueprintPlayground } from "../../../../insight/[blueprint_slug]/blueprint-playground.client";
import { getBridgePaths } from "../utils";

export default async function Page(props: {
searchParams: Promise<{
route: string;
}>;
Comment on lines +14 to +17
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The searchParams prop is typed as a Promise<{ route: string }>, but Next.js provides this parameter directly as an object. This causes an unnecessary await on line 19.

Consider updating the type signature to:

searchParams: {
  route: string;
}

And then remove the await when accessing params.route. This will align with Next.js's API and simplify the code.

Suggested change
export default async function Page(props: {
searchParams: Promise<{
route: string;
}>;
export default async function Page(props: {
searchParams: {
route: string;
};

Spotted by Diamond

Is this helpful? React 👍 or 👎 to let us know.

}) {
const params = await props.searchParams;

// invalid url
if (!params.route) {
redirect("/connect/pay/backend");
}

const thirdwebDomain = !isProd ? "thirdweb-dev" : "thirdweb";
const domain = `https://bridge.${thirdwebDomain}.com`;

const paths = await getBridgePaths();
const pathMetadata = paths.find(([path]) => path === params.route)?.[1]?.get;

// invalid url
if (!pathMetadata) {
redirect("/connect/pay/backend");
}

const title = pathMetadata.summary || "";
return (
<div>
<Breadcrumbs />
<h1 className="mt-3 mb-6 font-semibold text-2xl tracking-tight lg:text-3xl">
{title}
</h1>
<BlueprintPlayground
key={params.route}
metadata={pathMetadata}
backLink={"/connect/pay/backend"}
clientId={THIRDWEB_CLIENT.clientId}
path={params.route}
supportedChainIds={[]}
domain={domain}
/>
</div>
);
}

function Breadcrumbs() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/connect/pay/backend">
Universal Bridge API
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
</BreadcrumbList>
</Breadcrumb>
);
}
13 changes: 13 additions & 0 deletions apps/playground-web/src/app/connect/pay/backend/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { OpenAPIV3 } from "openapi-types";
import { isProd } from "../../../../lib/env";

export async function getBridgePaths() {
const thirdwebDomain = !isProd ? "thirdweb-dev" : "thirdweb";
const res = await fetch(`https://bridge.${thirdwebDomain}.com/openapi.json`);
const openapiJson = (await res.json()) as OpenAPIV3.Document;
return Object.entries(openapiJson.paths).filter(
([, pathObj]) =>
pathObj?.get?.deprecated === undefined ||
pathObj?.get?.deprecated === false,
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import {
useForm,
} from "react-hook-form";
import { z } from "zod";
import { isProd } from "../../../lib/env";
import type { BlueprintParameter, BlueprintPathMetadata } from "../utils";

export function BlueprintPlayground(props: {
Expand All @@ -44,6 +43,7 @@ export function BlueprintPlayground(props: {
clientId: string;
path: string;
supportedChainIds: number[];
domain: string;
}) {
const [abortController, setAbortController] =
useState<AbortController | null>(null);
Expand All @@ -56,6 +56,9 @@ export function BlueprintPlayground(props: {
try {
const res = await fetch(url, {
signal: controller.signal,
headers: {
"x-client-id": props.clientId,
},
});
return {
status: res.status,
Expand All @@ -78,8 +81,6 @@ export function BlueprintPlayground(props: {
},
});

const thirdwebDomain = !isProd ? "thirdweb-dev" : "thirdweb";

return (
<BlueprintPlaygroundUI
backLink={props.backLink}
Expand All @@ -98,7 +99,7 @@ export function BlueprintPlayground(props: {
abortController.abort();
}
}}
domain={`https://insight.${thirdwebDomain}.com`}
domain={props.domain}
path={props.path}
supportedChainIds={props.supportedChainIds}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from "@/components/ui/breadcrumb";
import { redirect } from "next/navigation";
import { THIRDWEB_CLIENT } from "../../../lib/client";
import { isProd } from "../../../lib/env";
import { fetchBlueprintSpec } from "../utils";
import { BlueprintPlayground } from "./blueprint-playground.client";

Expand All @@ -26,6 +27,9 @@ export default async function Page(props: {
redirect("/insight");
}

const thirdwebDomain = !isProd ? "thirdweb-dev" : "thirdweb";
const domain = `https://insight.${thirdwebDomain}.com`;

const [blueprintSpec] = await Promise.all([
fetchBlueprintSpec({
blueprintId: params.blueprint_slug,
Expand Down Expand Up @@ -58,6 +62,7 @@ export default async function Page(props: {
clientId={THIRDWEB_CLIENT.clientId}
path={searchParams.path}
supportedChainIds={supportedChainIds}
domain={domain}
/>
</div>
);
Expand Down
53 changes: 30 additions & 23 deletions apps/playground-web/src/app/navLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,28 +60,6 @@ export const staticSidebarLinks: SidebarLink[] = [
},
],
},
{
name: "Universal Bridge",
expanded: false,
links: [
{
name: "UI Component",
href: "/connect/pay",
},
{
name: "Fund Wallet",
href: "/connect/pay/fund-wallet",
},
{
name: "Commerce",
href: "/connect/pay/commerce",
},
{
name: "Transactions",
href: "/connect/pay/transactions",
},
],
},
{
name: "Auth",
href: "/connect/auth",
Expand Down Expand Up @@ -124,6 +102,34 @@ export const staticSidebarLinks: SidebarLink[] = [
},
];

const universalBridgeSidebarLinks: SidebarLink = {
name: "Universal Bridge",
isCollapsible: false,
expanded: false,
links: [
{
name: "UI Component",
href: "/connect/pay",
},
{
name: "Fund Wallet",
href: "/connect/pay/fund-wallet",
},
{
name: "Commerce",
href: "/connect/pay/commerce",
},
{
name: "Transactions",
href: "/connect/pay/transactions",
},
{
name: "Backend API",
href: "/connect/pay/backend",
},
],
};

const engineSidebarLinks: SidebarLink = {
name: "Engine",
isCollapsible: false,
Expand Down Expand Up @@ -167,13 +173,14 @@ export async function getSidebarLinks() {

const sidebarLinks: SidebarLink[] = [
...staticSidebarLinks,
universalBridgeSidebarLinks,
engineSidebarLinks,
{
name: "Insight",
isCollapsible: false,
expanded: false,
links: insightLinks,
},
engineSidebarLinks,
];

return sidebarLinks;
Expand Down
1 change: 1 addition & 0 deletions apps/playground-web/src/lib/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const THIRDWEB_CLIENT = createThirdwebClient(
process.env.THIRDWEB_SECRET_KEY
? {
secretKey: process.env.THIRDWEB_SECRET_KEY,
clientId: process.env.NEXT_PUBLIC_THIRDWEB_CLIENT_ID as string,
config: {
storage: isDev
? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const tagsToGroup = {
"@extension": "Extensions",
"@rpc": "RPC",
"@transaction": "Transactions",
"@bridge": "Universal Bridge",
"@buyCrypto": "Buy Crypto",
"@utils": "Utils",
"@chain": "Chain",
Expand All @@ -60,6 +61,7 @@ const sidebarGroupOrder: TagKey[] = [
"@account",
"@contract",
"@transaction",
"@bridge",
"@nebula",
"@social",
"@auth",
Expand Down
3 changes: 3 additions & 0 deletions packages/thirdweb/scripts/typedoc.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const app = await Application.bootstrapWithPlugins({
"src/adapters/eip1193/index.ts",
"src/wallets/smart/presets/index.ts",
"src/ai/index.ts",
"src/bridge/index.ts",
"src/bridge/Buy.ts",
"src/bridge/Sell.ts",
],
exclude: [
"src/exports/*.native.ts",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export type PublishContractParams = {
* metadata,
* });
* ```
* @extension thirdweb
* @extension THIRDWEB
*/
export function publishContract(
options: BaseTransactionOptions<PublishContractParams>,
Expand Down
1 change: 1 addition & 0 deletions packages/thirdweb/src/react/web/ui/PayEmbed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ export type PayEmbedProps = {
* buyWithFiat: false,
* }}
* />
* ```
*
* ### Customize the UI
*
Expand Down