Skip to content

Conversation

MananTank
Copy link
Member

@MananTank MananTank commented Aug 29, 2025


PR-Codex overview

This PR focuses on integrating a Pay Modal into the useSendAndConfirmTransaction hook, similar to the existing useSendTransaction hook. It enhances user experience by allowing users to buy required funds if their wallet lacks sufficient balance.

Detailed summary

  • Renamed useSendAndConfirmTransaction to useSendAndConfirmTransactionCore.
  • Added Pay Modal configuration to useSendAndConfirmTransaction.
  • Updated CreateDirectListingButton, ClaimButton, and BuyDirectListingButton to use the new Pay Modal feature.
  • Documented Pay Modal usage in the hook's comments.
  • Exported the updated useSendAndConfirmTransaction from the appropriate module.

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

Summary by CodeRabbit

  • New Features

    • Pay Modal integrated into send-and-confirm transaction flows, matching send-only behavior.
    • Prebuilt buttons (Buy Direct Listing, Claim, Create Direct Listing) now pass Pay Modal config and auto-fill metadata with sensible fallbacks for smoother top-ups.
    • Pay Modal options are configurable and compatible with gasless workflows.
  • Documentation

    • Added examples and guidance for configuring the Pay Modal (theme, disabling, and usage).

Copy link

linear bot commented Aug 29, 2025

Copy link

changeset-bot bot commented Aug 29, 2025

🦋 Changeset detected

Latest commit: 597431e

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

vercel bot commented Aug 29, 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 Aug 29, 2025 5:50pm
nebula Ready Ready Preview Comment Aug 29, 2025 5:50pm
thirdweb_playground Ready Ready Preview Comment Aug 29, 2025 5:50pm
thirdweb-www Building Building Aug 29, 2025 5:50pm
wallet-ui Ready Ready Preview Comment Aug 29, 2025 5:50pm

Copy link
Contributor

coderabbitai bot commented Aug 29, 2025

Walkthrough

Adds a web-specific useSendAndConfirmTransaction hook that composes useSendTransaction with on-chain confirmation and Pay Modal integration, renames the core hook export to useSendAndConfirmTransactionCore, updates react exports, augments JSDoc, and wires pay-modal metadata through several prebuilt UI buttons.

Changes

Cohort / File(s) Summary
Changeset
\.changeset/pretty-geese-win.md
Adds a patch changeset noting Pay Modal integration for useSendAndConfirmTransaction.
Exports: React (web/native)
packages/thirdweb/src/exports/react.ts
packages/thirdweb/src/exports/react.native.ts
Web: re-exports useSendAndConfirmTransaction from ../react/web/hooks/.... Native: re-exports internal useSendAndConfirmTransactionCore as useSendAndConfirmTransaction.
Core hook rename
packages/thirdweb/src/react/core/hooks/transaction/useSendAndConfirmTransaction.ts
Renames exported function to useSendAndConfirmTransactionCore, tightens mutation types, and adds a runtime guard for missing active account.
New web hook
packages/thirdweb/src/react/web/hooks/transaction/useSendAndConfirmTransaction.tsx
Adds web useSendAndConfirmTransaction that calls useSendTransaction to submit a tx and waitForReceipt to return a confirmed TransactionReceipt; accepts optional config with payModal and gasless support.
Docs addition
packages/thirdweb/src/react/web/hooks/transaction/useSendTransaction.tsx
JSDoc updated to document payModal config and disabling; no runtime changes.
UI: Pay Modal metadata wiring
packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.tsx
packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/ClaimButton/index.tsx
packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/CreateDirectListingButton/index.tsx
Update imports to web hook; call useSendAndConfirmTransaction({ payModal: ... }) and merge provided payModal with metadata fallback from default or useReadContract (payMetadata); ensure mutation and UI receive consistent payModal metadata.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor App as App Component
  participant Hook as useSendAndConfirmTransaction (web)
  participant Send as useSendTransaction
  participant Pay as Pay Modal
  participant RPC as Provider/Chain
  participant Conf as waitForReceipt

  App->>Hook: mutateAsync(transaction)
  activate Hook
  Hook->>Send: mutateAsync(transaction, { payModal: ... })
  alt Insufficient funds
    Send->>Pay: Open Pay Modal (metadata)
    Note right of Pay: User tops up or cancels
    Pay-->>Send: Proceed or error
  end
  Send->>RPC: submit tx
  Send-->>Hook: tx hash
  Hook->>Conf: waitForReceipt(tx hash)
  Conf-->>Hook: confirmed receipt
  Hook-->>App: TransactionReceipt
  deactivate Hook

  alt Error path
    Send-->>App: Error
    Conf-->>App: Error
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Assessment against linked issues

Objective Addressed Explanation
Integrate Pay Modal into useSendAndConfirmTransaction so it mirrors useSendTransaction (MNY-131)
Ensure buy UI (Pay Modal) appears when user lacks funds (MNY-131)
Parity features: showing modal and confirmation flow via single hook (MNY-131)
Support chain switching behavior in useSendAndConfirmTransaction similar to useSendTransaction (MNY-131) No explicit chain-switch handling added in the new web hook; relies on underlying useSendTransaction behavior, not verified here.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

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

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

Support

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

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Status, Documentation and Community

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

@github-actions github-actions bot added packages SDK Involves changes to the thirdweb SDK labels Aug 29, 2025
@MananTank MananTank changed the title [MNY-131] Add Pay Modal integration in hook [MNY-131] Add Pay Modal integration in useSendAndConfirmTransaction hook Aug 29, 2025
Copy link
Member Author

MananTank commented Aug 29, 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.

@MananTank MananTank marked this pull request as ready for review August 29, 2025 13:27
@MananTank MananTank requested review from a team as code owners August 29, 2025 13:27
Copy link
Contributor

github-actions bot commented Aug 29, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
thirdweb (esm) 64.01 KB (0%) 1.3 s (0%) 408 ms (+97.02% 🔺) 1.7 s
thirdweb (cjs) 357.32 KB (0%) 7.2 s (0%) 1.6 s (+5.11% 🔺) 8.8 s
thirdweb (minimal + tree-shaking) 5.73 KB (0%) 115 ms (0%) 119 ms (+963.72% 🔺) 233 ms
thirdweb/chains (tree-shaking) 526 B (0%) 11 ms (0%) 52 ms (+1302.28% 🔺) 62 ms
thirdweb/react (minimal + tree-shaking) 19.15 KB (0%) 383 ms (0%) 70 ms (+127.14% 🔺) 453 ms

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

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

⚠️ Outside diff range comments (5)
packages/thirdweb/src/tokens/create-token.ts (1)

19-33: Make this sync, fix event name in error, and add TSDoc with precise return type

  • Function is async without await; return a plain value to avoid unnecessary Promise wrapping.
  • Error mentions “AssetCreated” but the decoded event is Created; message should match.
  • Public API needs TSDoc (per repo guidelines). Also narrow return type to Address instead of generic hex.

Diff within this block:

-export async function getTokenAddressFromReceipt(receipt: TransactionReceipt) {
+/**
+ * Extract the created ERC20 token address from a token-creation transaction receipt.
+ *
+ * @param receipt The transaction receipt returned from sending the prepared create-token transaction.
+ * @returns The created token contract address.
+ * @example
+ * const tx = await sendAndConfirmTx(prepareCreateToken(opts));
+ * const tokenAddress = getTokenAddressFromReceipt(tx);
+ */
+export function getTokenAddressFromReceipt(receipt: TransactionReceipt) {
   const assetEvent = createdEvent();
   const decodedEvent = parseEventLogs({
     events: [assetEvent],
     logs: receipt.logs,
   });
 
   if (decodedEvent.length === 0 || !decodedEvent[0]) {
     throw new Error(
-      `No AssetCreated event found in transaction: ${receipt.transactionHash}`,
+      `No Created event found in transaction: ${receipt.transactionHash}`,
     );
   }
 
-  return decodedEvent[0]?.args.asset;
+  return decodedEvent[0].args.asset;
 }

Additionally, import and use the precise type:

// add to imports
import type { Address } from "viem";

And, if desired, annotate the return type explicitly:

export function getTokenAddressFromReceipt(receipt: TransactionReceipt): Address { ... }
packages/thirdweb/src/exports/react.ts (1)

70-76: Also export the config type for the new hook from the public surface.

Consumers will need the config type when using the hook. Please re-export it to keep the API consistent with other transaction hooks.

Apply this diff:

 export type {
   SendTransactionConfig,
   SendTransactionPayModalConfig,
 } from "../react/core/hooks/transaction/useSendTransaction.js";
+export type {
+  SendAndConfirmTransactionConfig,
+} from "../react/web/hooks/transaction/useSendAndConfirmTransaction.js";
packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/ClaimButton/index.tsx (1)

139-143: TransactionButton always receives an object, so payModal: false is ignored.

This unintentionally re-enables the modal. Preserve false.

Apply this diff:

-      payModal={{
-        metadata: defaultPayModalMetadata || payMetadata,
-        ...payModal,
-      }}
+      payModal={
+        payModal === false
+          ? false
+          : {
+              metadata: defaultPayModalMetadata || payMetadata,
+              ...payModal,
+            }
+      }
packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.tsx (2)

181-184: TransactionButton always receives an object, so payModal: false is ignored.

Preserve false when the user disables the modal.

Apply this diff:

-      payModal={{
-        metadata: defaultPayModalMetadata || payMetadata,
-        ...payModal,
-      }}
+      payModal={
+        payModal === false
+          ? false
+          : {
+              metadata: defaultPayModalMetadata || payMetadata,
+              ...payModal,
+            }
+      }

137-158: Quantity logic bug for ERC1155: overwrites user input and allows 0n.

  • _quantity is set from quantity and then overwritten with listing.quantity.
  • 0n passes validation though the error says “at least 1n”.

Fix validation and only default when quantity is not provided.

Apply this diff:

-    let _quantity = 1n;
-    // For ERC721 the quantity should always be 1n. We throw an error if user passes a different props
-    if (listing.asset.type === "ERC721") {
-      if (typeof quantity === "bigint" && (quantity !== 1n || quantity < 0n)) {
-        throw new Error(
-          "Invalid quantity. This is an ERC721 listing & quantity is always `1n`",
-        );
-      }
-    } else if (listing.asset.type === "ERC1155") {
-      if (typeof quantity === "bigint") {
-        if (quantity > listing.quantity) {
-          throw new Error(
-            `quantity exceeds available amount. Available: ${listing.quantity.toString()}`,
-          );
-        }
-        if (quantity < 0n) {
-          throw new Error("Invalid quantity. Should be at least 1n");
-        }
-        _quantity = quantity;
-      }
-      _quantity = listing.quantity;
-    }
+    let _quantity: bigint;
+    // ERC721 must always be 1
+    if (listing.asset.type === "ERC721") {
+      if (typeof quantity === "bigint" && quantity !== 1n) {
+        throw new Error(
+          "Invalid quantity. This is an ERC721 listing & quantity must be `1n`",
+        );
+      }
+      _quantity = 1n;
+    } else if (listing.asset.type === "ERC1155") {
+      if (typeof quantity === "bigint") {
+        if (quantity > listing.quantity) {
+          throw new Error(
+            `quantity exceeds available amount. Available: ${listing.quantity.toString()}`,
+          );
+        }
+        if (quantity <= 0n) {
+          throw new Error("Invalid quantity. Should be at least 1n");
+        }
+        _quantity = quantity;
+      } else {
+        _quantity = listing.quantity;
+      }
+    }
🧹 Nitpick comments (9)
packages/thirdweb/src/react/web/hooks/transaction/useSendTransaction.tsx (1)

96-121: Doc examples: fix destructuring and call out gasless disables Pay Modal

  • The snippets assign the hook return to sendTx, which reads like a function; previous examples use { mutate: sendTx }. Align for clarity.
  • Mention that gasless: true disables the Pay Modal even if configured.

Apply:

@@
- * const sendTx = useSendTransaction({
+ * const { mutate: sendTx } = useSendTransaction({
  *   payModal: {
  *     theme: "light",
  *   },
  * });
@@
- * const sendTx = useSendTransaction({
+ * const { mutate: sendTx } = useSendTransaction({
  *   payModal: false,
  * });
+ *
+ * // Note:
+ * // If you enable `gasless`, the Pay Modal is automatically disabled.
packages/thirdweb/src/react/core/hooks/transaction/useSendAndConfirmTransaction.ts (1)

8-10: JSDoc header references the wrong hook

Text says “Configuration for the useSendTransaction hook.” This file is for “useSendAndConfirmTransaction”. Fix to avoid confusing generated docs.

Suggested:

/**
 * Configuration for the `useSendAndConfirmTransaction` hook.
 */
packages/thirdweb/src/tokens/create-token.ts (1)

35-69: Add/ensure TSDoc for prepareCreateToken and tighten types

This is a public surface. Add TSDoc with an @example that compiles and clarifies that sending is external (hook or action). Consider returning a typed PreparedTransaction if available in your types to strengthen contracts.

Example TSDoc:

/**
 * Prepare the ERC20 create-token transaction without sending it.
 *
 * Use the returned transaction with `useSendAndConfirmTransaction` (web/RN) or the
 * low-level `sendAndConfirmTransaction` action.
 *
 * @param options Parameters for token creation including init params, creator, and pool config.
 * @returns A prepared transaction ready to be sent.
 * @example
 * const tx = await prepareCreateToken(opts);
 * const { mutateAsync: sendAndConfirmTx } = useSendAndConfirmTransaction();
 * const receipt = await sendAndConfirmTx(tx);
 * const tokenAddress = getTokenAddressFromReceipt(receipt);
 */
packages/thirdweb/src/react/web/hooks/transaction/useSendAndConfirmTransaction.tsx (1)

25-36: Minor doc fixes.

  • “users's” → “user's”

Apply this diff:

- * A hook to send a transaction and confirm the transaction with users's connected wallet
+ * A hook to send a transaction and confirm the transaction with the user's connected wallet
packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/CreateDirectListingButton/index.tsx (5)

91-98: Use nullish coalescing for metadata to avoid overriding valid falsy values.

|| will replace valid falsy values (e.g., empty string). Prefer ??.

-  const { mutateAsync } = useSendAndConfirmTransaction({
-    payModal: payModal
-      ? {
-          ...payModal,
-          metadata: payModal.metadata || payMetadata,
-        }
-      : undefined,
-  });
+  const { mutateAsync } = useSendAndConfirmTransaction({
+    payModal: payModal
+      ? {
+          ...payModal,
+          metadata: payModal.metadata ?? payMetadata,
+        }
+      : undefined,
+  });

178-183: Ensure UI and mutation resolve metadata identically; use ?? here too.

Keeps parity with the hook config and avoids clobbering valid falsy metadata.

-      payModal={{
-        metadata: defaultPayModalMetadata || payMetadata,
-        ...payModal,
-      }}
+      payModal={{
+        metadata: defaultPayModalMetadata ?? payMetadata,
+        ...payModal,
+      }}

Optional: derive a single resolvedPayModal (via useMemo) and pass it to both the hook and TransactionButton to eliminate drift.


156-160: Address comparison: prefer a canonical helper over toLowerCase() string ops.

Use an address equality helper (e.g., isAddressEqual(a, b)) if available to avoid locale/case pitfalls.

-      if (
-        !isApproved &&
-        tokenApproved.toLowerCase() !==
-          marketplaceContract.address.toLowerCase()
-      ) {
+      if (!isApproved && !isAddressEqual(tokenApproved, marketplaceContract.address)) {

If no helper exists, consider normalizing via checksum utilities already used in the codebase.


84-90: Query gating: prefer nullish check for readability and intent.

enabled: defaultPayModalMetadata == null communicates “fetch only when missing,” and avoids accidental disablement if an empty value is ever passed.

-      enabled: !defaultPayModalMetadata,
+      enabled: defaultPayModalMetadata == null,

183-183: Minor: pass the memoized function reference directly.

Avoids recreating a lambda on each render.

-      transaction={() => prepareTransaction()}
+      transaction={prepareTransaction}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

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

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 76694f0 and 24db91b.

📒 Files selected for processing (11)
  • .changeset/pretty-geese-win.md (1 hunks)
  • packages/thirdweb/src/exports/react.native.ts (1 hunks)
  • packages/thirdweb/src/exports/react.ts (1 hunks)
  • packages/thirdweb/src/exports/tokens.ts (1 hunks)
  • packages/thirdweb/src/react/core/hooks/transaction/useSendAndConfirmTransaction.ts (1 hunks)
  • packages/thirdweb/src/react/web/hooks/transaction/useSendAndConfirmTransaction.tsx (1 hunks)
  • packages/thirdweb/src/react/web/hooks/transaction/useSendTransaction.tsx (1 hunks)
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.tsx (2 hunks)
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/ClaimButton/index.tsx (2 hunks)
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/CreateDirectListingButton/index.tsx (2 hunks)
  • packages/thirdweb/src/tokens/create-token.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • packages/thirdweb/src/react/web/hooks/transaction/useSendTransaction.tsx
  • packages/thirdweb/src/react/core/hooks/transaction/useSendAndConfirmTransaction.ts
  • packages/thirdweb/src/exports/react.ts
  • packages/thirdweb/src/exports/react.native.ts
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/ClaimButton/index.tsx
  • packages/thirdweb/src/react/web/hooks/transaction/useSendAndConfirmTransaction.tsx
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/CreateDirectListingButton/index.tsx
  • packages/thirdweb/src/exports/tokens.ts
  • packages/thirdweb/src/tokens/create-token.ts
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.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/hooks/transaction/useSendTransaction.tsx
  • packages/thirdweb/src/react/core/hooks/transaction/useSendAndConfirmTransaction.ts
  • packages/thirdweb/src/exports/react.ts
  • packages/thirdweb/src/exports/react.native.ts
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/ClaimButton/index.tsx
  • packages/thirdweb/src/react/web/hooks/transaction/useSendAndConfirmTransaction.tsx
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/CreateDirectListingButton/index.tsx
  • packages/thirdweb/src/exports/tokens.ts
  • packages/thirdweb/src/tokens/create-token.ts
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.tsx
packages/thirdweb/src/exports/**

📄 CodeRabbit inference engine (CLAUDE.md)

packages/thirdweb/src/exports/**: Export everything via exports/ directory, grouped by feature in the SDK public API
Every public symbol must have comprehensive TSDoc with at least one @example block that compiles and custom annotation tags (@beta, @internal, @experimental)

Files:

  • packages/thirdweb/src/exports/react.ts
  • packages/thirdweb/src/exports/react.native.ts
  • packages/thirdweb/src/exports/tokens.ts
🧠 Learnings (4)
📚 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/exports/react.native.ts : React Native specific exports are in `src/exports/react.native.ts`

Applied to files:

  • packages/thirdweb/src/exports/react.ts
  • packages/thirdweb/src/exports/react.native.ts
📚 Learning: 2025-06-17T18:30:52.976Z
Learnt from: MananTank
PR: thirdweb-dev/js#7356
File: apps/nebula/src/app/not-found.tsx:1-1
Timestamp: 2025-06-17T18:30:52.976Z
Learning: In the thirdweb/js project, the React namespace is available for type annotations (like React.FC) without needing to explicitly import React. This is project-specific configuration that differs from typical TypeScript/React setups.

Applied to files:

  • packages/thirdweb/src/exports/react.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/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).

Applied to files:

  • packages/thirdweb/src/exports/react.ts
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/ClaimButton/index.tsx
📚 Learning: 2025-08-28T12:24:37.171Z
Learnt from: MananTank
PR: thirdweb-dev/js#7933
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/distribution/token-sale.tsx:0-0
Timestamp: 2025-08-28T12:24:37.171Z
Learning: In the token creation flow, the tokenAddress field in erc20Asset_poolMode is always initialized with nativeTokenAddress and is never undefined, so conditional checks for undefined tokenAddress are not needed.

Applied to files:

  • packages/thirdweb/src/tokens/create-token.ts
🧬 Code graph analysis (6)
packages/thirdweb/src/react/core/hooks/transaction/useSendAndConfirmTransaction.ts (1)
packages/thirdweb/src/exports/react.native.ts (1)
  • useSendAndConfirmTransactionCore (62-62)
packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/ClaimButton/index.tsx (1)
packages/thirdweb/src/react/web/hooks/transaction/useSendAndConfirmTransaction.tsx (1)
  • useSendAndConfirmTransaction (89-104)
packages/thirdweb/src/react/web/hooks/transaction/useSendAndConfirmTransaction.tsx (2)
packages/thirdweb/src/exports/react.ts (2)
  • useSendAndConfirmTransaction (127-127)
  • useSendTransaction (128-128)
packages/thirdweb/src/react/web/hooks/transaction/useSendTransaction.tsx (1)
  • useSendTransaction (124-177)
packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/CreateDirectListingButton/index.tsx (2)
packages/thirdweb/src/exports/react.ts (1)
  • useSendAndConfirmTransaction (127-127)
packages/thirdweb/src/react/web/hooks/transaction/useSendAndConfirmTransaction.tsx (1)
  • useSendAndConfirmTransaction (89-104)
packages/thirdweb/src/tokens/create-token.ts (1)
packages/thirdweb/src/exports/tokens.ts (1)
  • getTokenAddressFromReceipt (9-9)
packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.tsx (2)
packages/thirdweb/src/exports/react.ts (1)
  • useSendAndConfirmTransaction (127-127)
packages/thirdweb/src/react/web/hooks/transaction/useSendAndConfirmTransaction.tsx (1)
  • useSendAndConfirmTransaction (89-104)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Unit Tests
  • GitHub Check: Size
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (7)
packages/thirdweb/src/react/core/hooks/transaction/useSendAndConfirmTransaction.ts (1)

57-78: Rename to useSendAndConfirmTransactionCore looks good

The symbol rename preserves the public API via re-exports; hook logic unchanged. No functional concerns here.

packages/thirdweb/src/tokens/create-token.ts (1)

45-46: generateSalt enforces 32-byte salts; 31 bytes of entropy is correct
The helper always outputs a 32-byte value (1 byte flags + 31 bytes data), padding or hashing inputs to 62 hex chars and prepending the flag byte. Passing randomBytes(31) meets the contract’s expectations—no change required.

packages/thirdweb/src/exports/react.ts (1)

127-127: Switching the public export to the web hook looks correct.

This aligns the web API with the new Pay Modal flow. Cross-platform parity is handled in react.native.ts.

packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/ClaimButton/index.tsx (1)

14-14: Import path change to the web hook is correct.

packages/thirdweb/src/exports/react.native.ts (1)

62-62: RN export aliasing Core to the public name is correct.

Keeps the RN API stable while web moves to the new composition.

packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.tsx (1)

12-12: Import path change to the web hook is correct.

packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/CreateDirectListingButton/index.tsx (1)

17-17: All useSendAndConfirmTransaction imports are updated correctly—no stale imports found.

Copy link

codecov bot commented Aug 29, 2025

Codecov Report

❌ Patch coverage is 57.77778% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.53%. Comparing base (d5ff9f2) to head (597431e).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...prebuilt/thirdweb/BuyDirectListingButton/index.tsx 50.00% 5 Missing ⚠️
...act/web/ui/prebuilt/thirdweb/ClaimButton/index.tsx 50.00% 5 Missing ⚠️
...built/thirdweb/CreateDirectListingButton/index.tsx 50.00% 5 Missing ⚠️
...hooks/transaction/useSendAndConfirmTransaction.tsx 73.33% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7946      +/-   ##
==========================================
- Coverage   56.54%   56.53%   -0.02%     
==========================================
  Files         904      904              
  Lines       58605    58623      +18     
  Branches     4142     4146       +4     
==========================================
+ Hits        33141    33144       +3     
- Misses      25358    25373      +15     
  Partials      106      106              
Flag Coverage Δ
packages 56.53% <57.77%> (-0.02%) ⬇️
Files with missing lines Coverage Δ
...react/web/hooks/transaction/useSendTransaction.tsx 36.84% <ø> (ø)
...hooks/transaction/useSendAndConfirmTransaction.tsx 73.33% <73.33%> (ø)
...prebuilt/thirdweb/BuyDirectListingButton/index.tsx 43.69% <50.00%> (-0.45%) ⬇️
...act/web/ui/prebuilt/thirdweb/ClaimButton/index.tsx 64.19% <50.00%> (-1.39%) ⬇️
...built/thirdweb/CreateDirectListingButton/index.tsx 43.78% <50.00%> (-0.32%) ⬇️

... and 3 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

graphite-app bot commented Aug 29, 2025

Merge activity

…ook (#7946)

<!--

## 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 introduces a `Pay Modal` integration in the `useSendAndConfirmTransaction` hook, allowing users to handle insufficient funds by prompting them to purchase more. It also renames the hook and updates related components to utilize the new configuration.

### Detailed summary
- Renamed `useSendAndConfirmTransaction` to `useSendAndConfirmTransactionCore`.
- Updated exports to reflect the renaming.
- Added `payModal` configuration to `useSendAndConfirmTransaction`.
- Updated `CreateDirectListingButton`, `ClaimButton`, and `BuyDirectListingButton` to utilize the new `payModal` configuration.
- Enhanced documentation for `useSendAndConfirmTransaction` with usage examples for the `Pay Modal`.

> ✨ 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**
  * Pay Modal integrated into send-and-confirm transaction flows, matching send-only behavior.
  * Prebuilt buttons (Buy Direct Listing, Claim, Create Direct Listing) pass Pay Modal config and auto-fill metadata with sensible fallbacks for smoother top-ups.
  * Pay Modal options are configurable and compatible with gasless workflows.

* **Documentation**
  * Added examples and guidance for configuring the Pay Modal (theme, disabling, and usage).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
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

Caution

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

⚠️ Outside diff range comments (8)
packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.tsx (6)

91-91: Guard against boolean/null before accessing metadata.
Accessing payModal.metadata when payModal is true (boolean) or null will break typing or throw at runtime.

Apply:

-  const defaultPayModalMetadata = payModal ? payModal.metadata : undefined;
+  const defaultPayModalMetadata =
+    payModal && typeof payModal === "object" ? payModal.metadata : undefined;

99-105: Don’t fetch Pay metadata when the modal is disabled.
Avoid unnecessary network call if payModal === false.

   const { data: payMetadata } = useReadContract(getPayMetadata, {
     contract,
     listingId,
     queryOptions: {
-      enabled: !defaultPayModalMetadata,
+      enabled: payModal !== false && !defaultPayModalMetadata,
     },
   });

146-159: Fix ERC1155 quantity overwrite and lower-bound check.
_quantity is always reset to listing.quantity; and quantity < 0n allows 0n.

-    } else if (listing.asset.type === "ERC1155") {
-      if (typeof quantity === "bigint") {
-        if (quantity > listing.quantity) {
-          throw new Error(
-            `quantity exceeds available amount. Available: ${listing.quantity.toString()}`,
-          );
-        }
-        if (quantity < 0n) {
-          throw new Error("Invalid quantity. Should be at least 1n");
-        }
-        _quantity = quantity;
-      }
-      _quantity = listing.quantity;
-    }
+    } else if (listing.asset.type === "ERC1155") {
+      if (typeof quantity === "bigint") {
+        if (quantity > listing.quantity) {
+          throw new Error(
+            `quantity exceeds available amount. Available: ${listing.quantity.toString()}`,
+          );
+        }
+        if (quantity < 1n) {
+          throw new Error("Invalid quantity. Should be at least 1n");
+        }
+        _quantity = quantity;
+      } else {
+        _quantity = listing.quantity;
+      }
+    }

181-186: Passing an object here re-enables the modal when payModal === false.
This always passes a truthy object to TransactionButton, defeating the opt-out.

-    <TransactionButton
-      payModal={{
-        metadata: defaultPayModalMetadata || payMetadata,
-        ...payModal,
-      }}
+    <TransactionButton
+      payModal={
+        payModal === false
+          ? false
+          : payModal && typeof payModal === "object"
+            ? { metadata: defaultPayModalMetadata || payMetadata, ...payModal }
+            : undefined
+      }

25-27: Doc fix: wrong contract reference.
This component targets Marketplace v3, not Drop.

-   * The chain which the Drop contract is deployed on
+   * The chain which the Marketplace v3 contract is deployed on

51-80: Add required custom TSDoc tag for public symbol.
Repo guideline requires a custom tag (e.g., @beta). Add one to this component’s TSDoc.

  /**
   * This button is used with thirdweb Marketplace v3 contract, for buying NFT(s) from a listing.
@@
  * @transaction
+ * @beta
   */
packages/thirdweb/src/react/core/hooks/transaction/useSendAndConfirmTransaction.ts (2)

8-17: Doc header references wrong hook.
Should reference useSendAndConfirmTransaction(Core) not useSendTransaction.

-/**
- * Configuration for the `useSendTransaction` hook.
- */
+/**
+ * Configuration for the `useSendAndConfirmTransactionCore` hook.
+ */

20-55: Mark core hook as internal or fix examples.
This file exports useSendAndConfirmTransactionCore but examples import useSendAndConfirmTransaction. Either mark this as internal to avoid duplicate public docs, or update examples accordingly.

 /**
  * A hook to send a transaction.
  * @returns A mutation object to send a transaction.
@@
- * import { useSendAndConfirmTransaction } from "thirdweb/react";
+ * @internal
+ * Prefer `useSendAndConfirmTransaction` from `thirdweb/react` (web) or `thirdweb/react.native` (native).
+ * The examples below use the public re-exported name.
+ *
+ * import { useSendAndConfirmTransaction } from "thirdweb/react";
♻️ Duplicate comments (1)
packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.tsx (1)

107-115: Preserve explicit false and avoid null-object crash in hook config.
Current check treats null as object and spreads it; also less explicit than needed.

-  const { mutateAsync } = useSendAndConfirmTransaction({
-    payModal:
-      typeof payModal === "object"
-        ? {
-            ...payModal,
-            metadata: payModal.metadata || payMetadata,
-          }
-        : payModal,
-  });
+  const { mutateAsync } = useSendAndConfirmTransaction({
+    payModal:
+      payModal === false
+        ? false
+        : payModal && typeof payModal === "object"
+          ? { ...payModal, metadata: payModal.metadata || payMetadata }
+          : undefined,
+  });
🧹 Nitpick comments (1)
packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.tsx (1)

46-46: Nit: double space.

-   * The component will also throw an error if  you pass a `quantity` and it's greater than the listing's quantity
+   * The component will also throw an error if you pass a `quantity` and it's greater than the listing's quantity
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

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

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ec2ece0 and 597431e.

📒 Files selected for processing (9)
  • .changeset/pretty-geese-win.md (1 hunks)
  • packages/thirdweb/src/exports/react.native.ts (1 hunks)
  • packages/thirdweb/src/exports/react.ts (1 hunks)
  • packages/thirdweb/src/react/core/hooks/transaction/useSendAndConfirmTransaction.ts (1 hunks)
  • packages/thirdweb/src/react/web/hooks/transaction/useSendAndConfirmTransaction.tsx (1 hunks)
  • packages/thirdweb/src/react/web/hooks/transaction/useSendTransaction.tsx (1 hunks)
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.tsx (2 hunks)
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/ClaimButton/index.tsx (2 hunks)
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/CreateDirectListingButton/index.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • .changeset/pretty-geese-win.md
  • packages/thirdweb/src/react/web/hooks/transaction/useSendAndConfirmTransaction.tsx
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/ClaimButton/index.tsx
  • packages/thirdweb/src/exports/react.ts
  • packages/thirdweb/src/react/web/hooks/transaction/useSendTransaction.tsx
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/CreateDirectListingButton/index.tsx
  • packages/thirdweb/src/exports/react.native.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/core/hooks/transaction/useSendAndConfirmTransaction.ts
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.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/core/hooks/transaction/useSendAndConfirmTransaction.ts
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.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/core/hooks/transaction/useSendAndConfirmTransaction.ts
  • packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.tsx
🧬 Code graph analysis (2)
packages/thirdweb/src/react/core/hooks/transaction/useSendAndConfirmTransaction.ts (1)
packages/thirdweb/src/exports/react.native.ts (1)
  • useSendAndConfirmTransactionCore (62-62)
packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.tsx (2)
packages/thirdweb/src/exports/react.ts (1)
  • useSendAndConfirmTransaction (127-127)
packages/thirdweb/src/react/web/hooks/transaction/useSendAndConfirmTransaction.tsx (1)
  • useSendAndConfirmTransaction (89-104)
⏰ 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: Unit Tests
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: Size
  • GitHub Check: Lint Packages
  • GitHub Check: Build Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.tsx (1)

12-12: Import path change looks good.

packages/thirdweb/src/react/core/hooks/transaction/useSendAndConfirmTransaction.ts (1)

57-78: Core logic LGTM.
Error on missing account and delegation to sendAndConfirmTransaction look correct.

@graphite-app graphite-app bot merged commit 597431e into main Aug 29, 2025
24 of 25 checks passed
@graphite-app graphite-app bot deleted the 08-29-_mny-131_add_pay_modal_integration_in_hook branch August 29, 2025 17:51
@vercel vercel bot temporarily deployed to Production – docs-v2 August 29, 2025 18:08 Inactive
@vercel vercel bot temporarily deployed to Production – wallet-ui August 29, 2025 18:10 Inactive
@vercel vercel bot temporarily deployed to Production – thirdweb_playground August 29, 2025 18:13 Inactive
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