Skip to content

Conversation

@d4mr
Copy link
Member

@d4mr d4mr commented Oct 14, 2025

[Dashboard] Feature: Add Solana Transactions and Server Wallets tables

Notes for the reviewer

This PR introduces dedicated tables for Solana transactions and server wallets on the dashboard's transactions page, mirroring the existing functionality for EVM.

Key features include:

  • Displaying Solana transactions with details like transaction ID, signer, chain, status, and signature.
  • Status badges and clickable Solscan links for transactions.
  • Listing Solana server wallets with public keys, labels, and creation dates.
  • Functionality to create new Solana wallets via a modal.
  • Pagination support for both tables.
  • All Solana data is fetched via the Engine Cloud API.

Important: A large binary file apps/dashboard/core was added in this PR. This appears to be a biome binary and should likely not be part of this PR. Please advise on its removal or purpose.

How to test

  1. Ensure an Engine instance is configured with Solana support for a project.
  2. Navigate to the Transactions page for a project (/{team_slug}/{project_slug}/transactions).
  3. Verify that the "Solana Transactions" and "Solana Server Wallets" tables are displayed below the EVM tables.
  4. Test pagination on the Solana Server Wallets table.
  5. Attempt to create a new Solana wallet using the "Create Wallet" button in the Solana Server Wallets section.
  6. Verify transaction filtering by status on the Solana Transactions table.
  7. Confirm Solscan links are correctly generated and clickable for Solana transaction signatures.

Slack Thread

Open in Cursor Open in Web


PR-Codex overview

This PR focuses on enhancing Solana wallet functionality within the application. It includes the addition of new types, components, and logic for handling Solana transactions, as well as updates to existing wallet management features.

Detailed summary

  • Removed old tx-table and wallet-table components.
  • Updated GetSolanaAccountsData type to use items instead of accounts.
  • Introduced SolanaWallet type for wallet details.
  • Added statusDetails for transaction statuses.
  • Replaced TransactionsTable with UnifiedTransactionsTable.
  • Enhanced transaction layout to support async parameters.
  • Implemented Solana transaction fetching and activity logs.
  • Created new utility functions for Solana transaction URLs and names.
  • Added CreateSolanaWallet component for wallet creation.
  • Updated listSolanaAccounts and createSolanaAccount functions for better account management.
  • Improved UI for transaction details and activity logs.
  • Added Solana transaction testing functionality.

The following files were skipped due to too many changes: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/transactions-table.client.tsx

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

Summary by CodeRabbit

  • New Features

    • Unified transactions table for EVM and Solana with chain switcher, filters, auto-update, and pagination.
    • Solana transaction details view (overview, activity logs, raw JSON) with explorer links.
    • Send-test Solana transaction flow (Devnet) with wallet selection and toasts.
    • Server wallets management now includes Solana (listing, create flow, balances, actions) and Solana-permissions upgrade UI.
    • Hoverable Solana address badge with copy/preview.
  • Bug Fixes

    • Fixed Solana accounts response handling in Vault SDK.
  • Style

    • Improved spacing and padding on transaction detail layout.
  • Chores

    • Vault SDK patch bump.

@cursor
Copy link

cursor bot commented Oct 14, 2025

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@vercel
Copy link

vercel bot commented Oct 14, 2025

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

Project Deployment Preview Comments Updated (UTC)
thirdweb-www Building Building Oct 15, 2025 9:14pm
4 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
docs-v2 Skipped Skipped Oct 15, 2025 9:14pm
nebula Skipped Skipped Oct 15, 2025 9:14pm
thirdweb_playground Skipped Skipped Oct 15, 2025 9:14pm
wallet-ui Skipped Skipped Oct 15, 2025 9:14pm

@vercel vercel bot temporarily deployed to Preview – wallet-ui October 14, 2025 20:49 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 October 14, 2025 20:49 Inactive
@vercel vercel bot temporarily deployed to Preview – nebula October 14, 2025 20:49 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground October 14, 2025 20:49 Inactive
@changeset-bot
Copy link

changeset-bot bot commented Oct 14, 2025

🦋 Changeset detected

Latest commit: b83e372

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@thirdweb-dev/vault-sdk Patch

Not sure what this means? Click here to learn what changesets are.

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

@graphite-app
Copy link
Contributor

graphite-app bot commented Oct 14, 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.

@github-actions github-actions bot added the Dashboard Involves changes to the Dashboard. label Oct 14, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 14, 2025

Walkthrough

Adds comprehensive Solana support: new Solana types/utilities, Vault-backed Solana wallet listing/creation and permission upgrade flows, SendTestSolanaTransaction UI and modal, unified EVM+Solana transactions table and details UI, server-side Vault client helpers, and related wiring and type adjustments.

Changes

Cohort / File(s) Summary
Release/Versioning
.changeset/eleven-mangos-travel.md
Patch bump for @thirdweb-dev/vault-sdk; notes bug fix for Solana accounts response shape.
Unified Transactions (EVM + Solana)
apps/.../transactions/analytics/analytics-page.tsx, apps/.../transactions/components/transactions-table.client.tsx, apps/.../transactions/analytics/tx-table/types.ts, apps/.../transactions/analytics/tx-table/tx-table-ui.tsx (deleted), apps/.../transactions/analytics/tx-table/tx-table.tsx (deleted)
Replaces legacy TransactionsTable with UnifiedTransactionsTable supporting EVM and Solana, per-chain fetchers/filters/pagination; moves statusDetails to new types file and deletes old tx-table UI and wrapper.
FTUX & Send-Test Transactions
apps/.../transactions/analytics/ftux.client.tsx, apps/.../transactions/analytics/send-test-solana-tx.client.tsx
Adds solanaWallets and testSolanaTxWithWallet props to FTUX; introduces SendTestSolanaTransaction and modal with form validation, vault-aware POST, toast handling, and react-query invalidation.
Solana Types & Utilities
apps/.../transactions/analytics/solana-tx-table/types.ts, apps/.../transactions/lib/solana-utils.ts
Adds Solana transaction types/response shapes and utilities getSolscanUrl and getSolanaNetworkName.
Transaction Details Flow
apps/.../transactions/tx/[id]/page.tsx, apps/.../transactions/tx/[id]/solana-transaction-details-ui.tsx, apps/.../transactions/tx/[id]/layout.tsx
Parallel-fetches EVM and Solana transactions; prefers Solana when present; adds SolanaTransactionDetailsUI; layout changed to async and spacing/href updates.
Server Wallets (EVM + Solana) — New
apps/.../transactions/components/server-wallets-table.client.tsx, apps/.../transactions/page.tsx
New ServerWalletsTable supporting EVM and Solana tabs, balances, per-wallet actions (fund, send test tx, set default), pagination, and Solana permission propagation; page wires Solana accounts and pagination.
Solana Vault Integration (server)
apps/.../transactions/solana-wallets/lib/vault.client.ts, packages/vault-sdk/src/types.ts
Adds listSolanaAccounts and createSolanaAccount server helpers using Vault SDK; introduces upgradeAccessTokensForSolana (also in vault.client.ts); updates vault-sdk type key from accountsitems.
Solana Wallet UI (client)
apps/.../transactions/solana-wallets/components/create-solana-wallet.client.tsx, apps/.../transactions/solana-wallets/wallet-table/types.ts, apps/.../transactions/solana-wallets/components/upgrade-solana-permissions.client.tsx
Adds CreateSolanaWallet dialog, new SolanaWallet type, and UpgradeSolanaPermissions UI to enable Solana access (handles ejected/non-ejected vault flows).
Activity Log / Analytics Lib
apps/.../transactions/lib/analytics.ts
Adds getSingleSolanaTransaction and getSolanaTransactionActivityLogs; normalizes 401/404 handling for activity logs to return empty arrays.
Solana UI Components
apps/dashboard/src/@/components/blocks/solana-address.tsx
Adds SolanaAddress hoverable copy/display component.
Removed Client UIs (replaced/refactored)
apps/.../transactions/analytics/tx-table/tx-table-ui.tsx (deleted), apps/.../transactions/analytics/tx-table/tx-table.tsx (deleted), apps/.../transactions/server-wallets/wallet-table/wallet-table-ui.client.tsx (deleted), apps/.../transactions/server-wallets/wallet-table/wallet-table.tsx (deleted)
Deletes legacy transaction and server-wallet UI modules; functionality migrated into unified/new components.
Minor UI/Text & Routing
apps/.../components/ProjectSidebarLayout.tsx, apps/.../wallets/page.tsx
Sidebar labels adjusted (Transactions marked New); wallets page wired to fetch Solana accounts and provide split EVM/Solana props and pagination; dynamic = "force-dynamic" added where applicable.

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant Dashboard
  participant UnifiedTable as UnifiedTransactionsTable
  participant Engine as Engine Cloud Proxy

  User->>Dashboard: Open Transactions Analytics
  Dashboard->>UnifiedTable: Render (project, team, client)
  UnifiedTable->>UnifiedTable: Apply chain/filter/page
  alt Active = EVM
    UnifiedTable->>Engine: GET /v1/transactions?limit&page&status&id&from
    Engine-->>UnifiedTable: TransactionsResponse
  else Active = Solana
    UnifiedTable->>Engine: GET /v1/solana/transactions?limit&page&status&id&from
    Engine-->>UnifiedTable: SolanaTransactionsResponse
  end
  UnifiedTable-->>Dashboard: Render rows & pagination
Loading
sequenceDiagram
  actor User
  participant Dashboard
  participant Modal as SendTestSolanaTransactionModal
  participant Engine as Engine Cloud Proxy
  participant Query as React Query

  User->>Dashboard: Click "Send test Solana tx"
  Dashboard->>Modal: Open with wallets + project
  User->>Modal: Select wallet, enter token/secret, Submit
  Modal->>Engine: POST /v1/solana/transactions (headers vary by vault mode)
  alt Success
    Engine-->>Modal: 200 OK
    Modal-->>User: Success toast + auto-close
    Modal->>Query: Invalidate solana-transactions
  else Error
    Engine-->>Modal: Error
    Modal-->>User: Error toast
  end
Loading
sequenceDiagram
  participant Page as /transactions/tx/[id]
  participant Lib as analytics.ts
  participant UI as Details UI

  Page->>Lib: getSingleSolanaTransaction(id)
  Page->>Lib: getSingleTransaction(id)
  par Parallel fetch
  end
  alt Solana found
    Page->>Lib: getSolanaTransactionActivityLogs(id)
    Lib-->>Page: logs[]
    Page->>UI: SolanaTransactionDetailsUI(tx, logs)
  else EVM found
    Page->>Lib: getTransactionActivityLogs(id)
    Lib-->>Page: logs[]
    Page->>UI: TransactionDetailsUI(tx, decoded, logs)
  else none
    Page-->>Page: notFound()
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly and accurately captures the primary change of adding Solana transactions and wallets tables to the dashboard, matching the main focus of the pull request without extraneous detail.
Description Check ✅ Passed The description adheres to the repository’s template by providing a formatted title, a Notes for the reviewer section outlining key changes, and a detailed How to test guide, giving reviewers clear context and testing steps.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cursor/add-solana-transactions-and-wallets-tables-2ff0

Comment @coderabbitai help to get the list of available commands and usage tips.

Co-authored-by: prithvish <[email protected]>
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground October 14, 2025 20:53 Inactive
@vercel vercel bot temporarily deployed to Preview – nebula October 14, 2025 20:53 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 October 14, 2025 20:53 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui October 14, 2025 20:54 Inactive
@github-actions
Copy link
Contributor

github-actions bot commented Oct 14, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
thirdweb (esm) 64.51 KB (0%) 1.3 s (0%) 227 ms (+67.54% 🔺) 1.6 s
thirdweb (cjs) 365.68 KB (0%) 7.4 s (0%) 1.2 s (+10.43% 🔺) 8.5 s
thirdweb (minimal + tree-shaking) 5.73 KB (0%) 115 ms (0%) 95 ms (+1789.1% 🔺) 210 ms
thirdweb/chains (tree-shaking) 526 B (0%) 11 ms (0%) 72 ms (+2350.92% 🔺) 82 ms
thirdweb/react (minimal + tree-shaking) 19.13 KB (0%) 383 ms (0%) 79 ms (+1493.21% 🔺) 461 ms

@vercel vercel bot temporarily deployed to Preview – nebula October 14, 2025 21:37 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui October 14, 2025 21:37 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 October 14, 2025 21:37 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground October 14, 2025 21:37 Inactive
@d4mr d4mr marked this pull request as ready for review October 14, 2025 23:14
@d4mr d4mr requested review from a team as code owners October 14, 2025 23:14
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: 0

🧹 Nitpick comments (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/lib/vault.client.ts (2)

79-81: Improve error message extraction.

Using JSON.stringify(response.error) produces opaque error messages. Extract a human-readable message if available.

Apply this diff:

         error: response.error
-          ? new Error(JSON.stringify(response.error))
+          ? new Error(response.error.message || JSON.stringify(response.error))
           : new Error("Failed to fetch Solana accounts"),

Apply the same pattern at line 177 in createSolanaAccount.


44-53: Consider logging missing configuration.

The function silently returns an error when managementAccessToken or vault URL is missing. For debugging, consider logging a warning.

   if (!managementAccessToken || !NEXT_PUBLIC_THIRDWEB_VAULT_URL) {
+    console.warn("Vault client: missing managementAccessToken or NEXT_PUBLIC_THIRDWEB_VAULT_URL");
     return {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 9f37e52 and bc59fdd.

📒 Files selected for processing (1)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/lib/vault.client.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{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

**/*.{ts,tsx}: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from @/types where applicable
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/lib/vault.client.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/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/lib/vault.client.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/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/lib/vault.client.ts
apps/{dashboard,playground}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

apps/{dashboard,playground}/**/*.{ts,tsx}: Import UI primitives from @/components/ui/_ (e.g., Button, Input, Tabs, Card)
Use NavLink for internal navigation to get active state handling
Use Tailwind CSS for styling; no inline styles
Merge class names with cn() from @/lib/utils for conditional classes
Stick to design tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components must start with import "server-only"; use next/headers, server‑only env, heavy data fetching, and redirect() where appropriate
Client Components must start with 'use client'; handle interactivity with hooks and browser APIs
Server-side data fetching: call getAuthToken() from cookies, send Authorization: Bearer <token> header, and return typed results (avoid any)
Client-side data fetching: wrap calls in React Query with descriptive, stable queryKeys and set sensible staleTime/cacheTime (≥ 60s default); keep tokens secret via internal routes or server actions
Do not import posthog-js in server components (client-side only)

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/lib/vault.client.ts
🧬 Code graph analysis (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/lib/vault.client.ts (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/wallet-table/types.ts (1)
  • SolanaWallet (1-11)
apps/dashboard/src/@/constants/public-envs.ts (1)
  • NEXT_PUBLIC_THIRDWEB_VAULT_URL (4-5)
⏰ 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). (3)
  • GitHub Check: Size
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (5)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/lib/vault.client.ts (5)

1-9: LGTM! Server directive and imports are correct.

The "use server" directive is properly placed, and imports follow the expected patterns for server-side vault integration.


11-27: Internal types are well-defined.

The local interface definitions provide clear contracts for vault API responses and internal mapping.


163-168: Verify teamId usage in metadata.

The function passes teamId in metadata (line 166), but the SolanaWallet type definition (from types.ts) does not include teamId in its metadata shape. Confirm whether:

  1. The vault API requires/stores teamId, or
  2. This field should be omitted or the type definition should be updated

67-67: 1-based pagination assumption verified
Callers parse solana_page from searchParams.solana_page ?? "1", so page - 1 correctly converts to Vault SDK’s 0-based index.


89-113: Use API’s totalRecords and avoid client-side pagination breakage
Client-side filtering by projectId skews totalRecords and breaks pagination. Capture and return the SDK’s total before filtering instead of wallets.length:

+  // preserve API total before filtering
+  const apiTotalRecords = response.data.totalRecords ?? response.data.items?.length ?? 0;
   return {
     data: {
       items: wallets,
-      totalRecords: wallets.length,
+      totalRecords: apiTotalRecords,
     },
     error: null,
     success: true,
   };

Prefer passing projectId into vaultListSolanaAccounts({ projectId, … }) if the SDK supports it—confirm in the Vault SDK docs.

@vercel vercel bot temporarily deployed to Preview – wallet-ui October 15, 2025 12:56 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 October 15, 2025 12:56 Inactive
@vercel vercel bot temporarily deployed to Preview – nebula October 15, 2025 12:56 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground October 15, 2025 12:56 Inactive
@codecov
Copy link

codecov bot commented Oct 15, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 55.01%. Comparing base (e830109) to head (b83e372).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #8256   +/-   ##
=======================================
  Coverage   55.01%   55.01%           
=======================================
  Files         919      919           
  Lines       60588    60588           
  Branches     4126     4126           
=======================================
  Hits        33334    33334           
  Misses      27150    27150           
  Partials      104      104           
Flag Coverage Δ
packages 55.01% <ø> (ø)
🚀 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.

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: 2

♻️ Duplicate comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx (1)

204-220: Sensitive tokens are still leaking into ServerWalletsTable.

This client component continues to receive managementAccessToken and the JWT-backed client, exposing privileged credentials to the browser. The earlier review comment on this point still applies—please move privileged actions into server actions/API routes and pass only safe callbacks/data to the client UI.

🧹 Nitpick comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx (1)

51-55: LGTM! Optional accessibility enhancement available.

The implementation correctly highlights the new Transactions feature using the Badge component with proper Tailwind styling. The code follows the coding guidelines for importing UI primitives from @/components/ui/* and using Tailwind CSS classes.

Optionally, consider adding semantic context for screen readers:

              label: (
-               <span className="flex items-center gap-2">
-                 Transactions <Badge>New</Badge>
+               <span className="flex items-center gap-2">
+                 Transactions <Badge aria-label="New feature">New</Badge>
                </span>
              ),
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 bc59fdd and e06fbd9.

📒 Files selected for processing (11)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/send-test-solana-tx.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/transactions-table.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx (5 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/wallet-table/wallet-table-ui.client.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/wallet-table/wallet-table.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/upgrade-solana-permissions.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx (5 hunks)
💤 Files with no reviewable changes (2)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/wallet-table/wallet-table.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/wallet-table/wallet-table-ui.client.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/send-test-solana-tx.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/transactions-table.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{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

**/*.{ts,tsx}: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from @/types where applicable
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/upgrade-solana-permissions.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
**/*.{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/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/upgrade-solana-permissions.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
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/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/upgrade-solana-permissions.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
apps/{dashboard,playground}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

apps/{dashboard,playground}/**/*.{ts,tsx}: Import UI primitives from @/components/ui/_ (e.g., Button, Input, Tabs, Card)
Use NavLink for internal navigation to get active state handling
Use Tailwind CSS for styling; no inline styles
Merge class names with cn() from @/lib/utils for conditional classes
Stick to design tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components must start with import "server-only"; use next/headers, server‑only env, heavy data fetching, and redirect() where appropriate
Client Components must start with 'use client'; handle interactivity with hooks and browser APIs
Server-side data fetching: call getAuthToken() from cookies, send Authorization: Bearer <token> header, and return typed results (avoid any)
Client-side data fetching: wrap calls in React Query with descriptive, stable queryKeys and set sensible staleTime/cacheTime (≥ 60s default); keep tokens secret via internal routes or server actions
Do not import posthog-js in server components (client-side only)

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/upgrade-solana-permissions.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
apps/{dashboard,playground}/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Expose a className prop on the root element of every component

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/upgrade-solana-permissions.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
🧠 Learnings (3)
📚 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 : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/upgrade-solana-permissions.client.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 : Prefer API routes or server actions to keep tokens secret; the browser only sees relative paths.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.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} : Keep tokens secret via internal API routes or server actions

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx
🧬 Code graph analysis (4)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/upgrade-solana-permissions.client.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts (1)
  • upgradeAccessTokensForSolana (804-977)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/wallet-table/types.ts (1)
  • SolanaWallet (1-11)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/lib/vault.client.ts (1)
  • listSolanaAccounts (29-129)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx (1)
  • ServerWalletsTable (85-320)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts (3)
apps/dashboard/src/@/hooks/useApi.ts (1)
  • updateProjectClient (264-289)
packages/service-utils/src/node/index.ts (1)
  • hashSecretKey (187-189)
packages/service-utils/src/core/encryption.ts (2)
  • decrypt (49-96)
  • encrypt (1-47)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/wallet-table/types.ts (1)
  • SolanaWallet (1-11)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx (1)
  • ServerWalletsTable (85-320)
⏰ 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). (2)
  • GitHub Check: Size
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx (1)

88-88: LGTM!

The simplification of the Tokens label is appropriate and aligns with the PR's focus on highlighting the new Transactions features.

Comment on lines +41 to +46
const form = useForm<FormValues>({
defaultValues: {
secretKey: "",
},
resolver: zodResolver(formSchema),
});
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 | 🔴 Critical

Submit button stays disabled.

useForm defaults to mode: "onSubmit", so formState.isValid remains false until after a submit attempt. Because the button is disabled when !isValid, users can never submit. Set mode: "onChange" (or remove the disable check) so validity updates while typing. Example fix:

-  const form = useForm<FormValues>({
+  const form = useForm<FormValues>({
+    mode: "onChange",
     defaultValues: {
       secretKey: "",
     },
     resolver: zodResolver(formSchema),
   });
📝 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 form = useForm<FormValues>({
defaultValues: {
secretKey: "",
},
resolver: zodResolver(formSchema),
});
const form = useForm<FormValues>({
mode: "onChange",
defaultValues: {
secretKey: "",
},
resolver: zodResolver(formSchema),
});
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/upgrade-solana-permissions.client.tsx
around lines 41 to 46, the form is created with useForm but left at the default
mode ("onSubmit"), so formState.isValid stays false and the submit button
remains disabled; change the useForm options to include mode: "onChange" (or
alternatively remove/adjust the isValid-based disabling) so validation runs as
the user types and the submit button becomes enabled when the form is valid.

Comment on lines 190 to 206
<ServerWalletsTable
client={client}
currentPage={currentPage}
evmCurrentPage={currentPage}
evmTotalPages={Math.ceil(eoas.data.totalRecords / pageSize)}
evmTotalRecords={eoas.data.totalRecords}
evmWallets={eoas.data.items as Wallet[]}
managementAccessToken={managementAccessToken ?? undefined}
project={project}
solanaCurrentPage={solanCurrentPage}
solanaTotalPages={Math.ceil(
solanaAccounts.data.totalRecords / pageSize,
)}
solanaTotalRecords={solanaAccounts.data.totalRecords}
solanaWallets={solanaAccounts.data.items}
teamSlug={params.team_slug}
totalPages={Math.ceil(eoas.data.totalRecords / pageSize)}
totalRecords={eoas.data.totalRecords}
wallets={serverWallets ?? []}
solanaPermissionError={isSolanaPermissionError || false}
/>
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 | 🔴 Critical

Stop sending vault tokens to the client table.

ServerWalletsTable is a client component; handing it managementAccessToken (and the JWT-backed client) leaks privileged credentials into the browser. Per dashboard guidelines we must keep these tokens server-side and expose only server actions/API routes for privileged flows. Please refactor so the page performs sensitive work on the server and the client table receives non-sensitive callbacks instead.

d4mr added 2 commits October 16, 2025 02:10
… of github.com:thirdweb-dev/js into cursor/add-solana-transactions-and-wallets-tables-2ff0
@vercel vercel bot temporarily deployed to Preview – docs-v2 October 15, 2025 20:42 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui October 15, 2025 20:42 Inactive
@vercel vercel bot temporarily deployed to Preview – nebula October 15, 2025 20:42 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground October 15, 2025 20:42 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: 1

🧹 Nitpick comments (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts (3)

775-781: Clarify param semantics in docstring (adminKey vs project secret key)

Avoid confusion for ejected vaults vs non-ejected.

Apply this diff:

 /**
  * Upgrades existing access tokens to include Solana permissions
  * This is needed when a project was created before Solana support was added
  *
  * Returns an object with success/error instead of throwing for Next.js server actions
+ * For ejected vaults: pass the Vault admin key via `projectSecretKey`.
+ * For non-ejected vaults: pass the project secret key used to encrypt the admin key.
  */

929-933: Preserve maskedAdminKey if absent (defensive)

If older projects lack maskedAdminKey, set it to avoid UI gaps.

Apply this diff:

           {
             ...engineCloudService,
             managementAccessToken: managementToken.accessToken,
-            encryptedAdminKey,
+            encryptedAdminKey,
             encryptedWalletAccessToken,
+            maskedAdminKey:
+              engineCloudService.maskedAdminKey ?? maskSecret(adminKey),
           },

912-915: Optional: avoid re-encrypting unchanged adminKey

You can keep the existing encrypted admin key and only encrypt/store the new wallet token, reducing churn.

Apply this diff:

-    const [encryptedAdminKey, encryptedWalletAccessToken] = await Promise.all([
-      encrypt(adminKey, projectSecretKey),
-      encrypt(walletToken.accessToken, projectSecretKey),
-    ]);
+    const encryptedWalletAccessToken = await encrypt(
+      walletToken.accessToken,
+      projectSecretKey,
+    );

And update usage below:

-            encryptedAdminKey,
+            encryptedAdminKey: engineCloudService.encryptedAdminKey,
             encryptedWalletAccessToken,
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 e06fbd9 and b83e372.

📒 Files selected for processing (1)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{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

**/*.{ts,tsx}: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from @/types where applicable
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.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/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.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/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts
apps/{dashboard,playground}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

apps/{dashboard,playground}/**/*.{ts,tsx}: Import UI primitives from @/components/ui/_ (e.g., Button, Input, Tabs, Card)
Use NavLink for internal navigation to get active state handling
Use Tailwind CSS for styling; no inline styles
Merge class names with cn() from @/lib/utils for conditional classes
Stick to design tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components must start with import "server-only"; use next/headers, server‑only env, heavy data fetching, and redirect() where appropriate
Client Components must start with 'use client'; handle interactivity with hooks and browser APIs
Server-side data fetching: call getAuthToken() from cookies, send Authorization: Bearer <token> header, and return typed results (avoid any)
Client-side data fetching: wrap calls in React Query with descriptive, stable queryKeys and set sensible staleTime/cacheTime (≥ 60s default); keep tokens secret via internal routes or server actions
Do not import posthog-js in server components (client-side only)

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts
🧬 Code graph analysis (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts (3)
apps/dashboard/src/@/hooks/useApi.ts (1)
  • updateProjectClient (264-289)
packages/service-utils/src/node/index.ts (1)
  • hashSecretKey (187-189)
packages/service-utils/src/core/encryption.ts (2)
  • decrypt (49-96)
  • encrypt (1-47)
⏰ 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). (4)
  • GitHub Check: Size
  • GitHub Check: Lint Packages
  • GitHub Check: Build Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts (1)

3-3: Import looks correct

decrypt is now used in the new upgrade flow. No issues.

Comment on lines +781 to +787
export async function upgradeAccessTokensForSolana(props: {
project: Project;
projectSecretKey?: string;
}): Promise<{
success: boolean;
error?: string;
data?: {
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 | 🔴 Critical

🧩 Analysis chain

Handle freshly rotated secret keys (accept projectSecretHash like other path)

Without including projectSecretHash, valid just-rotated keys can be rejected. Mirror createAndEncryptVaultAccessTokens behavior.

Apply this diff:

-export async function upgradeAccessTokensForSolana(props: {
-  project: Project;
-  projectSecretKey?: string;
-}): Promise<{
+export async function upgradeAccessTokensForSolana(props: {
+  project: Project;
+  projectSecretKey?: string;
+  projectSecretHash?: string;
+}): Promise<{
@@
-  const { project, projectSecretKey } = props;
+  const { project, projectSecretKey, projectSecretHash } = props;
@@
-    const projectSecretKeyHash = await hashSecretKey(projectSecretKey);
-    if (!project.secretKeys.some((key) => key?.hash === projectSecretKeyHash)) {
+    const projectSecretKeyHash = await hashSecretKey(projectSecretKey);
+    const secretKeysHashed = [
+      ...project.secretKeys,
+      ...(projectSecretHash ? [{ hash: projectSecretHash }] : []),
+    ];
+    if (!secretKeysHashed.some((key) => key?.hash === projectSecretKeyHash)) {
       return {
         success: false,
         error: "Invalid project secret key",
       };
     }

Run to find call sites and ensure they pass projectSecretHash where applicable:

Also applies to: 792-792, 873-876


🏁 Script executed:

#!/bin/bash
rg -nP --type=ts -C3 '\bupgradeAccessTokensForSolana\s*\('

Length of output: 2247


🏁 Script executed:

#!/bin/bash
sed -n '760,840p' 'apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts'

Length of output: 2300


🏁 Script executed:

#!/bin/bash
rg -n -C3 'hashSecretKey' 'apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts'

Length of output: 950


Handle freshly rotated secret keys in upgradeAccessTokensForSolana

  • Add projectSecretHash?: string to the function signature and destructuring.
  • In both secret-key validation blocks (around lines 255–261 and 873–876 in vault.client.ts), build
    const secretKeysHashed = [
      ...project.secretKeys,
      ...(projectSecretHash ? [{ hash: projectSecretHash }] : []),
    ];
    then match projectSecretKeyHash against secretKeysHashed.
  • Update all call sites (e.g. upgrade-solana-permissions.client.tsx) to pass the new projectSecretHash prop.
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts
around lines 781 to 787, the function upgradeAccessTokensForSolana must accept a
freshly rotated secret hash: add projectSecretHash?: string to the function
signature and destructuring; in both secret-key validation blocks (near lines
~255–261 and ~873–876) construct const secretKeysHashed =
[...project.secretKeys, ...(projectSecretHash ? [{ hash: projectSecretHash }] :
[])]; and then match projectSecretKeyHash against secretKeysHashed (instead of
just project.secretKeys); finally update all call sites (e.g.
upgrade-solana-permissions.client.tsx) to pass projectSecretHash when available.

@d4mr d4mr added the merge-queue Adds the pull request to Graphite's merge queue. label Oct 15, 2025
Copy link
Member Author

d4mr commented Oct 15, 2025

Merge activity

  • Oct 15, 9:06 PM UTC: The merge label 'merge-queue' was detected. This PR will be added to the Graphite merge queue once it meets the requirements.
  • Oct 15, 9:20 PM UTC: The merge label 'merge-queue' was detected. This PR will be added to the Graphite merge queue once it meets the requirements.

@d4mr d4mr removed the merge-queue Adds the pull request to Graphite's merge queue. label Oct 15, 2025
@d4mr d4mr disabled auto-merge October 15, 2025 21:25
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. packages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants