Skip to content

posthog migration: part 5 #7367

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 19, 2025
Merged

Conversation

jnsdls
Copy link
Member

@jnsdls jnsdls commented Jun 18, 2025

Summary by CodeRabbit

  • New Features

    • Added event reporting for contract publishing, faucet usage, and custom chain configuration additions.
    • Introduced detailed event reporting for asset purchases, creations, imports, and configuration steps.
  • Refactor

    • Replaced legacy analytics tracking hooks with centralized reporting functions for key user actions.
    • Updated asset creation flows to report step transitions and outcomes with enhanced detail.
  • Bug Fixes

    • Clarified faucet claim restriction text to include the "Scale" plan alongside other eligible plans.
  • Chores

    • Removed all legacy analytics tracking hooks and event calls across the dashboard.
    • Simplified event reporting by eliminating unused tracking utilities and hooks without affecting user workflows.

PR-Codex overview

This PR primarily focuses on removing the useTrack hook from various components and replacing it with alternative tracking methods or removing tracking functionality altogether.

Detailed summary

  • Deleted useTrack hook usages in multiple components.
  • Removed tracking parameters from various event handlers.
  • Introduced reportAssetCreationStepConfigured for specific asset creation tracking.
  • Cleaned up unused tracking code across multiple files.

The following files were skipped due to too many changes: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/cloud/vault/components/list-access-tokens.client.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/components/primary-sale.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/mint-form.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/mint-supply-tab.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/reset-claim-eligibility.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/wallet-credentials/components/edit-wallet-credential-button.tsx, apps/dashboard/src/@/components/blocks/pricing-card.tsx, apps/dashboard/src/components/embedded-wallets/Configure/index.tsx, apps/dashboard/src/components/onboarding/ApplyForOpCreditsForm.tsx, apps/dashboard/src/components/settings/AuthorizedWallets/AuthorizedWalletsTable.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/components/platform-fees.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/update-metadata-form.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/burn-tab.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/shared-metadata-form.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/batch-lazy-mint-button.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/airdrop-tab.tsx, apps/dashboard/src/components/configure-networks/ConfigureNetworks.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/airdrop-form.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/burn-button.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/transfer-button.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/overview/components/backend-wallets-table.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/claim-button.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/admins/components/admins-table.tsx, apps/dashboard/src/components/smart-wallets/SponsorshipPolicies/index.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/relayers/components/relayers-table.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/access-tokens-table.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/claim-button.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/PayModal.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx, apps/dashboard/src/app/(app)/login/onboarding/account-onboarding-ui.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/index.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/upload-nfts/upload-nfts.tsx, apps/dashboard/src/components/CustomChat/CustomChatContent.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/primary-dashboard-button.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/FaucetButton.tsx, apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/cards.tsx, apps/dashboard/src/app/(app)/login/onboarding/VerifyEmail/VerifyEmail.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch/launch-nft.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/token/launch/launch-token.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/overview/buy-nft-drop/buy-nft-drop.client.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/claim-tokens/claim-tokens-ui.tsx, apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/overview/buy-edition-drop/buy-edition-drop.client.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/token/create-token-page-impl.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/create-nft-page.tsx, apps/dashboard/src/@/analytics/report.ts

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

Copy link

changeset-bot bot commented Jun 18, 2025

⚠️ No Changeset found

Latest commit: 1397adf

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

Copy link

vercel bot commented Jun 18, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
nebula ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 19, 2025 1:04am
thirdweb-www ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 19, 2025 1:04am
4 Skipped Deployments
Name Status Preview Comments Updated (UTC)
docs-v2 ⬜️ Skipped (Inspect) Jun 19, 2025 1:04am
login ⬜️ Skipped (Inspect) Jun 19, 2025 1:04am
thirdweb_playground ⬜️ Skipped (Inspect) Jun 19, 2025 1:04am
wallet-ui ⬜️ Skipped (Inspect) Jun 19, 2025 1:04am

Copy link
Contributor

coderabbitai bot commented Jun 18, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

## Walkthrough

This change removes the custom analytics tracking hook (`useTrack`) and all related event tracking logic from the application. All tracking calls, tracking utility functions, and props related to analytics have been deleted across components, pages, and stories. In a few places, new direct analytics reporting functions are introduced for specific events. The control flow and core functionality remain unchanged except for the removal of analytics side effects.

## Changes

| File(s) / Path(s)                                                                                     | Change Summary                                                                                                      |
|-------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|
| `apps/dashboard/src/hooks/analytics/useTrack.ts`<br>`apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/_common/tracking.ts`<br>`apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/token/_common/tracking.ts` | Deleted the custom `useTrack` analytics hook and all tracking data utility functions for NFT and token events.       |
| All files importing or using `useTrack` (components, pages, stories, modals, forms, etc.)             | Removed all imports, initializations, and calls to `useTrack` and `trackEvent`. Deleted related props and handlers. |
| Onboarding components, stories, and props (e.g., `LoginOrSignup`, `LinkWalletPrompt`, `VerifyEmail`)  | Removed all tracking-related props, types, and event calls from component signatures and usages.                     |
| `apps/dashboard/src/@/analytics/report.ts`                                                            | Simplified existing reporting, added new event reporting functions for contract publishing, faucet usage, and chain configuration. |
| `apps/dashboard/src/components/configure-networks/ConfigureNetworks.tsx`                              | Replaced generic tracking with direct call to new `reportChainConfigurationAdded` function on custom network add.    |
| `apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx`                   | Replaced tracking with new direct call to `reportContractPublished` on publish success; removed attempt/error tracking. |
| `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/FaucetButton.tsx` | Replaced tracking with direct call to `reportFaucetUsed` on faucet claim success; removed all other tracking.        |
| `apps/dashboard/src/components/smart-wallets/SponsorshipPolicies/index.tsx`<br>`apps/dashboard/src/components/embedded-wallets/Configure/index.tsx` | Removed `trackingCategory` prop and all tracking logic from smart wallet and embedded wallet settings components.     |
| `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/cards.tsx`             | Removed tracking-related props and logic from `CardLink` and `Cards`.                                                |
| `apps/dashboard/src/components/embedded-wallets/Configure/InAppWalletSettingsUI.stories.tsx`<br>`apps/dashboard/src/components/embedded-wallets/Configure/index.tsx` | Removed all tracking props and logic from embedded wallet settings stories and components.                           |
| `apps/dashboard/src/components/settings/Account/Billing/CreditsItem.tsx`<br>`apps/dashboard/src/components/onboarding/ApplyForOpCreditsForm.tsx`<br>`apps/dashboard/src/components/onboarding/ApplyForOpCreditsModal.tsx` | Removed all tracking logic from OP sponsorship credits components.                                                   |
| `apps/dashboard/src/components/settings/ApiKeys/Create/index.tsx`<br>`apps/dashboard/src/components/settings/AuthorizedWallets/AuthorizedWalletsTable.tsx` | Removed all tracking logic from API key and authorized wallet components.                                            |
| `apps/dashboard/src/components/settings/Account/Notifications.tsx`                                    | Removed tracking on notification preference update; now relies solely on transaction notifications.                  |
| `apps/nebula/src/@/components/ui/NavLink.tsx`<br>`apps/nebula/src/@/components/blocks/buttons/MismatchButton.tsx`<br>`apps/nebula/src/@/utils/parse-error.tsx`<br>`apps/nebula/src/app/(app)/components/Swap/common.tsx` | Removed or cleaned up commented-out tracking code in Nebula app components.                                          |
| `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/create-nft-page-ui.tsx`<br>`apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/token/create-token-page.client.tsx` | Added calls to `reportAssetCreationStepConfigured` at UI step transitions in NFT and token creation flows.            |
| `apps/dashboard/src/components/contract-components/import-contract/modal.tsx`                         | Added optional `onSuccess` callback prop to `ImportModal` and `ImportForm` components to notify successful import.   |
| All other affected files (various components, modals, forms, and pages)                               | Removed all tracking logic, props, and utility usage. Updated error handling to use `console.error` where applicable.|

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant UI_Component
    participant Analytics

    User->>UI_Component: Triggers tracked action (e.g., publish, faucet, add chain)
    alt New direct reporting (where applicable)
        UI_Component->>Analytics: reportContractPublished/reportFaucetUsed/reportChainConfigurationAdded
    else No tracking
        UI_Component-->>Analytics: (No call, tracking removed)
    end

Possibly related PRs

Suggested reviewers

  • joaquim-verges

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=thirdweb-dev/js&utm_content=7367):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` 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:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@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](https://docs.coderabbit.ai/guides/configure-coderabbit) 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`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

@github-actions github-actions bot added the Dashboard Involves changes to the Dashboard. label Jun 18, 2025
Copy link
Member Author

jnsdls commented Jun 18, 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.

@jnsdls jnsdls marked this pull request as ready for review June 18, 2025 06:14
@jnsdls jnsdls requested review from a team as code owners June 18, 2025 06:14
Copy link
Member Author

jnsdls commented Jun 18, 2025

@coderabbitai review

Copy link
Contributor

coderabbitai bot commented Jun 18, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

codecov bot commented Jun 18, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 52.35%. Comparing base (2aa9ce5) to head (1397adf).
Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7367   +/-   ##
=======================================
  Coverage   52.35%   52.35%           
=======================================
  Files         939      939           
  Lines       63161    63161           
  Branches     4217     4217           
=======================================
  Hits        33070    33070           
  Misses      29984    29984           
  Partials      107      107           
Flag Coverage Δ
packages 52.35% <ø> (ø)
🚀 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

github-actions bot commented Jun 18, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
thirdweb (esm) 62.53 KB (0%) 1.3 s (0%) 263 ms (+149.52% 🔺) 1.6 s
thirdweb (cjs) 350.55 KB (0%) 7.1 s (0%) 923 ms (-1.18% 🔽) 8 s
thirdweb (minimal + tree-shaking) 5.7 KB (0%) 114 ms (0%) 104 ms (+1232.48% 🔺) 218 ms
thirdweb/chains (tree-shaking) 531 B (0%) 11 ms (0%) 51 ms (+1777.91% 🔺) 61 ms
thirdweb/react (minimal + tree-shaking) 19.59 KB (0%) 392 ms (0%) 102 ms (+478.29% 🔺) 494 ms

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

🔭 Outside diff range comments (11)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/admins/components/add-admin-button.tsx (1)

68-79: Early-exit missing when wallet address is invalid

onError is invoked on an invalid address, but the code continues to call grantPermissions, which will inevitably fail (and potentially log sensitive errors). Add a return (or surround with else) to stop execution.

-            if (!isAddress(data.walletAddress)) {
-              onError(new Error("Invalid wallet address"));
-            }
+            if (!isAddress(data.walletAddress)) {
+              onError(new Error("Invalid wallet address"));
+              return;
+            }
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/claim-button.tsx (2)

94-101: transactionCount is incorrect when an approval tx is required

When approveTx exists you actually submit two transactions (approve + claim) but transactionCount is hard-coded to 1, so downstream UI components (e.g., progress bars) will under-report.

-            transactionCount={1}
+            transactionCount={approveTx ? 2 : 1}

80-84: Runtime regex may break while _decimals is loading

pattern={^\d+(\.\d{1,${_decimals || 18}})?$} will render undefined until the hook resolves, producing an invalid regex like ^\\d+(\.\d{1,undefined})?$. Guard the pattern or fall back to a safe default.

-                pattern={`^\\d+(\\.\\d{1,${_decimals || 18}})?$`}
+                pattern={_decimals !== undefined
+                  ? `^\\d+(\\.\\d{1,${_decimals}})?$`
+                  : '^\\d+(\\.\\d{1,18})?$'}
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/burn-tab.tsx (1)

31-41: Add basic numeric validation for amount to avoid BigInt runtime errors

burn1155 converts the user-supplied string to BigInt without validating that the input is a positive integer.
An empty value, decimals, or non-numeric characters will throw (BigInt fails on invalid input) and surface as an unhandled exception.

-<Input placeholder="1" {...register("amount")} />
+<Input
+  placeholder="1"
+  {...register("amount", {
+    required: "Amount is required",
+    pattern: {
+      value: /^[1-9]\d*$/,
+      message: "Enter a positive integer",
+    },
+  })}
+/>

This keeps UX consistent with other numeric fields and prevents avoidable crashes.

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/claim-tab.tsx (1)

60-76: Validate that amount is positive before creating the transaction

The current custom validator only checks for integer-ness. A user could therefore input 0 or a negative number, leading to a revert on-chain and a wasted transaction fee.

-                if (!Number.isInteger(valueNum)) {
-                  return "Amount must be an integer";
+                if (!Number.isInteger(valueNum) || valueNum <= 0) {
+                  return "Amount must be a positive integer";
                 }
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/index.tsx (1)

359-404: Form stays dirty after successful save – call form.reset instead of setValue
form.setValue("phases", newPhases) re-assigns fresh object references, so react-hook-form still marks the form as dirty. This keeps the “unsaved changes” banner visible even though the data is persisted. Use form.reset (or resetField) to synchronise internal state and clear the dirty flags.

-      const newPhases = d.phases.map((phase) => ({
-        ...phase,
-        isEditing: false,
-        fromSdk: true,
-      }));
-
-      form.setValue("phases", newPhases);
+      const newPhases = d.phases.map((phase) => ({
+        ...phase,
+        isEditing: false,
+        fromSdk: true,
+      }));
+
+      // clears dirty state & keeps validation meta intact
+      form.reset({ phases: newPhases }, { keepValues: true });
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/claim-button.tsx (1)

63-66: TransactionButton points to a non-existent form – add an id
TransactionButton’s form={CLAIM_FORM_ID} attribute relies on the <form> element having the same id. Without it, the button is detached from form submission semantics (e.g. native validation, Enter-key submit).

-        <form className="mt-8 flex w-full flex-col gap-3 md:flex-row">
+        <form
+          id={CLAIM_FORM_ID}
+          className="mt-8 flex w-full flex-col gap-3 md:flex-row"
+        >

Also applies to: 107-115

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx (1)

283-290: Duplicate push produces two identical storage service entries

serviceToAdd is pushed inside the if (serviceMeta.name === "storage") block and again immediately afterwards, resulting in duplicate objects in the services array.
This will send malformed payloads to the API and may break the project-settings update.

-        if (serviceMeta.name === "storage") {
-          serviceToAdd.actions = serviceMeta.actions as ("read" | "write")[];
-          services.push(serviceToAdd);
-        }
-
-        services.push(serviceToAdd);
+        if (serviceMeta.name === "storage") {
+          serviceToAdd.actions = serviceMeta.actions as ("read" | "write")[];
+        }
+
+        services.push(serviceToAdd);
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/list-form.tsx (1)

585-597: Buy-out price is never persisted for auctions

The input is always bound to pricePerToken, but when listingType === "auction" the mutation reads buyoutPricePerToken.
Result: every auction is created with a buy-out price of 0, irrespective of what the user enters.

-        <Input {...form.register("pricePerToken")} />
+        <Input
+          {...form.register(
+            form.watch("listingType") === "auction"
+              ? "buyoutPricePerToken"
+              : "pricePerToken",
+          )}
+        />

This keeps the direct-listing path intact while correctly wiring the auction field.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/create-nft-page.tsx (1)

127-135: mutateAsync fire-and-forget may raise unhandled rejections

addContractToProject.mutateAsync returns a Promise that is neither awaited nor .catch-ed.
If the network call fails you’ll get an unhandled rejection in the console, potentially killing React’s render loop in strict mode.

- addContractToProject.mutateAsync({
+ addContractToProject
+   .mutateAsync({
       teamId: props.teamId,
       projectId: props.projectId,
       contractAddress: contractAddress,
       chainId: collectionInfo.chain,
       deploymentType: "asset",
       contractType: ercType === "erc721" ? "DropERC721" : "DropERC1155",
- });
+   })
+   .catch((err) => {
+     console.error("Failed to register contract in project:", err);
+   });
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/relayers/components/add-relayer-button.tsx (1)

117-124: UX: disable the “Add” button while the mutation is in flight

Currently the form can be submitted repeatedly. Disable the button (or the whole form) using isLoading from react-query mutation state to prevent duplicate relayer creation requests.

-  const { mutate: createRelayer } = useEngineCreateRelayer({
+  const { mutate: createRelayer, isPending } = useEngineCreateRelayer({
...
-          <Button
+          <Button
             type="submit"
             colorScheme="primary"
-            isDisabled={!form.formState.isValid}
+            isDisabled={!form.formState.isValid || isPending}
+            isLoading={isPending}
           >
🧹 Nitpick comments (63)
apps/dashboard/src/@/components/blocks/pricing-card.tsx (2)

152-156: cta.onClick is passed directly – consider a small wrapper for stricter typing

cta.onClick is declared as () => void, while buttonProps.onClick expects React.MouseEventHandler<HTMLButtonElement>. Because React’s type definitions are bivariant this compiles, but the variance loophole can hide mistakes (e.g., someone later adds an event.preventDefault() inside cta.onClick and needs the event). Wrapping keeps the signature explicit and avoids accidental misuse:

- onClick: cta.onClick,
+ onClick: (e) => {
+   cta.onClick?.();        // still optional-safe
+ },

170-174: Same typing caveat for the Link element’s onClick

For consistency with the Button case above – and to avoid leaking the MouseEvent parameter to a callback that doesn’t expect it – wrap the call similarly:

- onClick={cta.onClick}
+ onClick={(e) => {
+   cta.onClick?.();
+ }}

This keeps both call-sites symmetric and future-proof.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/admins/components/add-admin-button.tsx (1)

77-79: Avoid leaking details through console logging

console.error(error) may expose engine URL or auth token in the browser console. Prefer wrapping or redacting the message before logging.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/add-access-token-button.tsx (1)

52-55: Redact sensitive data before logging

console.error(error) can surface the freshly-created access token if the API returns it inside the error object. Either remove the log or strip sensitive fields first.

-              console.error(error);
+              // console.error(redact(error));
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/configuration/components/kms-gcp-config.tsx (1)

71-72: Prefer structured error reporting instead of bare console.error

console.error(error) is helpful during local development but offers little value in production where logs may be discarded or unreachable.
Consider piping the exception into your central error-monitoring solution (e.g. Sentry, Datadog) or at least adding contextual metadata so ops can correlate failures.

- console.error(error);
+ captureException(error, {
+   component: "KmsGcpConfig",
+   action: "setGcpKmsConfig",
+   instanceUrl: instance.url,
+ });

If you deliberately removed analytics tracking, this is a good moment to ensure another mechanism still surfaces runtime errors.

apps/dashboard/src/components/settings/AuthorizedWallets/AuthorizedWalletsTable.tsx (1)

93-108: Surface error details to the user and monitoring tools

  1. The toast shows a generic failure message but discards the actual exception. Including the .message (or a safe subset) helps users debug quickly.
  2. As with other components, relying solely on console.error means losing visibility in production.
- toast.error("Something went wrong while revoking the device", {
-   description:
-     "Please visit our support site: https://thirdweb.com/support",
- });
+ toast.error("Failed to revoke device", {
+   description: (error as Error).message ?? undefined,
+ });
+
+ captureException(error, {
+   component: "AuthorizedWalletsTable",
+   action: "revokeAuthorizedWallet",
+   authorizedWalletId: revokeAuthorizedWalletId,
+ });
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/components/proposal-button.tsx (1)

67-72: Capture proposal-creation failures more robustly

console.error(error) silences failures in production UIs. Forward the exception to the same toast (for user context) and to your monitoring pipeline.

- onError: (error) => {
-   console.error(error);
- },
+ onError: (error) => {
+   toast.error((error as Error).message);
+   captureException(error, {
+     component: "ProposalButton",
+     action: "createProposal",
+     contractAddress: contract.address,
+   });
+ },
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/components/royalties.tsx (1)

101-106: Avoid double-logging & enrich error context

onError(error) already triggers the standard notification toast; adding a naked console.error duplicates noise without extra value.
If additional context is needed, prefer a structured logger or monitoring client:

- console.error(error);
- onError(error);
+ onError(error); // already notifies the UI
+ captureException(error, {
+   component: "SettingsRoyalties",
+   action: "setDefaultRoyaltyInfo",
+   contractAddress: contract.address,
+ });
apps/dashboard/src/components/settings/ApiKeys/Create/index.tsx (1)

221-223: Expose meaningful error information on project-creation failure

Right now users only see “Failed to create a project”. If the backend returns a descriptive message (e.g., duplicate name), surface it:

-onError: () => {
-  toast.error("Failed to create a project");
+onError: (error) => {
+  toast.error(
+    (error as Error).message || "Failed to create a project",
+  );
+  captureException(error, {
+    component: "CreateProjectForm",
+    action: "createProject",
+  });
 },

This improves UX and keeps observability parity after removing analytics tracking.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/webhooks/components/webhooks-table.tsx (1)

203-204: Avoid raw console.error in UI code.

Directly logging the entire error object to the browser console may expose stack traces or sensitive payloads, and it cannot be filtered/aggregated in production.
Prefer one of the following:

- console.error(error);
+// Replace with structured logging or send to monitoring service
+captureException(error);            // Sentry (example)
+// or at least:
+console.error("[Webhook-delete]", error?.message ?? error);

This keeps the console clean and prevents accidental leakage.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/webhooks/components/add-webhook-button.tsx (1)

83-84: Sanitise or remove console.error.

useTxNotifications already surfaces the failure to the user, so the extra console.error offers limited value and could reveal request details (URLs, auth headers) in prod consoles.

-                onError: (error) => {
-                  onError(error);
-                  console.error(error);
+                onError: (error) => {
+                  onError(error);          // already handles user feedback / telemetry
+                  // Optional: captureException(error);   // send to monitoring
                 },
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/keypairs-table.tsx (1)

151-154: Avoid double-logging and leaking stack traces

onError(error) already surfaces a toast notification; the extra uncontrolled console.error(error) will duplicate the log and may expose internal details in production builds.

-        onError: (error) => {
-          onError(error);
-          console.error(error);
-        },
+        onError,
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/claim-button.tsx (1)

120-131: Consolidate error handling

onError inside both approveTx and the main send call do nothing except console.error. Consider passing the shared claimTokensNotifications.onError to keep a consistent UX and avoid repeating code.

-                      onError: (error) => {
-                        console.error(error);
-                      },
+                      onError: claimTokensNotifications.onError,
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/relayers/components/relayers-table.tsx (2)

256-259: Redundant console.error

onError(error) already shows a toast; the extra console.error duplicates logs.

-      onError: (error) => {
-        onError(error);
-        console.error(error);
-      },
+      onError,

370-373: Same duplication in revoke flow

Apply the same cleanup here to avoid double logging.

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/mint-form.tsx (1)

121-123: Drop the second console.error – error is already logged in the catch

console.error here fires inside the mutation’s onError, and then the same error is logged again in the catch block below. One log line is enough.

-      onError: (error) => {
-        console.error(error);
-      },
+      onError: () => {
+        /* handled in catch */
+      },
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/wallet-credentials/components/edit-wallet-credential-button.tsx (1)

40-43: Remove duplicated logging (console.log vs console.error)

Both calls print the same error; keep the console.error (with stack trace) and drop the plain console.log to avoid noise.

-        console.log(error);
-        console.error(error);
+        console.error(error);
apps/dashboard/src/components/CustomChat/CustomChatContent.tsx (2)

49-55: Clear the chatAbortController in finally to avoid dangling references

setChatAbortController(abortController) is set before the fetch, but never reset once the request finishes (successfully or with an error).
Keeping the stale controller instance around in state is harmless, yet unnecessary and may cause confusion when debugging multiple parallel chats.

       } finally {
         setIsChatStreaming(false);
         setEnableAutoScroll(false);
+        // release reference to the finished/aborted request
+        setChatAbortController(undefined);
       }

191-192: messages in the dependency array causes a re-creation each render

handleFeedback depends on messages, which is recreated on every state update, so the callback is re-instantiated after each message change.
That’s fine functionally but unnecessary. Derive the needed message inside the callback via functional setState, or memoise messages if you really need it.
Reducing the dependency list slightly improves render performance.

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/lazy-mint-form.tsx (1)

103-110: Duplicate error handling – console noise

console.error is executed both in the onError callback and the outer catch, resulting in the same stack trace being printed twice.
Drop one of them to keep logs clean.

               onError: (error) => {
-                console.error(error);
               },
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/shared-metadata-form.tsx (1)

92-95: Same error logged twice

As in the lazy-mint form, the error is printed in both the onError callback and the surrounding catch block. Remove one to avoid duplication.

-              onError: (error) => {
-                console.error(error);
-              },
+              onError: () => { /* handled in surrounding catch */ },
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/components/platform-fees.tsx (1)

91-94: Duplicate console.error

The same error is logged here and in onError(error) from useTxNotifications, leading to redundant output.

-            onError: (error) => {
-              console.error(error);
-              onError(error);
-            },
+            onError,
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/token/create-token-page-impl.tsx (1)

103-110: Log the full error object, not just the parsed message

console.error(errorMessage) strips stack‐trace/context and is used four times in these catch blocks. Prefer logging the original error (or both) to aid debugging.

-      console.error(errorMessage);
+      console.error(e);            // preserves stack & metadata
+      console.error(errorMessage); // optional: keep user-friendly text

Apply the same change in the three other catch blocks for consistency.

Also applies to: 150-152, 208-210, 284-286

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/batch-lazy-mint-button.tsx (1)

108-111: Include stack trace when logging mint errors

Same note as above – log the raw error object before (or in addition to) any derived messaging to avoid losing context.

-                console.error(error);
+                console.error(error);          // full stack

Minor, but helpful during on-call debugging.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/overview/components/import-backend-wallet-button.tsx (1)

93-96: Retain original error details in logs

Logging only error is good. Consider adding structured data (e.g., instance.url, walletType) to speed up incident triage, but fine to defer.

apps/dashboard/src/components/pay/RouteDiscovery.tsx (1)

90-97: Disable the submit button when the form is invalid, not only when it’s pristine
disabled: !form.formState.isDirty blocks submission on untouched forms, but allows submission when fields are dirty yet invalid (e.g. empty token address). Prefer !form.formState.isValid (with mode: "onChange" or "all") to reflect actual validity.

-              disabled: !form.formState.isDirty,
+              disabled: !form.formState.isValid,

Remember to initialise the form with mode: "onChange" to get real-time validity updates:

-  const form = useForm<RouteDiscoveryValidationSchema>({
+  const form = useForm<RouteDiscoveryValidationSchema>({
     resolver: zodResolver(routeDiscoveryValidationSchema),
+    mode: "onChange",
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/add-keypair-button.tsx (1)

80-95: Missing client-side validation of the public key
onClick fires the mutation with whatever is in publicKey, but there’s no quick validation that the textarea actually contains a PEM-encoded public key for the selected algorithm. A simple length / header-footer check avoids round-trips and gives instant feedback.

   const onClick = async () => {
+    if (!publicKey.startsWith("-----BEGIN PUBLIC KEY-----") ||
+        !publicKey.trim().endsWith("-----END PUBLIC KEY-----")) {
+      onError(new Error("Invalid public key format"));
+      return;
+    }
+
     try {
       await importKeypair({
         publicKey,
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/claim-button.tsx (1)

90-100: Numeric validation should ensure a positive integer and use type="number"
The current validator only checks for an integer. Negative or zero amounts pass. Also, using an explicit number input gives users native mobile keyboards and prevents non-numeric characters.

-  <Input
-    type="text"
+  <Input
+    type="number"
     {...register("amount", {
       validate: (value) => {
         const valueNum = Number(value);
-        if (!Number.isInteger(valueNum)) {
-          return "Amount must be an integer";
+        if (!Number.isInteger(valueNum) || valueNum <= 0) {
+          return "Amount must be a positive integer";
         }
       },
     })}
apps/dashboard/src/app/(app)/login/onboarding/account-onboarding-ui.tsx (1)

43-46: Consider using an explicit reducer for multi-step onboarding
As the number of onboarding states grows, nested objects with backScreen references become harder to reason about. A useReducer with explicit action types (NEXT, BACK, RESET) will centralise transitions and avoid deep object copies.

No immediate bug – just a maintainability consideration.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/overview/components/create-backend-wallet-button.tsx (1)

71-80: Reduce duplicate error surfacing & tighten logging

toast.promise() already surfaces the rejected promise with the "Failed to create wallet" message, and useEngineCreateBackendWallet will throw in that case.
The additional onError handler therefore:

  1. Logs the same error twice (toast + console).
  2. Costs an extra callback that brings no state change.

Unless you plan to forward the error to a central logger (e.g. Sentry), consider dropping the callback or enriching the log.

-      onError: (error) => {
-        console.error(error);
-      },
+      // Let toast.promise handle UI feedback.
+      // Forward to external error logger here if needed.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/components/primary-sale.tsx (1)

90-94: Unnecessary extra console.error

useTxNotifications.onError() already turns the exception into a toast.
The extra console.error is fine in dev but can spam production logs.

-            onError: (error) => {
-              console.error(error);
-              onError(error);
-            },
+            onError,
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/admins/components/admins-table.tsx (1)

165-168: Prefer one-shot error handling instead of raw console.error

Both mutation handlers already feed into useTxNotifications.onError, so the explicit console.error duplicates noise without adding context.
If you need structured logging, consider a shared logger; otherwise drop the call.

-        onError: (error) => {
-          onError(error);
-          console.error(error);
-        },
+        onError,

Also applies to: 241-244

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/configuration/components/circle-config.tsx (1)

48-54: Avoid double-logging errors

toast.error already informs the user; the extra console.error can be removed or replaced with a structured logger.

-        toast.error("Failed to set configuration", {
-          description: error.message,
-        });
-        console.error(error);
+        toast.error("Failed to set configuration", {
+          description: error.message,
+        });
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx (2)

313-317: Prefer structured logging & user feedback over bare console.error

toast.error already informs the user; an additional naked console.error(err) spams the browser console and leaks raw error objects in prod.
Consider piping errors to a central logger/Sentry instead, or remove the extra statement.


946-949: Same console.error concern applies here

See comment above – logging the raw error for delete-project failures should go through a proper logger.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/access-tokens-table.tsx (2)

173-181: Surface error to the user, not just the console

onError already shows a toast, so emitting console.error(error) is redundant for production.
Route the error to a telemetry pipeline or remove the call.


249-257: Ditto for delete flow

Same remark as above – consider dropping or replacing direct console logging.

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/update-metadata-form.tsx (1)

160-166: Lost toast on tx-level failure

sendAndConfirmTx.mutateAsync’s onError only prints to the console now. The user only sees a toast if the promise rejects (caught in the outer catch).
For immediate feedback keep the toast inside onError as well:

-            onError: (error) => {
-              console.error(error);
-            },
+            onError: (error) => {
+              console.error(error);
+              updateMetadataNotifications.onError(error);
+            },
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/wallet-credentials/components/create-wallet-credential-button.tsx (1)

28-35: Replace raw console logging with structured reporting

As elsewhere, the rejection path only logs to the console. Consider forwarding to a central logger or removing to avoid leaking stack traces.

apps/dashboard/src/app/(app)/login/onboarding/LinkWalletPrompt/LinkWalletPrompt.tsx (1)

24-31: Add user feedback on success and surface precise errors

You notify the parent via onLinkWalletRequestSent, but the user never sees an explicit confirmation toast, while failures get only a generic message.

-      onSuccess: () => {
-        props.onLinkWalletRequestSent();
-      },
-      onError: (err) => {
-        const error = err as Error;
-        console.error(error);
-        toast.error("Failed to send link wallet request");
-      },
+      onSuccess: () => {
+        toast.success("Link-wallet email sent");
+        props.onLinkWalletRequestSent();
+      },
+      onError: (err) => {
+        console.error(err);
+        toast.error(err instanceof Error ? err.message : "Failed to send link wallet request");
+      },

Tiny UX win and more helpful diagnostics.

apps/dashboard/src/app/(app)/login/onboarding/LoginOrSignup/LoginOrSignup.tsx (1)

44-65: isExistingEmail is hard-coded to false on every success

If the backend chooses whether the email is new or existing, the callback currently mis-informs the next step. Consider making the API return that flag (or inspect the current tab state) instead of assuming.

-      onSuccess: () => {
-        props.onRequestSent({
-          email: values.email,
-          isExistingEmail: false,
-        });
+      onSuccess: (data) => {
+        props.onRequestSent({
+          email: values.email,
+          // derive this from API or the current tab
+          isExistingEmail: tab === "login",
+        });

Ensures the subsequent flow shows the correct UI.

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/FaucetButton.tsx (1)

121-124: Analytics call should not block UI in case of network hiccups

reportFaucetUsed is synchronous now, but if it ever becomes async and throws, it would bubble into React Query’s onSuccess chain. Wrap it defensively:

    onSuccess: () => {
-      reportFaucetUsed({ chainId });
+      try {
+        reportFaucetUsed({ chainId });
+      } catch {
+        // non-blocking
+      }
    },

Keeps the happy path resilient.

apps/dashboard/src/components/configure-networks/ConfigureNetworks.tsx (1)

29-35: Confirm path alias & payload size

  1. ../../@/analytics/report relies on the @ directory living at src/@. If the alias ever moves, TS won’t help because this is a relative import—consider using the established alias import (@/analytics/report) for consistency.

  2. rpcURLs can be large; PostHog payloads have a 32 kB limit. Trim/limit length if users enter many URLs.

-import { reportChainConfigurationAdded } from "../../@/analytics/report";
+import { reportChainConfigurationAdded } from "@/analytics/report";
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/components/delegate-button.tsx (1)

44-49: Console log could leak stack-traces; surface the message to the user & add context.

console.error(error); is handy while developing but (a) it does not surface anything useful to the end-user beyond the generic toast you already show, and (b) stack traces might leak internals in production logs.

-                console.error(error);
+                console.error("Failed to delegate tokens:", error);
+                // Optionally surface the specific reason to the user
+                // toast.error(error.message ?? "Unknown error");

If you want to keep silent logs, consider routing through a central logger instead of console.*.

apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx (1)

265-273: Include a fallback publisher identifier for better analytics fidelity.

ensNameOrAddress can be empty – sending "" gives you an anonymous publisher in PostHog.
Consider falling back to the wallet address to preserve attribution.

-                  publisher: ensNameOrAddress ?? "",
+                  publisher: ensNameOrAddress ?? account?.address ?? "",
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/overview/components/backend-wallets-table.tsx (2)

331-338: Prefer descriptive log messages over naked errors.

-          console.error(error);
+          console.error("Failed to update backend wallet label:", error);

A tiny improvement that eases production log grepping.


640-647: Same remark here – add context to the error log.

-          console.error(error);
+          console.error("Failed to delete backend wallet:", error);

Consistent, contextual logs make post-mortems quicker.

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/claim-tokens/claim-tokens-ui.tsx (1)

46-46: Please remove stale TODO or open a tracking ticket.

The comment still references figuring out tracking, but all PostHog-related tracking was intentionally removed in this PR. Leaving the TODO here is misleading.

-// TODO figure out proper tracking for this that helps us drive this product forward
+// (tracking removed – no longer applicable)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/contract-subscriptions/components/add-contract-subscription-button.tsx (1)

140-143: Avoid leaking errors only to the console – surface them to monitoring.

console.error is fine during development, but production UIs often suppress console output.
Consider forwarding the error to a central logger / Sentry so failures are observable.

-        console.error(error);
+        // TODO: send to central error reporter so ops can track failures
+        console.error(error);
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch/launch-nft.tsx (1)

205-213: Same logging remark as above – integrate with unified error reporting.

console.error(parsedError) is easy to miss in prod.
Hook this into whatever observability tool the dashboard uses (Sentry, LogRocket, etc.).

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/components/distribute-button.tsx (1)

58-60: Consider structured error reporting instead of plain console.error.

For consistency and easier debugging, forward the error to a shared logger before/after calling onError.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/create-nft-page.tsx (1)

52-56: Shadowing the chain identifier hampers readability

Within getContractAndAccount, chain is declared twice (parameter vs. local const chain = …).
While not technically wrong, the shadowing forces readers to double-take. Consider renaming the inner variable to something like resolvedChain or targetChain to make intent crystal-clear.

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/overview/buy-edition-drop/buy-edition-drop.client.tsx (1)

113-116: Repeated parseError + console.error blocks could be centralised

The same three-liner appears in three different catch scopes. A tiny helper like logParsedError(err) would DRY things up and avoid accidental divergence.

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/overview/buy-nft-drop/buy-nft-drop.client.tsx (1)

70-73: Ditto on duplicated error-handling

Same recommendation as the Edition-Drop component—factor out repetitive error logging to keep the happy-path logic readable.

apps/dashboard/src/components/embedded-wallets/Configure/index.tsx (2)

56-60: UpdateAPIKeyTrackingData is now dead code

Tracking is gone, but the helper type lingers. Prune it to avoid confusion.

-type UpdateAPIKeyTrackingData = {
-  hasCustomBranding: boolean;
-  hasCustomJwt: boolean;
-  hasCustomAuthEndpoint: boolean;
-};

230-239: Stale tracking parameter still propagated

props.updateApiKey is invoked with a second argument (trackingData) that no longer serves any purpose.
Either drop the extra argument here or update the prop’s signature to reflect its obsolescence—keeping both mismatched increases mental overhead.

-  props.updateApiKey(
-    {
-      services: newServices,
-    },
-    {
-      hasCustomBranding: !!branding,
-      hasCustomJwt: !!customAuthentication,
-      hasCustomAuthEndpoint: !!customAuthEndpoint,
-    },
-  );
+  props.updateApiKey({
+    services: newServices,
+  });
apps/dashboard/src/@/analytics/report.ts (1)

25-43: Consider normalising event names & payloads

The new helpers are great, but we now have mixed styles:

  • reportContractDeployed passes the payload raw.
  • reportFaucetUsed re-maps its props inline.

Consistent shape (either always spread incoming props or always re-map) will make the API easier to remember and reduce mistakes.

apps/dashboard/src/app/(app)/login/onboarding/VerifyEmail/VerifyEmail.tsx (2)

22-32: Remove the now-unused accountAddress prop

accountAddress is no longer referenced inside the component after the tracking clean-up. Keeping unused props invites confusion and triggers lint warnings.

-  accountAddress: string;

Unless this value is still consumed by callers, consider pruning it from both the prop type and all call-sites.


160-168: Drop the obsolete "trackingAction" key from Omit

VerifyEmailProps no longer contains trackingAction, yet it is still listed in the Omit utility. While TypeScript allows extraneous keys, removing it tightens intent and avoids future head-scratching.

-  props: Omit<VerifyEmailProps, "title" | "trackingAction">,
+  props: Omit<VerifyEmailProps, "title">,
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/contract-subscriptions/components/contract-subscriptions-table.tsx (2)

374-382: Use a centralized logger instead of console.error

Direct console.error calls make it hard to aggregate and search production issues. If you already have a unified logging/monitoring solution (e.g. Sentry, Datadog), delegate to it here.

-          onError(error);
-          console.error(error);
+          onError(error);           // toast / UI feedback
+          log.error(error);         // centralised telemetry

(Substitute log.error with whatever logger the dashboard uses.)


368-378: Minor readability: avoid shadowing the onSuccess / onError variables

mutate’s options already use the keys onSuccess and onError; re-using the same identifiers from the outer scope can be momentarily confusing.

-      onSuccess: () => {
-        onSuccess();
+      onSuccess: () => {
+        notifySuccess();
...
-      onError: (error) => {
-        onError(error);
+      onError: (error) => {
+        notifyError(error);

A simple rename clarifies the data-flow without functional changes.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/relayers/components/add-relayer-button.tsx (1)

120-126: Replace console.error with structured logging

Same concern as in the subscriptions modal—​prefer the project’s logging utility over raw console.error to keep error reporting consistent.

-        onError(error);
-        console.error(error);
+        notifyError(error); // existing toast/helper
+        log.error(error);   // centralised telemetry
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/PayModal.tsx (1)

19-23: Add type="button" to non-form buttons

Although this button is not inside a <form> today, adding type="button" prevents accidental form submission if the component is ever reused within a <form>.

-        <Button variant="primary" className="w-full">
+        <Button variant="primary" type="button" className="w-full">
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 57a8fec and cba391f.

📒 Files selected for processing (108)
  • apps/dashboard/src/@/analytics/report.ts (2 hunks)
  • apps/dashboard/src/@/components/blocks/pricing-card.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/FaucetButton.tsx (4 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/PayModal.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/cancel-tab.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/list-form.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/index.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/reset-claim-eligibility.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/primary-dashboard-button.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/airdrop-tab.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/burn-tab.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/claim-tab.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/mint-supply-tab.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/transfer-tab.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/update-metadata-form.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/batch-lazy-mint-button.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/claim-button.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/lazy-mint-form.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/mint-form.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/reveal-button.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/shared-metadata-form.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/Analytics.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/components/index.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/components/delegate-button.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/components/proposal-button.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/claim-tokens/claim-tokens-ui.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/overview/buy-edition-drop/buy-edition-drop.client.tsx (6 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/overview/buy-nft-drop/buy-nft-drop.client.tsx (5 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/components/metadata.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/components/platform-fees.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/components/primary-sale.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/components/royalties.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/components/distribute-button.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/airdrop-form.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/burn-button.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/claim-button.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/mint-button.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/transfer-button.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/account/contracts/DeployedContractsPageHeader.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/account/contracts/_components/DeployViaCLIOrImportCard.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/login/onboarding/LinkWalletPrompt/LinkWalletPrompt.stories.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/login/onboarding/LinkWalletPrompt/LinkWalletPrompt.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/login/onboarding/LoginOrSignup/LoginOrSignup.stories.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/login/onboarding/LoginOrSignup/LoginOrSignup.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/login/onboarding/VerifyEmail/VerifyEmail.stories.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/login/onboarding/VerifyEmail/VerifyEmail.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/login/onboarding/account-onboarding-ui.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/login/onboarding/account-onboarding.stories.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/login/onboarding/account-onboarding.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/_components/invite-team-members-button.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/cards.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/_common/step-card.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/_common/tracking.ts (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/create-nft-page.tsx (6 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch/launch-nft.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/upload-nfts/upload-nfts.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/token/_common/tracking.ts (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/token/create-token-page-impl.tsx (4 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/token/launch/launch-token.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/connect/account-abstraction/settings/page.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/connect/in-app-wallets/settings/page.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/cloud/analytics/send-test-tx.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/cloud/server-wallets/components/create-server-wallet.client.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/cloud/vault/components/create-vault-account.client.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/cloud/vault/components/list-access-tokens.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/cloud/vault/components/rotate-admin-key.client.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(general)/overview/engine-instances-table.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/access-tokens-table.tsx (4 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/add-access-token-button.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/add-keypair-button.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/keypairs-table.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/admins/components/add-admin-button.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/admins/components/admins-table.tsx (4 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/configuration/components/circle-config.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/configuration/components/kms-aws-config.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/configuration/components/kms-gcp-config.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/contract-subscriptions/components/add-contract-subscription-button.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/contract-subscriptions/components/contract-subscriptions-table.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/overview/components/backend-wallets-table.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/overview/components/create-backend-wallet-button.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/overview/components/import-backend-wallet-button.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/relayers/components/add-relayer-button.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/relayers/components/relayers-table.tsx (4 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/wallet-credentials/components/create-wallet-credential-button.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/wallet-credentials/components/edit-wallet-credential-button.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/webhooks/components/add-webhook-button.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/webhooks/components/webhooks-table.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx (3 hunks)
  • apps/dashboard/src/components/CustomChat/CustomChatButton.tsx (0 hunks)
  • apps/dashboard/src/components/CustomChat/CustomChatContent.tsx (3 hunks)
  • apps/dashboard/src/components/configure-networks/ConfigureNetworks.tsx (2 hunks)
  • apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx (2 hunks)
  • apps/dashboard/src/components/embedded-wallets/Configure/InAppWalletSettingsUI.stories.tsx (0 hunks)
  • apps/dashboard/src/components/embedded-wallets/Configure/index.tsx (1 hunks)
  • apps/dashboard/src/components/onboarding/ApplyForOpCreditsForm.tsx (0 hunks)
  • apps/dashboard/src/components/onboarding/ApplyForOpCreditsModal.tsx (0 hunks)
  • apps/dashboard/src/components/pay/PayConfig.tsx (0 hunks)
  • apps/dashboard/src/components/pay/RouteDiscovery.tsx (1 hunks)
  • apps/dashboard/src/components/settings/Account/Billing/CreditsItem.tsx (0 hunks)
  • apps/dashboard/src/components/settings/Account/Notifications.tsx (1 hunks)
  • apps/dashboard/src/components/settings/ApiKeys/Create/index.tsx (2 hunks)
  • apps/dashboard/src/components/settings/AuthorizedWallets/AuthorizedWalletsTable.tsx (1 hunks)
  • apps/dashboard/src/components/smart-wallets/SponsorshipPolicies/index.tsx (1 hunks)
  • apps/dashboard/src/hooks/analytics/useTrack.ts (0 hunks)
  • apps/nebula/src/@/components/blocks/buttons/MismatchButton.tsx (0 hunks)
  • apps/nebula/src/@/components/ui/NavLink.tsx (0 hunks)
  • apps/nebula/src/@/utils/parse-error.tsx (0 hunks)
  • apps/nebula/src/app/(app)/components/Swap/common.tsx (1 hunks)
💤 Files with no reviewable changes (36)
  • apps/dashboard/src/components/embedded-wallets/Configure/InAppWalletSettingsUI.stories.tsx
  • apps/dashboard/src/app/(app)/login/onboarding/LoginOrSignup/LoginOrSignup.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/connect/account-abstraction/settings/page.tsx
  • apps/dashboard/src/app/(app)/login/onboarding/account-onboarding.stories.tsx
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/mint-button.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/cloud/vault/components/rotate-admin-key.client.tsx
  • apps/nebula/src/@/utils/parse-error.tsx
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/reveal-button.tsx
  • apps/dashboard/src/components/onboarding/ApplyForOpCreditsForm.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/connect/in-app-wallets/settings/page.tsx
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/transfer-button.tsx
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/airdrop-tab.tsx
  • apps/dashboard/src/app/(app)/login/onboarding/VerifyEmail/VerifyEmail.stories.tsx
  • apps/dashboard/src/components/onboarding/ApplyForOpCreditsModal.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/cloud/server-wallets/components/create-server-wallet.client.tsx
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/reset-claim-eligibility.tsx
  • apps/nebula/src/@/components/ui/NavLink.tsx
  • apps/dashboard/src/app/(app)/login/onboarding/account-onboarding.tsx
  • apps/dashboard/src/components/CustomChat/CustomChatButton.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/cloud/vault/components/create-vault-account.client.tsx
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/components/metadata.tsx
  • apps/dashboard/src/app/(app)/login/onboarding/LinkWalletPrompt/LinkWalletPrompt.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(general)/overview/engine-instances-table.tsx
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/transfer-tab.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/_common/step-card.tsx
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/components/index.tsx
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/burn-button.tsx
  • apps/dashboard/src/components/settings/Account/Billing/CreditsItem.tsx
  • apps/dashboard/src/components/pay/PayConfig.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/token/launch/launch-token.tsx
  • apps/nebula/src/@/components/blocks/buttons/MismatchButton.tsx
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/cancel-tab.tsx
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/mint-supply-tab.tsx
  • apps/dashboard/src/hooks/analytics/useTrack.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/token/_common/tracking.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/_common/tracking.ts
🧰 Additional context used
🧬 Code Graph Analysis (4)
apps/dashboard/src/components/configure-networks/ConfigureNetworks.tsx (1)
apps/dashboard/src/@/analytics/report.ts (1)
  • reportChainConfigurationAdded (191-207)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/PayModal.tsx (1)
packages/thirdweb/src/react/web/ui/components/buttons.tsx (1)
  • Button (19-140)
apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx (1)
apps/dashboard/src/@/analytics/report.ts (1)
  • reportContractPublished (35-42)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/FaucetButton.tsx (1)
apps/dashboard/src/@/analytics/report.ts (1)
  • reportFaucetUsed (171-177)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: Size
  • GitHub Check: Unit Tests
  • GitHub Check: Build Packages
  • GitHub Check: Lint Packages
🔇 Additional comments (18)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/cloud/analytics/send-test-tx.client.tsx (1)

47-51: Removal of useTrack looks safe

The hook deletion does not affect runtime logic, and no other side-effects were introduced.
Good clean-up.

apps/dashboard/src/app/(app)/account/contracts/_components/DeployViaCLIOrImportCard.tsx (1)

5-6: Import clean-up is fine

useTrack removal has no behavioural impact here.

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/_components/invite-team-members-button.tsx (1)

9-14: LGTM – tracking removal only

The button now simply routes to the member settings page with no analytics side-effects.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/cloud/vault/components/list-access-tokens.client.tsx (1)

33-33: Removal of analytics hook looks good.

The useTrack cleanup introduces no functional or type-safety issues in this component.
Nothing else changed in this hunk.

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/Analytics.tsx (1)

11-11: Analytics hook removal confirmed.

The import removal is consistent with the PostHog deprecation. No further action needed.

apps/dashboard/src/app/(app)/account/contracts/DeployedContractsPageHeader.tsx (1)

41-46: Looks good – removal of analytics side-effect is complete

No functional impact; the button now purely toggles the modal.

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/airdrop-form.tsx (1)

48-58: 👍 Removal of tracking code is clean

No behavioural change; error handling remains intact.

apps/dashboard/src/components/CustomChat/CustomChatContent.tsx (1)

135-136: Missing dependency: props.client is read inside the component

The dependency array now omits props.client, but the hook uses it in JSX further down (<CustomChats … client={props.client} /> and <ChatBar … client={props.client} />).
While React guarantees prop-stability for the same object reference, it’s safer (and prevents future bugs) to include it explicitly.

-  [props.authToken, props.clientId, props.teamId, sessionId],
+  [props.authToken, props.client, props.clientId, props.teamId, sessionId],
apps/nebula/src/app/(app)/components/Swap/common.tsx (1)

1-7: Removal of unused tracking import looks good

The diff only reflects the removal of an (empty) line that previously held a useTrack import. No functional impact, and unused code was cleaned up.

apps/dashboard/src/components/settings/Account/Notifications.tsx (1)

36-39: Nice simplification of mutation callbacks

Passing the existing onSuccess / onError handlers directly keeps the component lean and removes now-unused tracking noise.

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/primary-dashboard-button.tsx (1)

20-20: Import change looks good

The updated import keeps the typings intact and removes the unused tracking utilities. No further action needed.

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/FaucetButton.tsx (1)

208-211: Clarify paid-plan message

The button text mentions “Starter, Growth, Scale and Pro”, but “Scale” was newly added. Double-check marketing copy for consistency elsewhere (pricing pages, FAQs).

apps/dashboard/src/components/smart-wallets/SponsorshipPolicies/index.tsx (1)

261-269: Mutation callbacks look good after tracking removal.

Forwarding onSuccess / onError directly keeps existing UX unchanged – no further action needed.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/cards.tsx (1)

70-82: Event handler removal is fine – keyboard fallback still works.

With onClick now directly wired, the onKeyDown check still guarantees keyboard accessibility. No additional changes required.

apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx (1)

1-3: Good move to centralised analytics helper.

Importing reportContractPublished keeps event semantics explicit and removes generic useTrack noise. 👍

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/claim-tokens/claim-tokens-ui.tsx (1)

34-34: Looks good – hook migration is correct.

useActiveAccount + useSendTransaction is the right pair after the SDK refactor. No issues spotted.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/upload-nfts/upload-nfts.tsx (1)

59-60: Passing callbacks directly keeps the component pure – nice.

Forwarding onNext / onPrev without side-effect wrappers simplifies the component and removes hidden analytics dependencies. 👍

Also applies to: 76-77

apps/dashboard/src/app/(app)/login/onboarding/VerifyEmail/VerifyEmail.tsx (1)

35-41: Double-check values vs defaultValues in useForm

React-Hook-Form’s stable API still expects defaultValues; the newer values option is experimental and gated behind the shouldUseFormState flag. If your project isn’t on that canary release, this will silently drop the initial value and may break type-safety.

-    values: {
+    defaultValues: {
       confirmationToken: "",
     },

Please verify your RHF version or switch to defaultValues to stay on the safe side.

@jnsdls jnsdls force-pushed the 06-17-posthog_migration_part_4 branch from f005dd2 to 74ce5f7 Compare June 19, 2025 00:34
@vercel vercel bot temporarily deployed to Preview – docs-v2 June 19, 2025 00:34 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground June 19, 2025 00:34 Inactive
@vercel vercel bot temporarily deployed to Preview – login June 19, 2025 00:34 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui June 19, 2025 00:34 Inactive
Copy link
Member Author

jnsdls commented Jun 19, 2025

@coderabbitai review

Copy link
Contributor

coderabbitai bot commented Jun 19, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

cursor[bot]

This comment was marked as outdated.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Error Handling Bug in Multiple UI Components

The parseError() function returns string | JSX.Element, but its result is now directly passed to reportAssetBuyFailed()'s error parameter and toast.error()'s description, both expecting a string. The removed type check (typeof errorMessage === "string" ? errorMessage : "Unknown error") previously prevented this. This can cause runtime errors when parseError() returns a JSX.Element. This issue affects buy-nft-drop.client.tsx, buy-edition-drop.client.tsx, and similar error handling in claim-tokens-ui.tsx, create-nft-page.tsx, create-token-page-impl.tsx, launch-nft.tsx, and launch-token.tsx.

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/overview/buy-nft-drop/buy-nft-drop.client.tsx#L110-L135

https://github.com/thirdweb-dev/js/blob/56caeaa97382bd7099ad21b9bf7d585392a79652/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/overview/buy-nft-drop/buy-nft-drop.client.tsx#L110-L135

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/overview/buy-edition-drop/buy-edition-drop.client.tsx#L168-L181

https://github.com/thirdweb-dev/js/blob/56caeaa97382bd7099ad21b9bf7d585392a79652/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/overview/buy-edition-drop/buy-edition-drop.client.tsx#L168-L181

Fix in Cursor


Bug: Type Mismatch in Error Reporting

The parseError utility can return string | JSX.Element, but its result is directly passed to reportAssetCreationFailed, which expects a string. This omits a necessary type check, potentially causing type or runtime errors when a JSX.Element is returned.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/create-nft-page.tsx#L151-L162

https://github.com/thirdweb-dev/js/blob/56caeaa97382bd7099ad21b9bf7d585392a79652/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/create-nft-page.tsx#L151-L162

Fix in Cursor


Was this report helpful? Give feedback by reacting with 👍 or 👎

Copy link
Contributor

graphite-app bot commented Jun 19, 2025

Merge activity

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Added event reporting for contract publishing, faucet usage, and custom chain configuration additions.
  - Introduced detailed event reporting for asset purchases, creations, imports, and configuration steps.

- **Refactor**
  - Replaced legacy analytics tracking hooks with centralized reporting functions for key user actions.
  - Updated asset creation flows to report step transitions and outcomes with enhanced detail.

- **Bug Fixes**
  - Clarified faucet claim restriction text to include the "Scale" plan alongside other eligible plans.

- **Chores**
  - Removed all legacy analytics tracking hooks and event calls across the dashboard.
  - Simplified event reporting by eliminating unused tracking utilities and hooks without affecting user workflows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on removing the `useTrack` analytics hook from various components and replacing it with direct logging or removing tracking functionality entirely.

### Detailed summary
- Deleted `useTrack` imports and instances from multiple files.
- Removed tracking-related code from components such as `LinkWalletPrompt`, `LoginOrSignup`, and `StepCard`.
- Replaced tracking calls with direct logging in error handling.
- Adjusted various components to eliminate unnecessary tracking.

> The following files were skipped due to too many changes: `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/cloud/vault/components/list-access-tokens.client.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/components/primary-sale.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/mint-form.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/mint-supply-tab.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/reset-claim-eligibility.tsx`, `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/wallet-credentials/components/edit-wallet-credential-button.tsx`, `apps/dashboard/src/@/components/blocks/pricing-card.tsx`, `apps/dashboard/src/components/embedded-wallets/Configure/index.tsx`, `apps/dashboard/src/components/onboarding/ApplyForOpCreditsForm.tsx`, `apps/dashboard/src/components/settings/AuthorizedWallets/AuthorizedWalletsTable.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/components/platform-fees.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/update-metadata-form.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/burn-tab.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/shared-metadata-form.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/batch-lazy-mint-button.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components/airdrop-tab.tsx`, `apps/dashboard/src/components/configure-networks/ConfigureNetworks.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/airdrop-form.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/burn-button.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/transfer-button.tsx`, `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/overview/components/backend-wallets-table.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/claim-button.tsx`, `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/admins/components/admins-table.tsx`, `apps/dashboard/src/components/smart-wallets/SponsorshipPolicies/index.tsx`, `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/relayers/components/relayers-table.tsx`, `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/access-tokens-table.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/claim-button.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/PayModal.tsx`, `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx`, `apps/dashboard/src/app/(app)/login/onboarding/account-onboarding-ui.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/index.tsx`, `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/upload-nfts/upload-nfts.tsx`, `apps/dashboard/src/components/CustomChat/CustomChatContent.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/primary-dashboard-button.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/FaucetButton.tsx`, `apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx`, `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/cards.tsx`, `apps/dashboard/src/app/(app)/login/onboarding/VerifyEmail/VerifyEmail.tsx`, `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch/launch-nft.tsx`, `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/token/launch/launch-token.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/overview/buy-nft-drop/buy-nft-drop.client.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/claim-tokens/claim-tokens-ui.tsx`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/overview/buy-edition-drop/buy-edition-drop.client.tsx`, `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/token/create-token-page-impl.tsx`, `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/create-nft-page.tsx`, `apps/dashboard/src/@/analytics/report.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 06-17-posthog_migration_part_4 branch from 74ce5f7 to 2aa9ce5 Compare June 19, 2025 00:55
@graphite-app graphite-app bot force-pushed the 06-17-posthog_migration_part_5 branch from 56caeaa to 1397adf Compare June 19, 2025 00:56
@vercel vercel bot temporarily deployed to Preview – wallet-ui June 19, 2025 00:56 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 June 19, 2025 00:56 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground June 19, 2025 00:56 Inactive
@vercel vercel bot temporarily deployed to Preview – login June 19, 2025 00:56 Inactive
Base automatically changed from 06-17-posthog_migration_part_4 to main June 19, 2025 01:06
@graphite-app graphite-app bot merged commit 1397adf into main Jun 19, 2025
23 checks passed
@graphite-app graphite-app bot deleted the 06-17-posthog_migration_part_5 branch June 19, 2025 01:07
@vercel vercel bot temporarily deployed to Production – thirdweb_playground June 19, 2025 01:07 Inactive
@vercel vercel bot temporarily deployed to Production – login June 19, 2025 01:07 Inactive
@vercel vercel bot temporarily deployed to Production – wallet-ui June 19, 2025 01:07 Inactive
@vercel vercel bot temporarily deployed to Production – docs-v2 June 19, 2025 01:07 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.

2 participants