Skip to content

Conversation

MananTank
Copy link
Member

@MananTank MananTank commented Sep 22, 2025


PR-Codex overview

This PR focuses on enhancing the BuyWidget and related components by updating callback props to include a quote object. It improves error handling and reporting for token purchases, ensuring better tracking of buy success, failure, and cancellations.

Detailed summary

  • Updated onSuccess, onError, and onCancel props in BuyWidget to accept a quote object.
  • Enhanced error reporting in BuyAndSwapEmbed for token buy failures and cancellations.
  • Introduced new reporting functions: reportTokenBuySuccessful, reportTokenBuyFailed, and reportTokenBuyCancelled.
  • Adjusted BridgeOrchestrator to handle quotes in completion and error callbacks.
  • Modified reportAssetBuySuccessful and related functions to accept optional contractType.

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

Summary by CodeRabbit

  • New Features

    • Buy and Bridge flows now provide quote details to success, error, and cancel callbacks.
    • Token-level analytics added for buy flows (success, failure, cancel).
  • Breaking Changes

    • Callback signatures changed to include quote parameters; client implementations must be updated.
  • Documentation

    • Examples updated to show new callback parameters and usage.
  • Chores

    • Analytics standardized for purchases; some contract-type fields may be unspecified.

Copy link

linear bot commented Sep 22, 2025

Copy link

vercel bot commented Sep 22, 2025

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

Project Deployment Preview Comments Updated (UTC)
docs-v2 Ready Ready Preview Comment Sep 22, 2025 11:38pm
nebula Ready Ready Preview Comment Sep 22, 2025 11:38pm
thirdweb_playground Ready Ready Preview Comment Sep 22, 2025 11:38pm
thirdweb-www Ready Ready Preview Comment Sep 22, 2025 11:38pm
wallet-ui Ready Ready Preview Comment Sep 22, 2025 11:38pm

Copy link

changeset-bot bot commented Sep 22, 2025

🦋 Changeset detected

Latest commit: a94f229

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

This PR includes changesets to release 3 packages
Name Type
thirdweb Patch
@thirdweb-dev/nebula Patch
@thirdweb-dev/wagmi-adapter Patch

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

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

Copy link
Contributor

coderabbitai bot commented Sep 22, 2025

Walkthrough

Callback signatures for BuyWidget and BridgeOrchestrator now carry a quote object (or optional quote). Dashboard analytics adds token-buy reporting functions and relaxes asset-buy contractType to allow undefined. BuyAndSwapEmbed updated to use new callbacks and emit token-level analytics. A changeset documents the API updates.

Changes

Cohort / File(s) Summary
UI buy/bridge callback API
packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx, packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
Public callbacks extended to include quote data: onSuccess(quote), onError(error, quote?), onCancel(quote?). Components propagate and guard on quote, narrow to buy/onramp where applicable, and wire handlers to forward the quote. Added BuyOrOnrampPrepareResult type alias and updated imports.
Dashboard analytics: token buy events
apps/dashboard/src/@/analytics/report.ts
Added TokenBuyParams type and exported reportTokenBuySuccessful, reportTokenBuyFailed, and reportTokenBuyCancelled. Made contractType optional (`AssetContractType
Dashboard widget integration
apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx
Updated BuyWidget callback signatures to receive quote; added token-level reporting calls on buy success/error/cancel using quote-derived token context; adjusted asset-level reports to set contractType = undefined for DropERC20 paths.
Changeset documentation
.changeset/better-lines-rule.md
Documents the BuyWidget prop signature updates with example usages showing quote passed to onSuccess, onError, and onCancel.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User
  participant BW as BuyWidget
  participant BO as BridgeOrchestrator
  participant A as Analytics

  Note over BW,BO: Callbacks now include quote (or optional quote)
  U->>BW: Initiate buy/onramp
  BW->>BO: prepare/execute
  BO-->>BO: produce quote
  alt Success
    BO-->>BW: complete(quote)
    BW-->>A: reportTokenBuySuccessful({buyTokenChainId, buyTokenAddress, pageType})
    BW-->>U: onSuccess(quote)
  else Error
    BO-->>BW: error(err, quote?)
    BW-->>A: reportTokenBuyFailed({buyTokenChainId, buyTokenAddress, pageType})
    BW-->>U: onError(err, quote?)
  else Cancel
    BO-->>BW: cancel(quote?)
    BW-->>A: reportTokenBuyCancelled({buyTokenChainId, buyTokenAddress, pageType})
    BW-->>U: onCancel(quote?)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning The PR implements token-buy analytics functions and wires token-level reporting into BuyWidget success/error/cancel flows while threading the quote object through callbacks, which satisfies much of MNY-204's intent; nevertheless the provided summary explicitly notes "no change to SwapWidget paths," so the PR does not fully meet the linked issue requirement to add token-buy tracking across both swap and buy widgets on all pages. Extend the same token-level reporting and quote-passing instrumentation to SwapWidget flows, verify event payloads across all pages (asset/bridge/chain), and include test steps or example analytics payloads to demonstrate coverage for success, error, and cancellation.
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "[MNY-204] Dashboard: Add tracking for BuyWidget, SDK: update callback types in BuyWidget" succinctly summarizes the primary work — adding dashboard tracking and updating SDK callback signatures for BuyWidget — and follows the repository prefix convention, so it's clear and relevant to the changes in the diff.
Out of Scope Changes Check ✅ Passed The modified files and signatures are closely related to the stated objectives (analytics/report additions, BuyWidget and BridgeOrchestrator callback changes, and dashboard wiring), and I do not see unrelated feature changes in the provided summaries; note that the SDK public callback signature changes are broad by nature and should be communicated as breaking/upgrade notes.
Description Check ✅ Passed The PR description includes the repository template and a concise PR-Codex overview that documents the intent, the API changes to BuyWidget, the analytics additions, and BridgeOrchestrator wiring; this provides sufficient context for reviewers to understand the changeset. However the template's non-commented "How to test" and "Notes for the reviewer" sections are not filled out, which would help reviewers validate behavior and downstream impacts.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 09-23-_mny-204_dashboard_add_tracking_for_buywidget_sdk_update_callback_types_in_buywidget

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ff1453b and a94f229.

📒 Files selected for processing (5)
  • .changeset/better-lines-rule.md (1 hunks)
  • apps/dashboard/src/@/analytics/report.ts (6 hunks)
  • apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx (2 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (7 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • .changeset/better-lines-rule.md
  • apps/dashboard/src/@/analytics/report.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

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

Files:

  • apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx
apps/{dashboard,playground}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx
apps/{dashboard,playground}/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Expose a className prop on the root element of every component

Files:

  • apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx
packages/thirdweb/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

packages/thirdweb/**/*.{ts,tsx}: Every public symbol must have comprehensive TSDoc with at least one compiling @example and a custom tag (@beta, @internal, @experimental, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Lazy‑load heavy dependencies inside async paths (e.g., const { jsPDF } = await import("jspdf"))

Files:

  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
🧬 Code graph analysis (3)
apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx (1)
apps/dashboard/src/@/analytics/report.ts (6)
  • reportTokenBuyFailed (272-274)
  • reportAssetBuyFailed (350-362)
  • reportTokenBuyCancelled (284-286)
  • reportAssetBuyCancelled (372-382)
  • reportTokenBuySuccessful (260-262)
  • reportAssetBuySuccessful (226-236)
packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (2)
packages/thirdweb/src/react/core/hooks/useBridgePrepare.ts (1)
  • BridgePrepareResult (23-27)
packages/thirdweb/src/bridge/Buy.ts (1)
  • quote (104-156)
packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (6)
packages/thirdweb/src/react/core/hooks/useBridgePrepare.ts (1)
  • BridgePrepareResult (23-27)
packages/thirdweb/src/react/core/hooks/useStepExecutor.ts (1)
  • CompletedStatusResult (25-32)
packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx (1)
  • StepRunner (67-406)
packages/thirdweb/src/react/web/adapters/WindowAdapter.ts (1)
  • webWindowAdapter (23-23)
packages/thirdweb/src/react/web/ui/Bridge/payment-success/SuccessScreen.tsx (1)
  • SuccessScreen (54-200)
packages/thirdweb/src/react/web/ui/TransactionButton/ExecutingScreen.tsx (1)
  • ExecutingTxScreen (19-183)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: Lint Packages
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: Size
  • GitHub Check: Unit Tests
  • GitHub Check: Build Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (16)
apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx (5)

12-14: LGTM!

Import additions are well-structured and align with the token-level analytics objectives.


72-99: LGTM! Strong type safety with discriminated union handling.

The implementation correctly uses discriminated union type narrowing with the quote?.type property to extract the appropriate token information. The type guards ensure that token context is only extracted for "buy" or "onramp" quote types, maintaining type safety.


100-124: LGTM! Consistent pattern implementation.

The onCancel handler follows the same discriminated union pattern established in the onError handler, ensuring consistency across callback implementations.


125-149: LGTM! Proper handling of optional vs required quote.

The onSuccess callback correctly handles the fact that quote is required (not optional like in onError/onCancel), and applies appropriate type narrowing for the discriminated union.


96-96: Approve: contractType can be undefined in analytics reporting

Verified — analytics functions accept contractType: AssetContractType | undefined (reportAssetBuySuccessful / reportAssetBuyFailed / reportAssetBuyCancelled in apps/dashboard/src/@/analytics/report.ts), so changing "DropERC20" to undefined is valid.

packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (4)

26-26: LGTM!

Import is correctly added to support the new quote-based callback signatures.


36-39: LGTM! Clean type alias for discriminated union extraction.

The BuyOrOnrampPrepareResult type alias correctly extracts the "buy" and "onramp" variants from BridgePrepareResult, providing type safety for the callback signatures.


164-164: LGTM! Well-designed callback signature updates with comprehensive TSDoc.

The callback signatures have been properly updated to include quote parameters:

  • onSuccess receives a required BuyOrOnrampPrepareResult
  • onError receives the error and an optional quote
  • onCancel receives an optional quote

The existing TSDoc documentation remains comprehensive and accurate.

Also applies to: 169-169, 174-174


456-473: LGTM! Consistent type guards throughout all callback handlers.

All three callback handlers (onCancel, onComplete, onError) correctly implement type guards to ensure that only "buy" or "onramp" quote types are forwarded to the props callbacks. This maintains type safety and prevents invalid quote types from reaching consumer code.

packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (7)

85-85: LGTM! Callback signature updates align with PR objectives.

The callback signatures have been appropriately updated to include quote context:

  • onComplete now receives a BridgePrepareResult for success tracking
  • onError now receives both error and optional quote for enhanced error reporting
  • onCancel now receives an optional quote for cancellation tracking

Also applies to: 90-90, 95-95


192-198: LGTM! Quote forwarding in transaction completion.

The handlePostBuyTransactionComplete callback correctly accepts and forwards the quote to the onComplete callback, maintaining the flow of quote context through the transaction lifecycle.


204-204: LGTM! Error handling with quote context.

The error handler correctly extracts the quote from state context and forwards it to the onError callback, providing enhanced error reporting capabilities.

Also applies to: 207-207


233-243: LGTM! Execution completion with quote propagation.

The handleExecutionComplete callback correctly accepts the quote parameter and forwards it to onComplete when not in transaction mode, maintaining consistency with the quote-based callback pattern.


250-250: LGTM! Local quote extraction for reuse.

Extracting the quote from state context to a local variable improves code readability and reduces repetitive access patterns throughout the component.


274-274: LGTM! Consistent quote threading throughout render branches.

All render branches correctly thread the quote through their respective components:

  • Error banner receives quote for cancellation
  • StepRunner receives quote for callbacks
  • SuccessScreen receives quote for display
  • ExecutingTxScreen receives quote for completion

The pattern is consistently implemented across all conditional renders.

Also applies to: 388-388, 391-391, 400-400, 406-406, 415-415, 418-418


380-380: Execute state guarantees quote & request are set.

QUOTE_RECEIVED sets ctx.quote and ctx.request and transitions to "preview", and only ROUTE_CONFIRMED from "preview" moves to "execute" — therefore when value === "execute" the quote and request will be present and the UI guard is correct.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • TEAM-0000: Entity not found: Issue - Could not find referenced Issue.

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

@MananTank MananTank marked this pull request as ready for review September 22, 2025 21:18
@github-actions github-actions bot added the Dashboard Involves changes to the Dashboard. label Sep 22, 2025
@github-actions github-actions bot added packages SDK Involves changes to the thirdweb SDK labels Sep 22, 2025
@MananTank MananTank requested review from a team as code owners September 22, 2025 21:18
Copy link
Member Author

MananTank commented Sep 22, 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.

Copy link
Contributor

github-actions bot commented Sep 22, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
thirdweb (esm) 64.07 KB (0%) 1.3 s (0%) 307 ms (+115.57% 🔺) 1.6 s
thirdweb (cjs) 361.6 KB (0%) 7.3 s (0%) 1.1 s (+10.05% 🔺) 8.3 s
thirdweb (minimal + tree-shaking) 5.73 KB (0%) 115 ms (0%) 127 ms (+2396.32% 🔺) 242 ms
thirdweb/chains (tree-shaking) 526 B (0%) 11 ms (0%) 76 ms (+2530.38% 🔺) 86 ms
thirdweb/react (minimal + tree-shaking) 19.14 KB (0%) 383 ms (0%) 109 ms (+1551.12% 🔺) 492 ms

Copy link

codecov bot commented Sep 22, 2025

Codecov Report

❌ Patch coverage is 0% with 49 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.32%. Comparing base (5249cb7) to head (a94f229).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...web/src/react/web/ui/Bridge/BridgeOrchestrator.tsx 0.00% 37 Missing ⚠️
...ges/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx 0.00% 12 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8100      +/-   ##
==========================================
- Coverage   56.33%   56.32%   -0.01%     
==========================================
  Files         906      906              
  Lines       59181    59197      +16     
  Branches     4178     4176       -2     
==========================================
+ Hits        33341    33345       +4     
- Misses      25735    25746      +11     
- Partials      105      106       +1     
Flag Coverage Δ
packages 56.32% <0.00%> (-0.01%) ⬇️
Files with missing lines Coverage Δ
...ges/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx 8.69% <0.00%> (-0.34%) ⬇️
...web/src/react/web/ui/Bridge/BridgeOrchestrator.tsx 6.66% <0.00%> (-0.28%) ⬇️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx (1)

24-31: Expose className on root element per dashboard guidelines.

Add className?: string to props and merge it into the root div.

 export function BuyAndSwapEmbed(props: {
   client: ThirdwebClient;
   chain: Chain;
   tokenAddress: string | undefined;
   buyAmount: string | undefined;
   pageType: "asset" | "bridge" | "chain";
+  className?: string;
 }) {
 ...
-  return (
-    <div className="bg-card rounded-2xl border overflow-hidden flex flex-col relative z-10">
+  return (
+    <div className={cn("bg-card rounded-2xl border overflow-hidden flex flex-col relative z-10", props.className)}>

Also consider adding className?: string to TabButton props and merging it similarly.

Also applies to: 48-49

🧹 Nitpick comments (6)
.changeset/better-lines-rule.md (1)

7-13: Fix example copy: use “Buy …” (not “Swap …”) to match BuyWidget.

Keeps docs consistent with the widget’s purpose.

Apply this diff:

 <BuyWidget
-  onSuccess={(quote) => console.log("Swap completed:", quote)}
-  onError={(error, quote) => console.error("Swap failed:", error, quote)}
-  onCancel={(quote) => console.log("Swap cancelled:", quote)}
+  onSuccess={(quote) => console.log("Buy completed:", quote)}
+  onError={(error, quote) => console.error("Buy failed:", error, quote)}
+  onCancel={(quote) => console.log("Buy cancelled:", quote)}
 />

Optional: annotate types for clarity in the snippet, e.g., (quote: Quote) and (error: unknown, quote: Quote).

apps/dashboard/src/@/analytics/report.ts (1)

264-275: Include errorMessage in failed token buy for parity with swap failed.

Capturing the error helps triage failures and mirrors reportTokenSwapFailed.

Apply:

-type TokenBuyParams = {
+type TokenBuyParams = {
   buyTokenChainId: number | undefined;
   buyTokenAddress: string | undefined;
   pageType: "asset" | "bridge" | "chain";
 };
 
+type TokenBuyFailedParams = TokenBuyParams & { errorMessage: string };
+
 /**
  * ### Why do we need to report this event?
  * - To track number of failed token buys
  * - To track which token buys are failing
  *
  * ### Who is responsible for this event?
  * @MananTank
  */
-export function reportTokenBuyFailed(properties: TokenBuyParams) {
+export function reportTokenBuyFailed(properties: TokenBuyFailedParams) {
   posthog.capture("token buy failed", properties);
 }

Follow-up in BuyAndSwapEmbed to pass errorMessage (see comment there).

apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx (3)

72-99: De-duplicate quote→props mapping and add errorMessage in failed token buy.

  • Mapping logic repeats across error/cancel/success.
  • If you accept adding errorMessage in report.ts, pass it here.

Apply:

         onError={(e, quote) => {
           const errorMessage = parseError(e);
-
-          reportTokenBuyFailed({
-            buyTokenChainId:
-              quote?.type === "buy"
-                ? quote.intent.destinationChainId
-                : quote?.type === "onramp"
-                  ? quote.intent.chainId
-                  : undefined,
-            buyTokenAddress:
-              quote?.type === "buy"
-                ? quote.intent.destinationTokenAddress
-                : quote?.type === "onramp"
-                  ? quote.intent.tokenAddress
-                  : undefined,
-            pageType: props.pageType,
-          });
+          const toTokenProps = (q: typeof quote) => ({
+            buyTokenChainId:
+              q?.type === "buy"
+                ? q.intent.destinationChainId
+                : q?.type === "onramp"
+                  ? q.intent.chainId
+                  : undefined,
+            buyTokenAddress:
+              q?.type === "buy"
+                ? q.intent.destinationTokenAddress
+                : q?.type === "onramp"
+                  ? q.intent.tokenAddress
+                  : undefined,
+            pageType: props.pageType,
+          });
+
+          reportTokenBuyFailed({
+            ...toTokenProps(quote),
+            errorMessage,
+          });

If you prefer a top-level helper, I can extract it.


100-124: Cancel path: reuse the same toTokenProps helper.

Reduces duplication and keeps mapping consistent.

-          onCancel={(quote) => {
-            reportTokenBuyCancelled({
-              buyTokenChainId:
-                quote?.type === "buy"
-                  ? quote.intent.destinationChainId
-                  : quote?.type === "onramp"
-                    ? quote.intent.chainId
-                    : undefined,
-              buyTokenAddress:
-                quote?.type === "buy"
-                  ? quote.intent.destinationTokenAddress
-                  : quote?.type === "onramp"
-                    ? quote.intent.tokenAddress
-                    : undefined,
-              pageType: props.pageType,
-            });
+          onCancel={(quote) => {
+            reportTokenBuyCancelled(toTokenProps(quote));

125-149: Success path: reuse the same toTokenProps helper.

Keeps all three callbacks uniform.

-          onSuccess={(quote) => {
-            reportTokenBuySuccessful({
-              buyTokenChainId:
-                quote.type === "buy"
-                  ? quote.intent.destinationChainId
-                  : quote.type === "onramp"
-                    ? quote.intent.chainId
-                    : undefined,
-              buyTokenAddress:
-                quote.type === "buy"
-                  ? quote.intent.destinationTokenAddress
-                  : quote.type === "onramp"
-                    ? quote.intent.tokenAddress
-                    : undefined,
-              pageType: props.pageType,
-            });
+          onSuccess={(quote) => {
+            reportTokenBuySuccessful(toTokenProps(quote));
packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (1)

456-473: DRY the quote type guard across handlers.

Minor cleanup to avoid repeating the predicate.

-        onCancel={(quote) => {
-          // type guard
-          if (quote?.type === "buy" || quote?.type === "onramp") {
-            props.onCancel?.(quote);
-          }
-        }}
-        onComplete={(quote) => {
-          // type guard
-          if (quote?.type === "buy" || quote?.type === "onramp") {
-            props.onSuccess?.(quote);
-          }
-        }}
-        onError={(err: Error, quote) => {
-          // type guard
-          if (quote?.type === "buy" || quote?.type === "onramp") {
-            props.onError?.(err, quote);
-          }
-        }}
+        onCancel={(quote) => {
+          const isBuyOrOnramp = quote?.type === "buy" || quote?.type === "onramp";
+          if (isBuyOrOnramp) props.onCancel?.(quote);
+        }}
+        onComplete={(quote) => {
+          const isBuyOrOnramp = quote?.type === "buy" || quote?.type === "onramp";
+          if (isBuyOrOnramp) props.onSuccess?.(quote);
+        }}
+        onError={(err: Error, quote) => {
+          const isBuyOrOnramp = quote?.type === "buy" || quote?.type === "onramp";
+          if (isBuyOrOnramp) props.onError?.(err, quote);
+        }}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b37ed57 and 9280df8.

📒 Files selected for processing (5)
  • .changeset/better-lines-rule.md (1 hunks)
  • apps/dashboard/src/@/analytics/report.ts (6 hunks)
  • apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx (3 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (7 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (4 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

.changeset/*.md: Each change in packages/* must include a changeset for the appropriate package
Version bump rules: patch for non‑API changes; minor for new/modified public API

Files:

  • .changeset/better-lines-rule.md
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

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

Files:

  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
  • apps/dashboard/src/@/analytics/report.ts
  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
  • apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
  • apps/dashboard/src/@/analytics/report.ts
  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
  • apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx
packages/thirdweb/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

packages/thirdweb/**/*.{ts,tsx}: Every public symbol must have comprehensive TSDoc with at least one compiling @example and a custom tag (@beta, @internal, @experimental, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Lazy‑load heavy dependencies inside async paths (e.g., const { jsPDF } = await import("jspdf"))

Files:

  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • apps/dashboard/src/@/analytics/report.ts
  • apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx
apps/{dashboard,playground}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • apps/dashboard/src/@/analytics/report.ts
  • apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx
apps/{dashboard,playground}/src/@/analytics/report.ts

📄 CodeRabbit inference engine (AGENTS.md)

apps/{dashboard,playground}/src/@/analytics/report.ts: Check report.ts before adding a new analytics event to avoid duplicates
Analytics naming: event name as <subject> <verb>; helper function as report<Subject><Verb> (PascalCase)
Each analytics helper must include a JSDoc header (Why/Owner), accept a single typed properties object, and forward it unchanged to posthog.capture

Files:

  • apps/dashboard/src/@/analytics/report.ts
apps/{dashboard,playground}/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Expose a className prop on the root element of every component

Files:

  • apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx
🧠 Learnings (6)
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to src/@/analytics/report.ts : Analytics event name: human-readable `<subject> <verb>` (e.g., "contract deployed"); function: `report<Subject><Verb>` (PascalCase)

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to src/@/analytics/report.ts : Review `src/@/analytics/report.ts` before adding analytics events to check for duplicates

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to apps/{dashboard,playground}/src/@/analytics/report.ts : Analytics naming: event name as `<subject> <verb>`; helper function as `report<Subject><Verb>` (PascalCase)

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to apps/{dashboard,playground}/src/@/analytics/report.ts : Check `report.ts` before adding a new analytics event to avoid duplicates

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/src/@/analytics/report.ts : Mandatory JSDoc: explain Why the event exists and Who owns it (`username`).

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/src/@/analytics/report.ts : Typed properties: accept a single `properties` object and pass it unchanged to `posthog.capture`.

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
🧬 Code graph analysis (3)
packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (5)
packages/thirdweb/src/react/core/hooks/useBridgePrepare.ts (1)
  • BridgePrepareResult (23-27)
packages/thirdweb/src/react/core/hooks/useStepExecutor.ts (1)
  • CompletedStatusResult (25-32)
packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx (1)
  • StepRunner (67-406)
packages/thirdweb/src/react/web/ui/Bridge/payment-success/SuccessScreen.tsx (1)
  • SuccessScreen (54-200)
packages/thirdweb/src/react/web/ui/TransactionButton/ExecutingScreen.tsx (1)
  • ExecutingTxScreen (19-183)
packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (1)
packages/thirdweb/src/react/core/hooks/useBridgePrepare.ts (1)
  • BridgePrepareResult (23-27)
apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx (1)
apps/dashboard/src/@/analytics/report.ts (6)
  • reportTokenBuyFailed (272-274)
  • reportAssetBuyFailed (350-362)
  • reportTokenBuyCancelled (284-286)
  • reportAssetBuyCancelled (372-382)
  • reportTokenBuySuccessful (260-262)
  • reportAssetBuySuccessful (226-236)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Unit Tests
  • GitHub Check: Build Packages
  • GitHub Check: Size
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (24)
.changeset/better-lines-rule.md (1)

1-3: Verify affected package(s) are correctly listed.

If BuyWidget lives in a different publishable package (or multiple), add each package name (from its package.json) to the changeset front‑matter. Automated search returned no matches here — manually confirm which package(s) own BuyWidget and update .changeset accordingly.

apps/dashboard/src/@/analytics/report.ts (9)

246-251: TokenBuyParams shape looks good and minimal.

Fields align with usage across BuyWidget and onramp/buy flows. LGTM.


252-263: New token buy success event: naming + pass-through match guidelines.

Event name and helper naming follow our conventions; properties are forwarded unchanged. LGTM.


278-286: Token buy cancelled: naming + pass-through OK.

Consistent with conventions; JSDoc present. LGTM.


289-295: Doc tweak for swap success.

No functional change. LGTM.


314-322: Doc tweak for swap failed.

No functional change. LGTM.


332-340: Doc tweak for swap cancelled.

No functional change. LGTM.


350-362: No change needed — contractType already optional

reportAssetBuyFailed declares contractType: AssetContractType | undefined in apps/dashboard/src/@/analytics/report.ts and an rg search found no other "asset buy failed" captures in apps TypeScript.


372-382: Make contractType optional and verify analytics handling

Change properties.contractType to an optional property (contractType?: AssetContractType) in apps/dashboard/src/@/analytics/report.ts and ensure the capture payload omits the field when unknown (don’t send explicit undefined). Verify PostHog/BI dashboards, cohorts, and ingestion tolerate missing/null contractType or map it to a consistent sentinel.


226-235: Make contractType optional — confirm downstream analytics tolerate undefined.

Repo search found only this capture (apps/dashboard/src/@/analytics/report.ts, ~lines 226–235). That doesn't guarantee external consumers (PostHog schema, PostHog→warehouse exports, ETL, Looker/Metabase/SQL dashboards) handle nulls. Actions:

  • Confirm PostHog event schema and any exported event tables accept null contractType.
  • Search/update BI dashboards / SQL queries that filter or group by contractType to handle nulls.
  • If consumers can't handle null, either send a fallback (e.g., contractType: properties.contractType ?? 'unknown') or update those consumers.
apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx (3)

12-18: New token-level reporting imports: good integration.

Imports align with new helpers in report.ts.


217-221: Active tab styles: OK.

Use of design tokens and cn() is consistent. LGTM.


91-98: Asset events: contractType set to undefined — confirm dashboards don't rely on it.
analytics/report.ts capture handlers for "asset buy successful/failed/cancelled" (lines 231, 356, 377) only include assetType and chainId; passing undefined matches the schema change — confirm downstream dashboards/pipeline won't break.
Location: apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx lines 91–98 (also 117–123, 142–147).

packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (3)

26-26: Import BridgePrepareResult: correct source for narrowing.

Type-only import keeps bundle clean. LGTM.


36-39: Local narrowing type is precise and avoids exporting internals.

Extract<..., { type: "buy" | "onramp" }> is the right constraint. LGTM.


164-175: Public API change — update TSDoc for BuyWidget callbacks

  • Changeset exists: .changeset/better-lines-rule.md documents that onSuccess/onError/onCancel now receive the quote.
  • Update prop docs in packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx to state:
    • onSuccess(quote: BuyOrOnrampPrepareResult)
    • onError(error: Error, quote: BuyOrOnrampPrepareResult | undefined) — quote may be undefined
    • onCancel(quote: BuyOrOnrampPrepareResult | undefined) — quote may be undefined
packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (8)

192-198: Post-transaction completion passes quote: correct for transaction mode.

Resets state after notifying parent. LGTM.


201-208: Error path forwards current quote; dependency array includes it.

Avoids stale capture; console.error is acceptable here. LGTM.


233-243: Execution complete: quote forwarding gated by mode is correct.

Avoids double-calling in transaction mode. LGTM.


250-251: Local alias for quote improves readability.

Centralizes quote usage below. LGTM.


380-397: Execute state wires cancel/complete with quote: correct.

Propagation matches new prop signatures.


399-411: Success screen uses preparedQuote from state: correct.

No risk; analytics downstream rely on this shape already. LGTM.


413-425: Post-buy transaction: on close, notify with quote then reset.

Matches the intended flow. LGTM.


85-96: Public API passes quote to callbacks — update story call sites

Public API now passes BridgePrepareResult to onComplete/onError/onCancel (good). Update remaining zero-arg handlers in packages/thirdweb/src/stories/Bridge/BridgeOrchestrator.stories.tsx (args.onComplete, args.onCancel) to accept the quote param (e.g., (quote) => {} or (_quote) => {}).

Likely an incorrect or invalid review comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (2)

456-473: Consider adding TSDoc for the new callback parameters.

The callback props in the interface have TSDoc comments, but they don't describe the new quote parameters or their purpose for tracking. Consider updating the documentation to help developers understand what data is available in the quote object.

Example documentation update:

  /**
   * Callback triggered when the purchase is successful.
+  * @param quote - Contains transaction details including token, amount, and provider information
   */
  onSuccess?: (quote: BuyOrOnrampPrepareResult) => void;

36-39: Add unit tests for BuyWidget callback forwarding

BridgeOrchestrator forwards onCancel/onComplete/onError to BuyWidget props only for quotes with type "buy" | "onramp", and there are no tests covering this. Add unit tests in packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (BridgeOrchestrator props — ~lines 440–500) to verify:

  • Type guards only forward quotes with type "buy" or "onramp".
  • onCancel / onSuccess / onError are invoked with the expected quote payload for "buy"/"onramp".
  • Callbacks are not invoked for unsupported quote types.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9280df8 and ff1453b.

📒 Files selected for processing (5)
  • .changeset/better-lines-rule.md (1 hunks)
  • apps/dashboard/src/@/analytics/report.ts (6 hunks)
  • apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx (2 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (7 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • .changeset/better-lines-rule.md
  • apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

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

Files:

  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
  • apps/dashboard/src/@/analytics/report.ts
  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
  • apps/dashboard/src/@/analytics/report.ts
  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
packages/thirdweb/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

packages/thirdweb/**/*.{ts,tsx}: Every public symbol must have comprehensive TSDoc with at least one compiling @example and a custom tag (@beta, @internal, @experimental, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Lazy‑load heavy dependencies inside async paths (e.g., const { jsPDF } = await import("jspdf"))

Files:

  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • apps/dashboard/src/@/analytics/report.ts
apps/{dashboard,playground}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • apps/dashboard/src/@/analytics/report.ts
apps/{dashboard,playground}/src/@/analytics/report.ts

📄 CodeRabbit inference engine (AGENTS.md)

apps/{dashboard,playground}/src/@/analytics/report.ts: Check report.ts before adding a new analytics event to avoid duplicates
Analytics naming: event name as <subject> <verb>; helper function as report<Subject><Verb> (PascalCase)
Each analytics helper must include a JSDoc header (Why/Owner), accept a single typed properties object, and forward it unchanged to posthog.capture

Files:

  • apps/dashboard/src/@/analytics/report.ts
🧠 Learnings (8)
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to src/@/analytics/report.ts : Analytics event name: human-readable `<subject> <verb>` (e.g., "contract deployed"); function: `report<Subject><Verb>` (PascalCase)

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to apps/{dashboard,playground}/src/@/analytics/report.ts : Analytics naming: event name as `<subject> <verb>`; helper function as `report<Subject><Verb>` (PascalCase)

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to src/@/analytics/report.ts : Review `src/@/analytics/report.ts` before adding analytics events to check for duplicates

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to apps/{dashboard,playground}/src/@/analytics/report.ts : Each analytics helper must include a JSDoc header (Why/Owner), accept a single typed `properties` object, and forward it unchanged to `posthog.capture`

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to apps/{dashboard,playground}/src/@/analytics/report.ts : Check `report.ts` before adding a new analytics event to avoid duplicates

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/src/@/analytics/report.ts : Reporting helper: `report<Subject><Verb>` (PascalCase); all live in `src/@/analytics/report.ts`.

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/src/@/analytics/report.ts : Typed properties: accept a single `properties` object and pass it unchanged to `posthog.capture`.

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/src/@/analytics/report.ts : Mandatory JSDoc: explain Why the event exists and Who owns it (`username`).

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
🧬 Code graph analysis (2)
packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (4)
packages/thirdweb/src/react/core/hooks/useBridgePrepare.ts (1)
  • BridgePrepareResult (23-27)
packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx (1)
  • StepRunner (67-406)
packages/thirdweb/src/react/web/ui/Bridge/payment-success/SuccessScreen.tsx (1)
  • SuccessScreen (54-200)
packages/thirdweb/src/react/web/ui/TransactionButton/ExecutingScreen.tsx (1)
  • ExecutingTxScreen (19-183)
packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (1)
packages/thirdweb/src/react/core/hooks/useBridgePrepare.ts (1)
  • BridgePrepareResult (23-27)
🪛 GitHub Check: codecov/patch
packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx

[warning] 192-198: packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L192-L198
Added lines #L192 - L198 were not covered by tests


[warning] 204-204: packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L204
Added line #L204 was not covered by tests


[warning] 207-207: packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L207
Added line #L207 was not covered by tests


[warning] 233-236: packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L233-L236
Added lines #L233 - L236 were not covered by tests


[warning] 239-239: packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L239
Added line #L239 was not covered by tests


[warning] 250-250: packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L250
Added line #L250 was not covered by tests


[warning] 274-274: packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L274
Added line #L274 was not covered by tests


[warning] 380-396: packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L380-L396
Added lines #L380 - L396 were not covered by tests


[warning] 400-400: packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L400
Added line #L400 was not covered by tests


[warning] 406-406: packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L406
Added line #L406 was not covered by tests


[warning] 415-415: packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L415
Added line #L415 was not covered by tests


[warning] 418-418: packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L418
Added line #L418 was not covered by tests

packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx

[warning] 456-456: packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx#L456
Added line #L456 was not covered by tests


[warning] 458-460: packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx#L458-L460
Added lines #L458 - L460 were not covered by tests


[warning] 462-462: packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx#L462
Added line #L462 was not covered by tests


[warning] 464-466: packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx#L464-L466
Added lines #L464 - L466 were not covered by tests


[warning] 468-468: packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx#L468
Added line #L468 was not covered by tests


[warning] 470-472: packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx#L470-L472
Added lines #L470 - L472 were not covered by tests

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Size
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (23)
apps/dashboard/src/@/analytics/report.ts (7)

228-228: LGTM! Making contractType optional aligns with the new token-centric tracking approach.

The change allows for more flexible reporting when contract type information may not be available, which is appropriate for the broader token-buy tracking scope.


246-250: Well-structured type definition for token-buy tracking.

The TokenBuyParams type properly supports the new token-level analytics by allowing optional token identifiers and including the necessary pageType context. The undefined values for buyTokenChainId and buyTokenAddress appropriately handle cases where token information might not be available during the buy flow.


252-262: Excellent implementation following established patterns.

The function correctly implements the required JSDoc structure with clear "Why" and "Who" sections, accepts a single typed properties object, and forwards it unchanged to posthog.capture. The event name follows the established <subject> <verb> pattern.


264-274: Consistent implementation for failed token-buy tracking.

The function maintains consistency with other reporting functions and properly uses the shared TokenBuyParams type.


276-286: Consistent implementation for cancelled token-buy tracking.

The function maintains consistency with the other token-buy reporting functions and follows the established patterns.


352-352: LGTM! Consistent application of optional contractType.

The changes to make contractType optional in both reportAssetBuyFailed and reportAssetBuyCancelled maintain consistency with the reportAssetBuySuccessful function and support the broader token-buy tracking requirements.

Also applies to: 374-374


278-279: Minor wording improvements in JSDoc comments.

The updated comments better reflect the token-focused nature of the events and improve clarity by changing "track number of" to more natural phrasing.

Also applies to: 288-291, 316-316, 332-332, 344-344

packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (10)

85-95: LGTM: Proper type-safe callback signature updates.

The callback signatures have been updated to include the quote parameter, which enables proper propagation of transaction context to consumers. The type safety is maintained with BridgePrepareResult type and proper handling of undefined quotes in error and cancel scenarios.


192-198: LGTM: Quote parameter properly threaded through completion handler.

The handler correctly accepts and forwards the quote to the callback, maintaining consistency with the updated API signature.


201-208: LGTM: Context-aware error handling with quote propagation.

The error handler now properly includes the current quote from state context when invoking the error callback, providing valuable transaction context for error handling and analytics.


232-243: LGTM: Execution completion properly handles quote forwarding.

The completion handler correctly accepts the quote parameter and conditionally forwards it to onComplete based on the UI mode, maintaining proper separation between transaction and non-transaction flows.


250-250: LGTM: Efficient quote reference extraction.

Using a local variable for the quote reduces repetitive access to state.context.quote throughout the render function.


270-278: LGTM: Error screen cancel handler includes quote context.

The cancel callback in the error banner properly includes the quote context, enabling analytics tracking of cancellations even during error states.


380-397: LGTM: StepRunner integration with quote-aware callbacks.

The execution phase correctly:

  • Guards against undefined quote before rendering
  • Passes quote through to both cancel and complete handlers
  • Maintains proper callback signatures

399-411: LGTM: Success screen receives quote for analytics.

The success screen properly receives the quote parameter, enabling completion analytics tracking.


413-425: LGTM: Post-buy transaction completion includes quote context.

The transaction execution screen properly forwards the quote to the completion handler, maintaining transaction context through the entire flow.


380-425: Guard quote before use in renders and callbacks

Render branches already guard for quote (preview / execute / success / post-buy-transaction). Two unguarded usages found — either add guards or ensure the receivers handle undefined:

  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx — line ~204: onError?.(error, state.context.quote) passes state.context.quote into the callback without an explicit guard.
  • packages/thirdweb/src/react/web/ui/Bridge/swap-widget/SwapWidget.tsx — lines ~353–356: setScreen({ id: "error", preparedQuote: quote, … }) assigns quote into UI state without an explicit guard.
packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (6)

26-26: LGTM! Clean import addition.

The new import for BridgePrepareResult is correctly added and necessary for the type alias below.


36-39: Well-designed type alias for callback specificity.

The BuyOrOnrampPrepareResult type alias appropriately extracts only the relevant quote types ("buy" and "onramp") from the broader BridgePrepareResult union. This provides type safety for the callback parameters while maintaining clarity about which operations are supported by this widget.


164-164: Enhanced callback signatures improve tracking capabilities.

The updated callback signatures now include quote objects, enabling detailed analytics and reporting:

  • onSuccess receives the complete quote for successful transactions
  • onError receives both error and optional quote for failed attempts
  • onCancel receives optional quote for cancelled operations

This aligns well with the PR objective to add token-buy tracking across the dashboard.

Also applies to: 169-169, 174-174


462-467: Consistent type guarding for success callbacks.

The onComplete to onSuccess forwarding maintains the same type guard pattern, ensuring only relevant quote types trigger the success callback. The naming change from "Complete" to "Success" in the forwarding also provides clearer semantic meaning.


468-473: Error handling maintains quote context.

The error callback forwarding preserves both the error and quote context while applying the same type guard. This enables comprehensive error reporting with transaction details when available.


456-461: Approve — type guard is correct and safe.

BridgeOrchestrator.onCancel is (quote: BridgePrepareResult | undefined) => void; the BuyWidget guard (quote?.type === "buy" || quote?.type === "onramp") correctly narrows the union to the Buy/Onramp variant before calling props.onCancel, ensuring type safety.

Copy link
Contributor

graphite-app bot commented Sep 22, 2025

Merge activity

… types in BuyWidget (#8100)

<!--

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

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

## Notes for the reviewer

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

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR enhances the `BuyWidget` and related components by updating the callback props to include a `quote` object, allowing for better tracking of token buy events and improving error handling.

### Detailed summary
- Updated `onSuccess`, `onError`, and `onCancel` props in `BuyWidget` to accept a `quote` object.
- Enhanced error reporting with detailed information in `reportTokenBuyFailed`, `reportTokenBuyCancelled`, and `reportTokenBuySuccessful`.
- Modified `BuyAndSwapEmbed` component to handle the new callback signatures.
- Adjusted `BridgeOrchestrator` to utilize the `quote` object in its flow.

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

<!-- end pr-codex -->

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

- New Features
  - Buy and Bridge flows now provide quote details to success, error, and cancel callbacks.
  - Token-level analytics added for buy flows (success, failure, cancel).
- Breaking Changes
  - Callback signatures changed to include quote parameters; client implementations must be updated.
- Documentation
  - Examples updated to show new callback parameters and usage.
- Chores
  - Standardized analytics for asset purchases where contract type may be unspecified.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Dashboard Involves changes to the Dashboard. packages SDK Involves changes to the thirdweb SDK
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants