Skip to content

Conversation

@MananTank
Copy link
Member

@MananTank MananTank commented Aug 28, 2025


PR-Codex overview

This PR focuses on refactoring the token management functionality in the universal-bridge API by updating imports, relocating the TokenMetadata type definition, and implementing a new token fetching function.

Detailed summary

  • Added TokenMetadata type in apps/dashboard/src/@/api/universal-bridge/types.ts.
  • Updated import paths for getUniversalBridgeTokens from tokens to token-list.
  • Implemented getUniversalBridgeTokens function in apps/dashboard/src/@/api/universal-bridge/token-list.ts.
  • Removed the old getUniversalBridgeTokens and TokenMetadata definition from apps/dashboard/src/@/api/universal-bridge/tokens.ts.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • New Features
    • Added capability to add tokens to Universal Bridge for a specific project via authenticated requests.
  • Improvements
    • More reliable token loading and clearer errors when fetching tokens across the dashboard (e.g., token selectors and payment link flows).
  • Refactor
    • Streamlined token APIs and centralized token metadata type for consistency.
    • Updated authentication to use project-based credentials for Universal Bridge requests.
  • Chores
    • Updated imports and internal references to the new token APIs and types.

@linear
Copy link

linear bot commented Aug 28, 2025

@changeset-bot
Copy link

changeset-bot bot commented Aug 28, 2025

⚠️ No Changeset found

Latest commit: 67616c2

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 28, 2025

Walkthrough

Introduces a new GET helper to fetch Universal Bridge tokens, refactors the existing tokens module to a POST-based add-token route with Bearer auth, extracts TokenMetadata into a shared types file, and updates imports in hooks and components to use the new helper and type path.

Changes

Cohort / File(s) Summary
Universal Bridge API: token listing
apps/dashboard/src/@/api/universal-bridge/token-list.ts
New GET helper getUniversalBridgeTokens hitting UB_BASE_URL/v1/tokens with optional chainId and tokenAddress, limit=1000, includePrices=false; returns json.data as TokenMetadata[].
Universal Bridge API: add token route & types
apps/dashboard/src/@/api/universal-bridge/tokens.ts, apps/dashboard/src/@/api/universal-bridge/types.ts
Replaces old GET list function with POST addUniversalBridgeTokenRoute requiring { chainId, tokenAddress, project }, using Bearer auth and x-client-id from project.publishableKey; TokenMetadata moved to types.ts.
Type import updates in UI
apps/dashboard/src/@/components/blocks/TokenSelector.tsx
Updates TokenMetadata import path to "@/api/universal-bridge/types".
Consumers: fetch helper path update
apps/dashboard/src/@/hooks/tokens.ts, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
Switch imports to "@/api/universal-bridge/token-list" for getUniversalBridgeTokens; no logic changes.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant UI as UI (hooks/components)
    participant UB as Universal Bridge API

    rect rgba(200,220,255,0.25)
    note over UI: Fetch token list (new helper)
    UI->>UB: GET /v1/tokens?chainId&tokenAddress&limit=1000&includePrices=false<br/>Headers: x-client-id
    UB-->>UI: 200 OK { data: TokenMetadata[] }
    alt error
        UB-->>UI: !200 + error text
        UI-->>UI: Throw Error(text)
    end
    end
Loading
sequenceDiagram
    autonumber
    participant UI as UI (server/context)
    participant Auth as Auth Provider
    participant UB as Universal Bridge API

    rect rgba(200,255,200,0.25)
    note over UI: Add token (modified route)
    UI->>Auth: getAuthToken()
    Auth-->>UI: Bearer token
    UI->>UB: POST /v1/tokens { chainId, tokenAddress }<br/>Headers: Authorization: Bearer, x-client-id: project.publishableKey
    UB-->>UI: 200 OK { data: TokenMetadata[] }
    alt error
        UB-->>UI: !200 + error text
        UI-->>UI: Throw Error(text)
    end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Assessment against linked issues

Objective Addressed Explanation
Remove server action for fetching token list (MNY-127)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Introduce POST addUniversalBridgeTokenRoute with Bearer auth (apps/dashboard/src/@/api/universal-bridge/tokens.ts, lines N/A) Adding a token via POST and auth changes are not part of removing the fetch server action for token list.
Extract TokenMetadata to a new module (apps/dashboard/src/@/api/universal-bridge/types.ts, lines N/A) Type extraction is ancillary and not strictly required to remove the server action.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • TEAM-0000: Entity not found: Issue - Could not find referenced Issue.
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 08-29-_mny-127_dashboard_remove_unnecessary_server_action_for_fetching_token_list

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbit in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbit in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbit gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbit read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbit help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbit ignore or @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbit summary or @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbit or @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@MananTank MananTank marked this pull request as ready for review August 28, 2025 19:30
@vercel
Copy link

vercel bot commented Aug 28, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
thirdweb-www Ready Ready Preview Comment Aug 28, 2025 9:45pm
4 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
docs-v2 Skipped Skipped Aug 28, 2025 9:45pm
nebula Skipped Skipped Aug 28, 2025 9:45pm
thirdweb_playground Skipped Skipped Aug 28, 2025 9:45pm
wallet-ui Skipped Skipped Aug 28, 2025 9:45pm

@MananTank MananTank requested a review from a team as a code owner August 28, 2025 19:30
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground August 28, 2025 19:30 Inactive
@MananTank MananTank requested a review from a team as a code owner August 28, 2025 19:30
@vercel vercel bot temporarily deployed to Preview – nebula August 28, 2025 19:30 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 August 28, 2025 19:30 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui August 28, 2025 19:30 Inactive
@github-actions github-actions bot added the Dashboard Involves changes to the Dashboard. label Aug 28, 2025
Copy link
Member Author

MananTank commented Aug 28, 2025


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • merge-queue - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@codecov
Copy link

codecov bot commented Aug 28, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 56.55%. Comparing base (51f7418) to head (67616c2).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7940   +/-   ##
=======================================
  Coverage   56.55%   56.55%           
=======================================
  Files         904      904           
  Lines       58581    58581           
  Branches     4142     4142           
=======================================
  Hits        33128    33128           
  Misses      25347    25347           
  Partials      106      106           
Flag Coverage Δ
packages 56.55% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Contributor

github-actions bot commented Aug 28, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
thirdweb (esm) 64.06 KB (0%) 1.3 s (0%) 303 ms (+73.04% 🔺) 1.6 s
thirdweb (cjs) 357.05 KB (0%) 7.2 s (0%) 1.3 s (+6.86% 🔺) 8.5 s
thirdweb (minimal + tree-shaking) 5.73 KB (0%) 115 ms (0%) 63 ms (+662.87% 🔺) 178 ms
thirdweb/chains (tree-shaking) 526 B (0%) 11 ms (0%) 54 ms (+886.77% 🔺) 64 ms
thirdweb/react (minimal + tree-shaking) 19.15 KB (0%) 383 ms (0%) 113 ms (+408.52% 🔺) 496 ms

@MananTank MananTank force-pushed the 08-29-_mny-127_dashboard_remove_unnecessary_server_action_for_fetching_token_list branch from 156f0ed to d47a876 Compare August 28, 2025 21:20
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground August 28, 2025 21:20 Inactive
@vercel vercel bot temporarily deployed to Preview – nebula August 28, 2025 21:20 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui August 28, 2025 21:20 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 August 28, 2025 21:20 Inactive
@graphite-app graphite-app bot changed the base branch from mny-128 to graphite-base/7940 August 28, 2025 21:26
@graphite-app
Copy link
Contributor

graphite-app bot commented Aug 28, 2025

Merge activity

@graphite-app graphite-app bot changed the base branch from graphite-base/7940 to main August 28, 2025 21:37
…ken list (#7940)

<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the token management in the universal bridge API, including the introduction of a new `TokenMetadata` type and the relocation of the `getUniversalBridgeTokens` function to a new file. It also updates import paths for consistency.

### Detailed summary
- Added `TokenMetadata` type in `apps/dashboard/src/@/api/universal-bridge/types.ts`.
- Updated import path for `getUniversalBridgeTokens` in `apps/dashboard/src/@/hooks/tokens.ts` and `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx`.
- Created `getUniversalBridgeTokens` function in `apps/dashboard/src/@/api/universal-bridge/token-list.ts`.
- Removed old `getUniversalBridgeTokens` function and `TokenMetadata` type from `apps/dashboard/src/@/api/universal-bridge/tokens.ts`.

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->
@graphite-app graphite-app bot force-pushed the 08-29-_mny-127_dashboard_remove_unnecessary_server_action_for_fetching_token_list branch from d47a876 to 67616c2 Compare August 28, 2025 21:37
@vercel vercel bot temporarily deployed to Preview – nebula August 28, 2025 21:37 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui August 28, 2025 21:37 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 August 28, 2025 21:37 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground August 28, 2025 21:37 Inactive
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/dashboard/src/@/api/universal-bridge/tokens.ts (1)

7-35: Harden server call: validate inputs, add timeout, and explicit return type

Add minimal input checks, a fetch timeout, no-store caching, and better error messages. Also declare the return type.

 import type { ProjectResponse } from "@thirdweb-dev/service-utils";
 import { getAuthToken } from "@/api/auth-token";
 import { UB_BASE_URL } from "./constants";
 import type { TokenMetadata } from "./types";
+import { getAddress } from "thirdweb";
 
-export async function addUniversalBridgeTokenRoute(props: {
+export async function addUniversalBridgeTokenRoute(props: {
   chainId: number;
   tokenAddress: string;
   project: ProjectResponse;
-}) {
+}): Promise<TokenMetadata[]> {
+  if (!Number.isInteger(props.chainId) || props.chainId <= 0) {
+    throw new Error("Invalid chainId");
+  }
+  let tokenAddress: string;
+  try {
+    tokenAddress = getAddress(props.tokenAddress);
+  } catch {
+    throw new Error("Invalid tokenAddress");
+  }
+
   const authToken = await getAuthToken();
   const url = new URL(`${UB_BASE_URL}/v1/tokens`);
 
-  const res = await fetch(url.toString(), {
-    body: JSON.stringify({
-      chainId: props.chainId,
-      tokenAddress: props.tokenAddress,
-    }),
-    headers: {
-      Authorization: `Bearer ${authToken}`,
-      "Content-Type": "application/json",
-      "x-client-id": props.project.publishableKey,
-    } as Record<string, string>,
-    method: "POST",
-  });
+  const ac = new AbortController();
+  const t = setTimeout(() => ac.abort(), 15_000);
+  let res: Response;
+  try {
+    res = await fetch(url.toString(), {
+      body: JSON.stringify({
+        chainId: props.chainId,
+        tokenAddress,
+      }),
+      headers: {
+        Authorization: `Bearer ${authToken}`,
+        "Content-Type": "application/json",
+        "x-client-id": props.project.publishableKey,
+      },
+      method: "POST",
+      cache: "no-store",
+      signal: ac.signal,
+      next: { revalidate: 0 },
+    });
+  } finally {
+    clearTimeout(t);
+  }
 
   if (!res.ok) {
-    const text = await res.text();
-    throw new Error(text);
+    // Treat duplicate/exists as non-fatal (idempotent add)
+    if (res.status === 409) {
+      return [];
+    }
+    const text = await res.text().catch(() => "");
+    throw new Error(`[${res.status}] ${text || res.statusText}`);
   }
 
-  const json = await res.json();
-  return json.data as Array<TokenMetadata>;
+  const json = (await res.json().catch(() => ({}))) as { data?: TokenMetadata[] };
+  return (json.data ?? []) as TokenMetadata[];
 }
apps/dashboard/src/@/hooks/tokens.ts (1)

11-15: Set React Query staleTime per guidelines (≥60s)

Prevents refetch thrash and matches the dashboard guideline.

   return useQuery({
     enabled,
     queryFn: () => getUniversalBridgeTokens({ chainId }),
     queryKey: ["universal-bridge-tokens", chainId],
+    staleTime: 60_000,
   });
🧹 Nitpick comments (4)
apps/dashboard/src/@/components/blocks/TokenSelector.tsx (1)

52-67: Avoid duplicate native token by normalizing address comparison

If API returns lowercase addresses, the strict equality may miss the native token and add a duplicate. Normalize using getAddress.

-      const hasNativeToken = tokensQuery.data.some(
-        (token) => token.address === checksummedNativeTokenAddress,
-      );
+      const hasNativeToken = tokensQuery.data.some((token) => {
+        try {
+          return getAddress(token.address) === checksummedNativeTokenAddress;
+        } catch {
+          return token.address.toLowerCase() === checksummedNativeTokenAddress.toLowerCase();
+        }
+      });
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx (1)

112-121: Optional: avoid extra network by reusing selected token’s decimals

You already have TokenSelector; consider storing the selected TokenMetadata (or just decimals) in form state to skip this GET during submission.

apps/dashboard/src/@/api/universal-bridge/token-list.ts (2)

20-26: Clean up headers; avoid unnecessary Content-Type on GET; pass signal; omit empty client-id.

Removes preflight-triggering header, adds Accept, and wires cancellation.

-  const res = await fetch(url.toString(), {
-    headers: {
-      "Content-Type": "application/json",
-      "x-client-id": NEXT_PUBLIC_DASHBOARD_CLIENT_ID,
-    } as Record<string, string>,
-    method: "GET",
-  });
+  const headers: HeadersInit = { Accept: "application/json" };
+  if (NEXT_PUBLIC_DASHBOARD_CLIENT_ID) {
+    (headers as Record<string, string>)["x-client-id"] = NEXT_PUBLIC_DASHBOARD_CLIENT_ID;
+  }
+  const res = await fetch(url.toString(), {
+    method: "GET",
+    headers,
+    signal: props.signal,
+  });

28-31: Improve error surface: include status and JSON message when available.

Easier debugging and fewer HTML error blobs in thrown messages.

-  if (!res.ok) {
-    const text = await res.text();
-    throw new Error(text);
-  }
+  if (!res.ok) {
+    let message = "";
+    const ct = res.headers.get("content-type") || "";
+    if (ct.includes("application/json")) {
+      try {
+        const err = await res.json();
+        message = (err && (err.message || err.error)) || JSON.stringify(err);
+      } catch {
+        message = await res.text();
+      }
+    } else {
+      message = await res.text();
+    }
+    throw new Error(`${res.status} ${res.statusText}: ${message}`);
+  }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 51f7418 and 67616c2.

📒 Files selected for processing (6)
  • apps/dashboard/src/@/api/universal-bridge/token-list.ts (1 hunks)
  • apps/dashboard/src/@/api/universal-bridge/tokens.ts (1 hunks)
  • apps/dashboard/src/@/api/universal-bridge/types.ts (1 hunks)
  • apps/dashboard/src/@/components/blocks/TokenSelector.tsx (1 hunks)
  • apps/dashboard/src/@/hooks/tokens.ts (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from @/types or local types.ts barrels
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose

Files:

  • apps/dashboard/src/@/api/universal-bridge/types.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
  • apps/dashboard/src/@/hooks/tokens.ts
  • apps/dashboard/src/@/components/blocks/TokenSelector.tsx
  • apps/dashboard/src/@/api/universal-bridge/token-list.ts
  • apps/dashboard/src/@/api/universal-bridge/tokens.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)

Files:

  • apps/dashboard/src/@/api/universal-bridge/types.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
  • apps/dashboard/src/@/hooks/tokens.ts
  • apps/dashboard/src/@/components/blocks/TokenSelector.tsx
  • apps/dashboard/src/@/api/universal-bridge/token-list.ts
  • apps/dashboard/src/@/api/universal-bridge/tokens.ts
apps/{dashboard,playground-web}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/{dashboard,playground-web}/**/*.{ts,tsx}: Import UI primitives from @/components/ui/* (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Use NavLink for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Use cn() from @/lib/utils for conditional class logic
Use design system tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components (Node edge): Start files with import "server-only";
Client Components (browser): Begin files with 'use client';
Always call getAuthToken() to retrieve JWT from cookies on server side
Use Authorization: Bearer header – never embed tokens in URLs
Return typed results (e.g., Project[], User[]) – avoid any
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stable queryKeys for React Query cache hits
Configure staleTime/cacheTime in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never import posthog-js in server components

Files:

  • apps/dashboard/src/@/api/universal-bridge/types.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
  • apps/dashboard/src/@/hooks/tokens.ts
  • apps/dashboard/src/@/components/blocks/TokenSelector.tsx
  • apps/dashboard/src/@/api/universal-bridge/token-list.ts
  • apps/dashboard/src/@/api/universal-bridge/tokens.ts
🧠 Learnings (10)
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout changes.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout PR #7888.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
📚 Learning: 2025-08-27T22:11:41.748Z
Learnt from: MananTank
PR: thirdweb-dev/js#7933
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx:465-473
Timestamp: 2025-08-27T22:11:41.748Z
Learning: In the token creation flow (create-token-page-impl.tsx), the createTokenOnUniversalBridge() call is intentionally not awaited (fire-and-forget pattern) to allow the token creation process to complete immediately without waiting for the bridge operation. This is a deliberate design choice to prioritize user experience by not blocking the main flow with supplementary bridge operations.

Applied to files:

  • apps/dashboard/src/@/hooks/tokens.ts
  • apps/dashboard/src/@/api/universal-bridge/token-list.ts
  • apps/dashboard/src/@/api/universal-bridge/tokens.ts
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Use design system tokens (e.g., `bg-card`, `border-border`, `text-muted-foreground`)

Applied to files:

  • apps/dashboard/src/@/components/blocks/TokenSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps

Applied to files:

  • apps/dashboard/src/@/components/blocks/TokenSelector.tsx
📚 Learning: 2025-05-30T17:14:25.332Z
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.

Applied to files:

  • apps/dashboard/src/@/components/blocks/TokenSelector.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Anything that consumes hooks from `tanstack/react-query` or thirdweb SDKs.

Applied to files:

  • apps/dashboard/src/@/components/blocks/TokenSelector.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/api/**/*.{ts,tsx} : Pass the token in the `Authorization: Bearer` header – never embed it in the URL.

Applied to files:

  • apps/dashboard/src/@/api/universal-bridge/tokens.ts
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Use `Authorization: Bearer` header – never embed tokens in URLs

Applied to files:

  • apps/dashboard/src/@/api/universal-bridge/tokens.ts
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Keep tokens secret via internal API routes or server actions

Applied to files:

  • apps/dashboard/src/@/api/universal-bridge/tokens.ts
🧬 Code graph analysis (1)
apps/dashboard/src/@/api/universal-bridge/token-list.ts (3)
apps/dashboard/src/@/api/universal-bridge/constants.ts (1)
  • UB_BASE_URL (1-1)
apps/dashboard/src/@/constants/public-envs.ts (1)
  • NEXT_PUBLIC_DASHBOARD_CLIENT_ID (1-2)
apps/dashboard/src/@/api/universal-bridge/types.ts (1)
  • TokenMetadata (1-8)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: Unit Tests
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: Size
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (7)
apps/dashboard/src/@/api/universal-bridge/types.ts (1)

1-8: Type extraction looks good

TokenMetadata definition is concise and matches current usages.

apps/dashboard/src/@/components/blocks/TokenSelector.tsx (1)

8-8: Import path update is correct

Switching to "@/api/universal-bridge/types" aligns with the new types module.

apps/dashboard/src/@/api/universal-bridge/tokens.ts (1)

1-5: No remaining imports of getUniversalBridgeTokens from tokens.ts
Removal of the GET helper is complete—no lingering imports were found.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx (2)

14-15: Import now targets the client-safe GET helper

Looks correct for removing server action usage here.


92-101: getUniversalBridgeTokens helper is client-safe: token-list.ts contains no "use server" directives, auth cookies, or server-only imports.

apps/dashboard/src/@/hooks/tokens.ts (1)

2-2: Import path update looks good

Hook now sources the client-side GET helper.

apps/dashboard/src/@/api/universal-bridge/token-list.ts (1)

5-35: Optional: add Next.js fetch revalidation
If this API is primarily called server-side, pass { next: { revalidate: 60 } } to fetch; on the client, the useQuery wrapper in contract-hooks.ts already sets staleTime: 60 * 60 * 1000.

Comment on lines +5 to +8
export async function getUniversalBridgeTokens(props: {
chainId?: number;
address?: string;
}) {
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add explicit return type (and optional AbortSignal).

Conform to TS guidelines and make cancellation possible without breaking callers.

-export async function getUniversalBridgeTokens(props: {
-  chainId?: number;
-  address?: string;
-}) {
+export async function getUniversalBridgeTokens(props: {
+  chainId?: number;
+  address?: string;
+  signal?: AbortSignal;
+}): Promise<TokenMetadata[]> {
📝 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
export async function getUniversalBridgeTokens(props: {
chainId?: number;
address?: string;
}) {
export async function getUniversalBridgeTokens(props: {
chainId?: number;
address?: string;
signal?: AbortSignal;
}): Promise<TokenMetadata[]> {
🤖 Prompt for AI Agents
In apps/dashboard/src/@/api/universal-bridge/token-list.ts around lines 5–8,
update the function signature to include an explicit return type and an optional
AbortSignal parameter: e.g. export async function
getUniversalBridgeTokens(props: { chainId?: number; address?: string; signal?:
AbortSignal; }): Promise<YourTokenType[]> { ... }. Replace YourTokenType with
the appropriate token interface (or import it), ensure all internal fetch/async
calls accept/forward props.signal to enable cancellation, and update any
callers/tests if needed to satisfy the new return type and optional signal
parameter.

Comment on lines +9 to +10
const url = new URL(`${UB_BASE_URL}/v1/tokens`);

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

Guard missing UB_BASE_URL and build URL with a base.

Avoid “Invalid URL” at runtime and produce a clear config error.

-  const url = new URL(`${UB_BASE_URL}/v1/tokens`);
+  if (!UB_BASE_URL) {
+    throw new Error("Missing NEXT_PUBLIC_THIRDWEB_BRIDGE_HOST for Universal Bridge.");
+  }
+  const url = new URL("/v1/tokens", UB_BASE_URL);
📝 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 url = new URL(`${UB_BASE_URL}/v1/tokens`);
// apps/dashboard/src/@/api/universal-bridge/token-list.ts
// …previous code…
if (!UB_BASE_URL) {
throw new Error("Missing NEXT_PUBLIC_THIRDWEB_BRIDGE_HOST for Universal Bridge.");
}
const url = new URL("/v1/tokens", UB_BASE_URL);
// …subsequent code…
🤖 Prompt for AI Agents
In apps/dashboard/src/@/api/universal-bridge/token-list.ts around lines 9 to 10,
the code constructs a URL with `${UB_BASE_URL}/v1/tokens` without validating
UB_BASE_URL which can cause an "Invalid URL" at runtime; add a guard that throws
a clear, descriptive configuration error if UB_BASE_URL is missing or empty, and
build the token endpoint using the URL constructor with the base parameter
(e.g., new URL('/v1/tokens', UB_BASE_URL)) to avoid malformed URL creation.

Comment on lines +11 to +16
if (props.chainId) {
url.searchParams.append("chainId", String(props.chainId));
}
if (props.address) {
url.searchParams.append("tokenAddress", props.address);
}
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

Fix truthy check for chainId (0 should be valid).

Use a nullish check so chainId=0 isn’t dropped.

-  if (props.chainId) {
+  if (props.chainId != null) {
     url.searchParams.append("chainId", String(props.chainId));
   }
-  if (props.address) {
+  if (props.address) {
     url.searchParams.append("tokenAddress", props.address);
   }

Optional: normalize props.address to lowercase if backend is case-insensitive.

📝 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
if (props.chainId) {
url.searchParams.append("chainId", String(props.chainId));
}
if (props.address) {
url.searchParams.append("tokenAddress", props.address);
}
if (props.chainId != null) {
url.searchParams.append("chainId", String(props.chainId));
}
if (props.address) {
url.searchParams.append("tokenAddress", props.address);
}
🤖 Prompt for AI Agents
In apps/dashboard/src/@/api/universal-bridge/token-list.ts around lines 11 to
16, the current truthy check drops chainId when it is 0; change the condition to
a nullish check (e.g., props.chainId != null) so 0 is allowed, keep appending
chainId via String(props.chainId). Also change the address check to explicitly
test for null/undefined (e.g., props.address != null) and, if the backend is
case-insensitive, normalize by using props.address.toLowerCase() before
appending tokenAddress.

Comment on lines +33 to +35
const json = await res.json();
return json.data as Array<TokenMetadata>;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Return typed payload and validate shape.

Avoids implicit any, aligns with “return typed results”.

-  const json = await res.json();
-  return json.data as Array<TokenMetadata>;
+  const { data } = (await res.json()) as { data: TokenMetadata[] };
+  if (!Array.isArray(data)) {
+    throw new Error("Malformed response: expected data: TokenMetadata[].");
+  }
+  return data;
📝 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 json = await res.json();
return json.data as Array<TokenMetadata>;
}
const { data } = (await res.json()) as { data: TokenMetadata[] };
if (!Array.isArray(data)) {
throw new Error("Malformed response: expected data: TokenMetadata[].");
}
return data;
}
🤖 Prompt for AI Agents
In apps/dashboard/src/@/api/universal-bridge/token-list.ts around lines 33 to
35, the function currently returns json.data without a typed response or
validation; change it to return a properly typed payload (define or import an
interface such as { data: TokenMetadata[] } for the response) and validate the
runtime shape before returning (e.g., ensure json is an object and json.data is
an array of objects, optionally checking required TokenMetadata fields); if
validation fails, throw a descriptive error; finally return json.data typed as
Array<TokenMetadata>.

@graphite-app graphite-app bot merged commit 67616c2 into main Aug 28, 2025
25 checks passed
@graphite-app graphite-app bot deleted the 08-29-_mny-127_dashboard_remove_unnecessary_server_action_for_fetching_token_list branch August 28, 2025 21:46
@vercel vercel bot temporarily deployed to Production – docs-v2 August 28, 2025 21:46 Inactive
@vercel vercel bot temporarily deployed to Production – thirdweb_playground August 28, 2025 21:46 Inactive
@vercel vercel bot temporarily deployed to Production – wallet-ui August 28, 2025 21:46 Inactive
@vercel vercel bot temporarily deployed to Production – nebula August 28, 2025 21:46 Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Dashboard Involves changes to the Dashboard.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants