diff --git a/apps/playground-web/public/ub.png b/apps/playground-web/public/ub.png new file mode 100644 index 00000000000..6448e1d2a10 Binary files /dev/null and b/apps/playground-web/public/ub.png differ diff --git a/apps/playground-web/src/app/connect/pay/backend/layout.tsx b/apps/playground-web/src/app/connect/pay/backend/layout.tsx new file mode 100644 index 00000000000..0b0c4052825 --- /dev/null +++ b/apps/playground-web/src/app/connect/pay/backend/layout.tsx @@ -0,0 +1,21 @@ +import type React from "react"; +import { APIHeader } from "../../../../components/blocks/APIHeader"; + +export default function Layout(props: { + children: React.ReactNode; +}) { + return ( +
+ 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} +
+ ); +} diff --git a/apps/playground-web/src/app/connect/pay/backend/page.tsx b/apps/playground-web/src/app/connect/pay/backend/page.tsx new file mode 100644 index 00000000000..26681e88431 --- /dev/null +++ b/apps/playground-web/src/app/connect/pay/backend/page.tsx @@ -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 ( +
+

+ Universal Bridge REST API +

+

+ Directly interact with the Universal Bridge API from your backend, + using standard REST api. +

+ +
+ { + if (!pathObj) { + throw new Error(`Path not found: ${pathName}`); + } + return { + name: pathName, + description: pathObj.get?.description || "", + link: `/connect/pay/backend/reference?route=${pathName}`, + }; + })} + /> +
+
+ ); + } catch (error) { + console.error(error); + return
Error fetching API spec
; + } +} + +function BlueprintSection(props: { + title: string; + blueprints: { name: string; description: string; link: string }[]; +}) { + return ( +
+
+

{props.title}

+
+ + + {props.blueprints.map((item) => ( + + + + +
+

{item.name}

+

+ {item.description} +

+
+ +
+
+
+ ))} +
+
+
+ ); +} diff --git a/apps/playground-web/src/app/connect/pay/backend/reference/page.tsx b/apps/playground-web/src/app/connect/pay/backend/reference/page.tsx new file mode 100644 index 00000000000..1f2fda67f19 --- /dev/null +++ b/apps/playground-web/src/app/connect/pay/backend/reference/page.tsx @@ -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; + }>; +}) { + 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 ( +
+ +

+ {title} +

+ +
+ ); +} + +function Breadcrumbs() { + return ( + + + + + Universal Bridge API + + + + + + ); +} diff --git a/apps/playground-web/src/app/connect/pay/backend/utils.ts b/apps/playground-web/src/app/connect/pay/backend/utils.ts new file mode 100644 index 00000000000..eb75e377ffc --- /dev/null +++ b/apps/playground-web/src/app/connect/pay/backend/utils.ts @@ -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, + ); +} diff --git a/apps/playground-web/src/app/insight/[blueprint_slug]/blueprint-playground.client.tsx b/apps/playground-web/src/app/insight/[blueprint_slug]/blueprint-playground.client.tsx index 333e9462746..211271f62fa 100644 --- a/apps/playground-web/src/app/insight/[blueprint_slug]/blueprint-playground.client.tsx +++ b/apps/playground-web/src/app/insight/[blueprint_slug]/blueprint-playground.client.tsx @@ -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: { @@ -44,6 +43,7 @@ export function BlueprintPlayground(props: { clientId: string; path: string; supportedChainIds: number[]; + domain: string; }) { const [abortController, setAbortController] = useState(null); @@ -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, @@ -78,8 +81,6 @@ export function BlueprintPlayground(props: { }, }); - const thirdwebDomain = !isProd ? "thirdweb-dev" : "thirdweb"; - return ( diff --git a/apps/playground-web/src/app/insight/[blueprint_slug]/page.tsx b/apps/playground-web/src/app/insight/[blueprint_slug]/page.tsx index e5fd2979d3a..9604218d930 100644 --- a/apps/playground-web/src/app/insight/[blueprint_slug]/page.tsx +++ b/apps/playground-web/src/app/insight/[blueprint_slug]/page.tsx @@ -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"; @@ -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, @@ -58,6 +62,7 @@ export default async function Page(props: { clientId={THIRDWEB_CLIENT.clientId} path={searchParams.path} supportedChainIds={supportedChainIds} + domain={domain} /> ); diff --git a/apps/playground-web/src/app/navLinks.ts b/apps/playground-web/src/app/navLinks.ts index a1ce0f3f712..037cc6beced 100644 --- a/apps/playground-web/src/app/navLinks.ts +++ b/apps/playground-web/src/app/navLinks.ts @@ -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", @@ -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, @@ -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; diff --git a/apps/playground-web/src/lib/client.ts b/apps/playground-web/src/lib/client.ts index e6be51abf73..ed34bcc545f 100644 --- a/apps/playground-web/src/lib/client.ts +++ b/apps/playground-web/src/lib/client.ts @@ -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 ? { diff --git a/apps/portal/src/app/references/components/TDoc/utils/getSidebarLinkgroups.ts b/apps/portal/src/app/references/components/TDoc/utils/getSidebarLinkgroups.ts index 780bc6428b9..1798f467815 100644 --- a/apps/portal/src/app/references/components/TDoc/utils/getSidebarLinkgroups.ts +++ b/apps/portal/src/app/references/components/TDoc/utils/getSidebarLinkgroups.ts @@ -35,6 +35,7 @@ const tagsToGroup = { "@extension": "Extensions", "@rpc": "RPC", "@transaction": "Transactions", + "@bridge": "Universal Bridge", "@buyCrypto": "Buy Crypto", "@utils": "Utils", "@chain": "Chain", @@ -60,6 +61,7 @@ const sidebarGroupOrder: TagKey[] = [ "@account", "@contract", "@transaction", + "@bridge", "@nebula", "@social", "@auth", diff --git a/packages/thirdweb/scripts/typedoc.mjs b/packages/thirdweb/scripts/typedoc.mjs index 2d42ffd0108..dd7f8ceddff 100644 --- a/packages/thirdweb/scripts/typedoc.mjs +++ b/packages/thirdweb/scripts/typedoc.mjs @@ -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", diff --git a/packages/thirdweb/src/extensions/thirdweb/write/publish.ts b/packages/thirdweb/src/extensions/thirdweb/write/publish.ts index 0c098feff2b..5ae855d6719 100644 --- a/packages/thirdweb/src/extensions/thirdweb/write/publish.ts +++ b/packages/thirdweb/src/extensions/thirdweb/write/publish.ts @@ -39,7 +39,7 @@ export type PublishContractParams = { * metadata, * }); * ``` - * @extension thirdweb + * @extension THIRDWEB */ export function publishContract( options: BaseTransactionOptions, diff --git a/packages/thirdweb/src/react/web/ui/PayEmbed.tsx b/packages/thirdweb/src/react/web/ui/PayEmbed.tsx index 7161d9e44c7..d7efb970c35 100644 --- a/packages/thirdweb/src/react/web/ui/PayEmbed.tsx +++ b/packages/thirdweb/src/react/web/ui/PayEmbed.tsx @@ -256,6 +256,7 @@ export type PayEmbedProps = { * buyWithFiat: false, * }} * /> + * ``` * * ### Customize the UI *