Skip to content

Conversation

@joaquim-verges
Copy link
Member

@joaquim-verges joaquim-verges commented Sep 14, 2025


PR-Codex overview

This PR focuses on improving the handling of fiat payments in the thirdweb package by making wallet and payerWallet optional, enhancing error handling, and refining transaction execution logic.

Detailed summary

  • Added optional chaining for wallet and payerWallet in multiple files.
  • Improved error messages for missing recipient addresses and wallets.
  • Enhanced transaction execution logic to handle cases where no wallet is provided.
  • Updated PaymentDetails and BuyWidget components to utilize new optional props.

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

Summary by CodeRabbit

  • New Features

    • Added optional receiverAddress prop to the buy widget so callers can specify the recipient.
  • Bug Fixes

    • Fiat payments can proceed without a connected wallet when no transactions run; flows now validate recipient addresses and show clearer wallet-related errors when required.
    • Wallet handling made optional across bridge/payment steps to improve flow flexibility.
    • Background queries now return explicit values and cache by currency to stabilize quote tracking and refreshes.

@vercel
Copy link

vercel bot commented Sep 14, 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 14, 2025 10:46am
nebula Ready Ready Preview Comment Sep 14, 2025 10:46am
thirdweb_playground Ready Ready Preview Comment Sep 14, 2025 10:46am
thirdweb-www Ready Ready Preview Comment Sep 14, 2025 10:46am
wallet-ui Ready Ready Preview Comment Sep 14, 2025 10:46am

@changeset-bot
Copy link

changeset-bot bot commented Sep 14, 2025

🦋 Changeset detected

Latest commit: a38e299

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 14, 2025

Walkthrough

Optionalized wallet usage across fiat payment flows and step execution, added recipient-address resolution/validation for fiat payments, made several React Query functions explicitly return boolean, introduced a new optional BuyWidget prop, and added a patch changeset: “Fix fiat payments with no wallets connected.”

Changes

Cohort / File(s) Summary
Release changeset
\.changeset/fuzzy-suits-wear.md
Adds a patch changeset for the thirdweb package documenting the bug fix: “Fix fiat payments with no wallets connected.”
Core execution hook
packages/thirdweb/src/react/core/hooks/useStepExecutor.ts
StepExecutorOptions.wallet made optional; execution now skips wallet/account checks when there are no transactions; explicit errors thrown if transactions exist but wallet or account missing; preserves chain switching, batching, single-tx execution, completion, and error handling.
Payment machine types
packages/thirdweb/src/react/core/machines/paymentMachine.ts
PaymentMethod.fiat.payerWallet changed from required to optional (payerWallet?: Wallet).
Bridge orchestration & runner
packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx, packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx
Removed execute-branch guard requiring payerWallet; StepRunner.wallet made optional and is passed (possibly undefined) to the executor.
Quote & payment details queries
packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx, packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx
Query queryFns now explicitly return true; to satisfy typing/React Query expectations; PaymentDetails uses optional chaining when reading payerWallet address.
Payment selection (fiat)
packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx
Resolves recipient address from receiverAddress or payerWallet?.getAccount()?.address; errors if no recipient address available; fiat currency defaults preserved.
Buy flow caching
packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.tsx
Added currency to React Query key to scope cache per currency and trigger refetches on currency change.
Buy widget prop
packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
Added new optional prop receiverAddress?: Address and forwards it to BridgeOrchestrator.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User
  participant B as Bridge UI
  participant SR as StepRunner
  participant SE as useStepExecutor
  participant W as Wallet (optional)
  participant A as Account
  participant C as Chain

  U->>B: Select fiat payment (wallet may be absent)
  B->>SR: Render (wallet may be undefined)
  SR->>SE: start({ wallet?, steps })
  alt No transactions
    SE-->>SR: Skip wallet/account checks
    SR-->>B: Complete without tx execution
  else Transactions present
    alt Wallet missing
      SE-->>SR: Error "No wallet provided to execute transactions" (400)
      SR-->>B: Surface error
    else Wallet provided
      SE->>W: getAccount()
      alt No account
        SE-->>SR: Error "Wallet not connected" (400)
        SR-->>B: Surface error
      else Account present
        SE->>W: getChain()
        SE->>C: switch if needed
        opt Batch path
          SE->>A: sendBatchTransaction(batchedTxs)
        end
        opt Single-tx path
          SE->>A: sendTransaction(tx)
        end
        SE-->>SR: Completed statuses
        SR-->>B: onComplete()
      end
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The PR includes a useful PR‑Codex overview and detailed change summary but leaves the repository's required template fields as commented placeholders (notably "Notes for the reviewer", "How to test", and the title/issue tag header), so explicit reviewer guidance and concrete testing steps are missing. This reduces clarity for reviewers and QA. Populate the template's "Notes for the reviewer" and "How to test" sections and include the Linear/issue tag or branch info; add concrete reproduction steps and any required test commands or environments so reviewers can validate the change.
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% 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 title "[SDK] Fix fiat payments with no wallet connected" succinctly and accurately describes the PR's primary change—allowing fiat payments without a connected wallet by making wallet/payerWallet optional and adjusting execution logic—and follows the repository's prefix convention, so a teammate scanning history will understand the main intent.
Linked Issues Check ✅ Passed The changes map directly to linked issue #8032: wallet and payerWallet are made optional (paymentMachine, StepRunner, useStepExecutor), BridgeOrchestrator no longer gates execute on a payer wallet, PaymentSelection and BuyWidget now support supplying/deriving a recipient address, and useStepExecutor skips wallet/account checks when there are no transactions while still erroring clearly if a wallet is needed. These modifications enable fiat on‑ramp flows without a connected wallet while preserving explicit failures for wallet-required actions.
Out of Scope Changes Check ✅ Passed I did not find changes that appear unrelated to the linked issue's objectives; the optional wallet/payerWallet changes, removed wallet gating, receiverAddress prop, and small query return fixes all support enabling fiat payments without a connected wallet. The only notable public-facing change is relaxing StepRunner's wallet prop to optional, which aligns with the PR goal but should be noted for consumers.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch Fix_fiat_payments_with_no_wallet_connected

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.

@github-actions github-actions bot added packages SDK Involves changes to the thirdweb SDK labels Sep 14, 2025
@joaquim-verges joaquim-verges changed the title Fix fiat payments with no wallet connected [SDK] Fix fiat payments with no wallet connected Sep 14, 2025
@joaquim-verges joaquim-verges marked this pull request as ready for review September 14, 2025 09:44
@joaquim-verges joaquim-verges requested review from a team as code owners September 14, 2025 09:44
Copy link
Member Author


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.

@github-actions
Copy link
Contributor

github-actions bot commented Sep 14, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
thirdweb (esm) 63.96 KB (0%) 1.3 s (0%) 479 ms (+47.4% 🔺) 1.8 s
thirdweb (cjs) 361.44 KB (0%) 7.3 s (0%) 2.8 s (+5.47% 🔺) 10 s
thirdweb (minimal + tree-shaking) 5.73 KB (0%) 115 ms (0%) 124 ms (+784.74% 🔺) 238 ms
thirdweb/chains (tree-shaking) 526 B (0%) 11 ms (0%) 130 ms (+1472.89% 🔺) 141 ms
thirdweb/react (minimal + tree-shaking) 19.15 KB (0%) 383 ms (0%) 88 ms (+436.63% 🔺) 471 ms

@codecov
Copy link

codecov bot commented Sep 14, 2025

Codecov Report

❌ Patch coverage is 0% with 78 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.53%. Comparing base (9f9fadf) to head (a38e299).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...s/thirdweb/src/react/core/hooks/useStepExecutor.ts 0.00% 64 Missing ⚠️
...b/ui/Bridge/payment-selection/PaymentSelection.tsx 0.00% 8 Missing ⚠️
...t/web/ui/Bridge/payment-details/PaymentDetails.tsx 0.00% 2 Missing ⚠️
...web/src/react/web/ui/Bridge/BridgeOrchestrator.tsx 0.00% 1 Missing ⚠️
...ges/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx 0.00% 1 Missing ⚠️
...s/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx 0.00% 1 Missing ⚠️
...eb/ui/ConnectWallet/screens/Buy/swap/FiatValue.tsx 0.00% 1 Missing ⚠️

❌ Your patch status has failed because the patch coverage (0.00%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8048      +/-   ##
==========================================
- Coverage   56.54%   56.53%   -0.02%     
==========================================
  Files         904      904              
  Lines       58842    58857      +15     
  Branches     4167     4170       +3     
==========================================
+ Hits        33275    33276       +1     
- Misses      25461    25476      +15     
+ Partials      106      105       -1     
Flag Coverage Δ
packages 56.53% <0.00%> (-0.02%) ⬇️
Files with missing lines Coverage Δ
...thirdweb/src/react/core/machines/paymentMachine.ts 72.94% <ø> (ø)
...es/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx 3.90% <ø> (ø)
...web/src/react/web/ui/Bridge/BridgeOrchestrator.tsx 6.99% <0.00%> (+0.02%) ⬆️
...ges/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx 9.03% <0.00%> (ø)
...s/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx 6.89% <0.00%> (-0.05%) ⬇️
...eb/ui/ConnectWallet/screens/Buy/swap/FiatValue.tsx 21.95% <0.00%> (-0.55%) ⬇️
...t/web/ui/Bridge/payment-details/PaymentDetails.tsx 4.48% <0.00%> (-0.02%) ⬇️
...b/ui/Bridge/payment-selection/PaymentSelection.tsx 7.42% <0.00%> (-0.12%) ⬇️
...s/thirdweb/src/react/core/hooks/useStepExecutor.ts 1.86% <0.00%> (-0.05%) ⬇️

... and 4 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: 6

Caution

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

⚠️ Outside diff range comments (3)
packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx (1)

108-124: Add TSDoc and explicit return type for public export.

Repo guidelines require comprehensive TSDoc (with an @example and custom tag) and explicit return types.

+/**
+ * Payment method selection for Bridge flows (crypto or fiat).
+ * Resolves payer wallet and recipient, and routes to the chosen on‑ramp/provider.
+ * @beta
+ * @example
+ * <PaymentSelection
+ *   destinationToken={token}
+ *   destinationAmount="100"
+ *   client={client}
+ *   receiverAddress="0xabc..."
+ *   country="US"
+ *   connectLocale={{ locale: "en" }}
+ *   onPaymentMethodSelected={(m) => console.log(m)}
+ *   onError={(e) => console.error(e)}
+ * />
+ */
-export function PaymentSelection({
+export function PaymentSelection({
   destinationToken,
   client,
   destinationAmount,
   receiverAddress,
   onPaymentMethodSelected,
   onError,
   onBack,
   connectOptions,
   connectLocale,
   includeDestinationToken,
   paymentMethods = ["crypto", "card"],
   supportedTokens,
   feePayer,
   currency,
   country,
-}: PaymentSelectionProps) {
+}: PaymentSelectionProps): JSX.Element {
.changeset/fuzzy-suits-wear.md (1)

6-6: Remove stray character that will break the changeset parser.

There is a dangling 6 at EOF.

Apply:

-6
packages/thirdweb/src/react/core/machines/paymentMachine.ts (1)

22-35: Fix unguarded payerWallet accesses in Bridge/QuoteLoader

  • Found unguarded uses that can throw when payerWallet is undefined:
    • packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx — paymentMethod.payerWallet.getAccount()?.address (lines ~224 and ~243).
  • Action: guard these accesses (check paymentMethod.type === "wallet" before use or use optional chaining: paymentMethod.payerWallet?.getAccount()?.address).
  • Note: other hits (PaymentOverview, PaymentDetails, TokenSelection) are already type‑narrowed or use optional chaining.
🧹 Nitpick comments (4)
packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx (3)

308-317: Provider screen receives empty toAddress when only wallet is present.

Mirror the recipient fallback so the provider UI is prefilled correctly.

-            toAddress={receiverAddress || ""}
+            toAddress={receiverAddress ?? payerWallet?.getAccount()?.address ?? ""}

158-163: Boolean default may exclude destination token unintentionally.

A || (B !== C) evaluates to false when both addresses are undefined, potentially excluding the destination token when intent is “include unless same address is known.” Consider a nullish default.

-    includeDestinationToken:
-      includeDestinationToken ||
-      receiverAddress?.toLowerCase() !==
-        payerWallet?.getAccount()?.address?.toLowerCase(),
+    includeDestinationToken:
+      includeDestinationToken ??
+      (Boolean(receiverAddress) &&
+        receiverAddress!.toLowerCase() !==
+          payerWallet?.getAccount()?.address?.toLowerCase()),

132-143: Side‑effect via useQuery has a static key.

For analytics side‑effects, prefer a stable useEffect or at least key by inputs to avoid accidental deduping/caching conflicts across pages.

-  useQuery({
+  useQuery({
     queryFn: () => {
       trackPayEvent({
         client,
         event: "payment_selection",
         toChainId: destinationToken.chainId,
         toToken: destinationToken.address,
       });
       return true;
     },
-    queryKey: ["payment_selection"],
+    queryKey: ["payment_selection", destinationToken.chainId, destinationToken.address],
   });
packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.tsx (1)

39-40: Key the query by the effective currency to avoid duplicate caches.

queryFn defaults to "USD" but queryKey uses props.currency (possibly undefined), causing two cache entries for USD. Normalize in the key.

Apply:

-      props.currency,
+      props.currency ?? "USD",
📜 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 9f9fadf and 066082b.

📒 Files selected for processing (9)
  • .changeset/fuzzy-suits-wear.md (1 hunks)
  • packages/thirdweb/src/react/core/hooks/useStepExecutor.ts (2 hunks)
  • packages/thirdweb/src/react/core/machines/paymentMachine.ts (1 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (1 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx (1 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx (1 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx (2 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx (1 hunks)
  • packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

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

Files:

  • packages/thirdweb/src/react/core/machines/paymentMachine.ts
  • packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx
  • packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx
  • packages/thirdweb/src/react/core/hooks/useStepExecutor.ts
**/*.{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/core/machines/paymentMachine.ts
  • packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx
  • packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx
  • packages/thirdweb/src/react/core/hooks/useStepExecutor.ts
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/core/machines/paymentMachine.ts
  • packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx
  • packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx
  • packages/thirdweb/src/react/core/hooks/useStepExecutor.ts
.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/fuzzy-suits-wear.md
🧠 Learnings (5)
📚 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 packages/thirdweb/src/wallets/** : Support for in-app wallets (social/email login)

Applied to files:

  • .changeset/fuzzy-suits-wear.md
  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Wrap client-side data fetching calls in React Query (`tanstack/react-query`)

Applied to files:

  • packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx
📚 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}/**/*.{ts,tsx} : 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

Applied to files:

  • packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to packages/thirdweb/src/wallets/** : Unified `Wallet` and `Account` interfaces in wallet architecture

Applied to files:

  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to packages/thirdweb/src/wallets/** : Smart wallets with account abstraction

Applied to files:

  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx
🧬 Code graph analysis (2)
packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx (1)
packages/thirdweb/src/react/core/machines/paymentMachine.ts (1)
  • PaymentMethod (22-35)
packages/thirdweb/src/react/core/hooks/useStepExecutor.ts (2)
packages/thirdweb/src/bridge/types/Errors.ts (1)
  • ApiError (11-36)
packages/thirdweb/src/chains/utils.ts (1)
  • getCachedChain (79-89)
⏰ 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: E2E Tests (pnpm, webpack)
  • GitHub Check: Size
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: Unit Tests
  • GitHub Check: Build Packages
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (8)
packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx (1)

136-136: Fix for queryFn return type.

Explicitly returning true addresses the TypeScript requirement that useQuery's queryFn must return a value. This ensures the query resolves properly while maintaining the side effect of tracking the pay event.

packages/thirdweb/src/react/core/hooks/useStepExecutor.ts (3)

41-41: Correctly makes wallet optional with proper validation.

Making the wallet parameter optional is essential for supporting fiat-only flows. The implementation correctly validates wallet presence when transactions need to be executed, ensuring type safety while enabling no-wallet scenarios.


420-436: Excellent guard logic for wallet-dependent operations.

The implementation properly separates concerns:

  • Only validates wallet presence when there are actual transactions to execute
  • Provides clear, actionable error messages for missing wallet or account
  • Maintains existing wallet connection validation logic

This approach allows fiat-only flows (onramp) to proceed without a wallet while ensuring transaction execution paths have proper validation.


438-511: Well-structured transaction execution with proper validation.

The transaction execution logic maintains robust error handling and validation:

  • Clear error for invalid step indices
  • Chain switching when needed
  • Smart batching for compatible transactions
  • Proper completion tracking

The nested transaction logic is well-organized and maintains the existing behavior while accommodating the optional wallet parameter.

packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx (1)

33-33: Proper alignment with useStepExecutor changes.

Making the wallet prop optional correctly aligns with the useStepExecutor hook's updated interface. The component still passes the wallet value through, maintaining compatibility while enabling no-wallet execution flows.

packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx (2)

104-104: Correct queryFn return value fix.

Adding return true ensures the useQuery call has a proper return value, maintaining consistency with similar patterns throughout the codebase (like in QuoteLoader.tsx).


243-243: Safe optional chaining for wallet access.

Using optional chaining (paymentMethod.payerWallet?.getAccount()?.address) properly handles cases where payerWallet might be undefined in fiat payment flows. This prevents runtime errors while maintaining the existing fallback logic with preparedQuote.intent.sender.

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

370-372: Simplified execution gating enables no-wallet flows.

Removing the payerWallet requirement from the execution condition is the key change that allows fiat payments to proceed to the StepRunner without a connected wallet. The StepRunner still receives the payerWallet (which may be undefined) and the useStepExecutor hook properly handles the validation when transactions actually need to be executed.

This change maintains safety by delegating wallet validation to the appropriate execution layer while removing unnecessary blocking conditions.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

197-201: Document precedence and stability of receiverAddress

Clarify that receiverAddress takes precedence over the connected wallet address (and that it can be used when no wallet is connected). Consider tagging this prop with @beta (repo guideline) and adding a short example in the BuyWidget docs to avoid ambiguity.

packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx (1)

33-33: Make wallet optional — add UX hint when missing

Optionalizing wallet matches the executor change. Minor UX: when wallet is absent and txs exist, surface a clearer CTA than “Retry” (e.g., show “Back” to method selection) on INVALID_INPUT to guide users.

packages/thirdweb/src/react/core/hooks/useStepExecutor.ts (2)

41-42: Public API: wallet is now optional — update JSDoc

Good change. Please update StepExecutorOptions docs to state that wallet is required only when transactions exist; onramp‑only runs without a wallet.


420-511: Guard tx execution on wallet presence — treat user-initiated aborts as non-errors

Verified ErrorCode includes "INVALID_INPUT" (packages/thirdweb/src/bridge/types/Errors.ts).

@@
-    } catch (err) {
-      console.error("Error executing payment", err);
-      if (err instanceof ApiError) {
-        setError(err);
-      } else {
-        setError(
-          new ApiError({
-            code: "UNKNOWN_ERROR",
-            message: (err as Error)?.message || "An unknown error occurred",
-            statusCode: 500,
-          }),
-        );
-      }
+    } catch (err) {
+      // Treat user-initiated aborts as non-errors
+      const msg = (err as Error)?.message || "";
+      const aborted =
+        abortControllerRef.current?.signal.aborted || msg === "Polling aborted";
+      if (!aborted) {
+        console.error("Error executing payment", err);
+        if (err instanceof ApiError) {
+          setError(err);
+        } else {
+          setError(
+            new ApiError({
+              code: "UNKNOWN_ERROR",
+              message: msg || "An unknown error occurred",
+              statusCode: 500,
+            }),
+          );
+        }
+      }
packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (1)

370-385: Bubble StepRunner executor errors to the payment machine (add onError and forward errors)

StepRunner consumes useStepExecutor errors but does not notify BridgeOrchestrator, so the machine never receives ERROR_OCCURRED and the ErrorBanner won't appear.

  • Add onError?: (error: Error) => void to packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx and invoke it when useStepExecutor reports an error (e.g., "No wallet provided to execute transactions").
  • In packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx pass handleError to StepRunner (onError={handleError}) so the machine can transition to the error state.
📜 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 066082b and 9646cfd.

📒 Files selected for processing (10)
  • .changeset/fuzzy-suits-wear.md (1 hunks)
  • packages/thirdweb/src/react/core/hooks/useStepExecutor.ts (2 hunks)
  • packages/thirdweb/src/react/core/machines/paymentMachine.ts (1 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (1 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (2 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx (1 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx (1 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx (2 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx (1 hunks)
  • packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • .changeset/fuzzy-suits-wear.md
  • packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.tsx
  • packages/thirdweb/src/react/core/machines/paymentMachine.ts
  • packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

**/*.{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/BuyWidget.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx
  • packages/thirdweb/src/react/core/hooks/useStepExecutor.ts
**/*.{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/BuyWidget.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx
  • packages/thirdweb/src/react/core/hooks/useStepExecutor.ts
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
  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx
  • packages/thirdweb/src/react/core/hooks/useStepExecutor.ts
🧠 Learnings (3)
📚 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 packages/thirdweb/src/wallets/** : Unified `Wallet` and `Account` interfaces in wallet architecture

Applied to files:

  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to packages/thirdweb/src/wallets/** : Smart wallets with account abstraction

Applied to files:

  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to packages/thirdweb/src/wallets/** : Support for in-app wallets (social/email login)

Applied to files:

  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx
🧬 Code graph analysis (2)
packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (1)
packages/thirdweb/src/exports/utils.ts (1)
  • Address (144-144)
packages/thirdweb/src/react/core/hooks/useStepExecutor.ts (2)
packages/thirdweb/src/bridge/types/Errors.ts (1)
  • ApiError (11-36)
packages/thirdweb/src/chains/utils.ts (1)
  • getCachedChain (79-89)
⏰ 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, vite)
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: Unit Tests
  • GitHub Check: Lint Packages
  • GitHub Check: Size
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: Build Packages
  • GitHub Check: Analyze (javascript)

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

♻️ Duplicate comments (3)
packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx (3)

207-207: Default currency: use nullish coalescing.

Prevents overriding a deliberately empty string and aligns with common style.

-      currency: currency || "USD",
+      currency: currency ?? "USD",

209-209: Ensure all downstream usages treat payerWallet as optional.

Please re-scan for unsafe derefs or non‑null assertions on payerWallet.

#!/bin/bash
# Find non-null assertions and unguarded dereferences of payerWallet
rg -nP -C2 --type=ts '\bpayerWallet\s*!'
rg -nP -C2 --type=ts '(?<!\?)\bpayerWallet\.(getAccount|[A-Za-z_]\w*)\('

312-314: UI alignment fix for toAddress — LGTM.

Now consistent with the guard used on selection; avoids empty address when a wallet is connected.

🧹 Nitpick comments (1)
packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx (1)

199-204: Guard looks good; prefer nullish coalescing for address resolution.

Use ?? to avoid defaulting when receiverAddress is an empty string and for consistency with TS idioms.

-    const recipientAddress =
-      receiverAddress || payerWallet?.getAccount()?.address;
+    const recipientAddress =
+      receiverAddress ?? payerWallet?.getAccount()?.address;
📜 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 9646cfd and a38e299.

📒 Files selected for processing (10)
  • .changeset/fuzzy-suits-wear.md (1 hunks)
  • packages/thirdweb/src/react/core/hooks/useStepExecutor.ts (2 hunks)
  • packages/thirdweb/src/react/core/machines/paymentMachine.ts (1 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (1 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (2 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx (1 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx (1 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx (2 hunks)
  • packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx (2 hunks)
  • packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • packages/thirdweb/src/react/core/machines/paymentMachine.ts
  • packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx
  • .changeset/fuzzy-suits-wear.md
  • packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
  • packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx
  • packages/thirdweb/src/react/core/hooks/useStepExecutor.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

**/*.{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/payment-selection/PaymentSelection.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/payment-selection/PaymentSelection.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/payment-selection/PaymentSelection.tsx
🧠 Learnings (1)
📚 Learning: 2025-06-26T19:46:04.024Z
Learnt from: gregfromstl
PR: thirdweb-dev/js#7450
File: packages/thirdweb/src/bridge/Webhook.ts:57-81
Timestamp: 2025-06-26T19:46:04.024Z
Learning: In the onramp webhook schema (`packages/thirdweb/src/bridge/Webhook.ts`), the `currencyAmount` field is intentionally typed as `z.number()` while other amount fields use `z.string()` because `currencyAmount` represents fiat currency amounts in decimals (like $10.50), whereas other amount fields represent token amounts in wei (very large integers that benefit from bigint representation). The different naming convention (`currencyAmount` vs `amount`) reflects this intentional distinction.

Applied to files:

  • packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx
🧬 Code graph analysis (1)
packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx (1)
packages/thirdweb/src/react/core/machines/paymentMachine.ts (1)
  • PaymentMethod (22-35)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: Size
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: Unit Tests
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)

@joaquim-verges joaquim-verges merged commit 97e5080 into main Sep 14, 2025
24 of 25 checks passed
@joaquim-verges joaquim-verges deleted the Fix_fiat_payments_with_no_wallet_connected branch September 14, 2025 10:54
@joaquim-verges joaquim-verges mentioned this pull request Sep 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

packages SDK Involves changes to the thirdweb SDK

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants