Skip to content
Merged
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
56 changes: 53 additions & 3 deletions apps/dashboard/src/app/bridge/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Metadata } from "next";
import { isAddress, NATIVE_TOKEN_ADDRESS } from "thirdweb";
import { BridgePageUI } from "./components/bridge-page";

const title = "thirdweb Bridge: Buy, Bridge & Swap Crypto on 85+ Chains";
Expand All @@ -14,11 +15,50 @@ export const metadata: Metadata = {
title,
};

export default function Page() {
type SearchParams = {
[key: string]: string | string[] | undefined;
};

export default async function Page(props: {
searchParams: Promise<SearchParams>;
}) {
const searchParams = await props.searchParams;

const onlyAddress = (v: string) => (isAddress(v) ? v : undefined);
const onlyNumber = (v: string) =>
Number.isNaN(Number(v)) ? undefined : Number(v);

// output is buy, input is sell
const sellChain = parse(searchParams.inputChain, onlyNumber);
const sellCurrency = parse(searchParams.inputCurrency, onlyAddress);

const buyChain = parse(searchParams.outputChain, onlyNumber);
const buyCurrency = parse(searchParams.outputCurrency, onlyAddress);
Comment on lines +28 to +36
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Harden chain ID parsing to reject empty/invalid values.

onlyNumber currently accepts values like "" or " " (coerced to 0) and any non-integer such as "1.5", so a query like ?outputChain= ends up sending chainId: 0. That’s not a valid EVM chain ID and will surface downstream as a broken bridge configuration. Please tighten the validator to bail out on blank strings and non-integer values before we build the embed props.

-  const onlyNumber = (v: string) =>
-    Number.isNaN(Number(v)) ? undefined : Number(v);
+  const onlyNumber = (v: string) => {
+    if (v.trim() === "") {
+      return undefined;
+    }
+    const parsed = Number(v);
+    return Number.isInteger(parsed) ? parsed : undefined;
+  };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const onlyNumber = (v: string) =>
Number.isNaN(Number(v)) ? undefined : Number(v);
// output is buy, input is sell
const sellChain = parse(searchParams.inputChain, onlyNumber);
const sellCurrency = parse(searchParams.inputCurrency, onlyAddress);
const buyChain = parse(searchParams.outputChain, onlyNumber);
const buyCurrency = parse(searchParams.outputCurrency, onlyAddress);
const onlyNumber = (v: string) => {
if (v.trim() === "") {
return undefined;
}
const parsed = Number(v);
return Number.isInteger(parsed) ? parsed : undefined;
};
// output is buy, input is sell
const sellChain = parse(searchParams.inputChain, onlyNumber);
const sellCurrency = parse(searchParams.inputCurrency, onlyAddress);
const buyChain = parse(searchParams.outputChain, onlyNumber);
const buyCurrency = parse(searchParams.outputCurrency, onlyAddress);
🤖 Prompt for AI Agents
In apps/dashboard/src/app/bridge/page.tsx around lines 28 to 36, the onlyNumber
validator currently coerces blank/whitespace and non-integer strings to 0 (e.g.
"" -> 0) which allows invalid chainId values; update the validator to first trim
and reject empty strings, then verify the raw string strictly represents an
integer (no decimals, no signs, e.g. using a /^\d+$/-style check or equivalent)
before converting to a Number, returning undefined for anything that fails so
parse(...) won't produce chainId: 0.


return (
<BridgePageUI
buyTab={undefined}
swapTab={undefined}
buyTab={{
buyToken: buyChain
? {
chainId: buyChain,
tokenAddress: buyCurrency || NATIVE_TOKEN_ADDRESS,
}
: undefined,
}}
swapTab={{
sellToken: sellChain
? {
chainId: sellChain,
tokenAddress: sellCurrency || NATIVE_TOKEN_ADDRESS,
}
: undefined,
buyToken: buyChain
? {
chainId: buyChain,
tokenAddress: buyCurrency || NATIVE_TOKEN_ADDRESS,
}
: undefined,
}}
title={
<h1 className="text-3xl md:text-6xl font-semibold tracking-tighter text-balance text-center">
Bridge and Swap tokens <br className="max-sm:hidden" /> across any
Expand All @@ -28,3 +68,13 @@ export default function Page() {
/>
);
}

function parse<T>(
value: string | string[] | undefined,
fn: (value: string) => T | undefined,
): T | undefined {
if (typeof value === "string") {
return fn(value);
}
return undefined;
}
Loading