Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 26 additions & 36 deletions apps/dashboard/src/@/components/tx-button/MismatchButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
} from "thirdweb";
import { type Chain, type ChainMetadata, localhost } from "thirdweb/chains";
import {
PayEmbed,
CheckoutWidget,
useActiveAccount,
useActiveWallet,
useActiveWalletChain,
Expand All @@ -29,7 +29,6 @@ import {
import { privateKeyToAccount, type Wallet } from "thirdweb/wallets";
import { apiServerProxy } from "@/actions/proxies";
import { Button } from "@/components/ui/button";
import { DynamicHeight } from "@/components/ui/DynamicHeight";
import {
Dialog,
DialogContent,
Expand Down Expand Up @@ -251,39 +250,34 @@ export const MismatchButton = forwardRef<
>
<DialogContent
className={cn(
"gap-0 p-0",
dialog === "no-funds" && "md:!max-w-[480px]",
dialog === "pay" && "md:!max-w-[360px] border-none bg-transparent",
"gap-0 p-0 md:!max-w-[480px]",
dialog === "pay" && "border-none bg-transparent",
)}
dialogCloseClassName="focus:ring-0"
>
<DynamicHeight>
{dialog === "no-funds" && (
<NoFundsDialogContent
chain={txChain}
client={props.client}
isLoggedIn={props.isLoggedIn}
onCloseModal={() => setDialog(undefined)}
openPayModal={() => {
setDialog("pay");
}}
/>
)}
{dialog === "no-funds" && (
<NoFundsDialogContent
chain={txChain}
client={props.client}
isLoggedIn={props.isLoggedIn}
onCloseModal={() => setDialog(undefined)}
openPayModal={() => {
setDialog("pay");
}}
/>
)}

{dialog === "pay" && (
<PayEmbed
className="!w-auto"
client={props.client}
payOptions={{
prefillBuy: {
amount: "0.01",
chain: txChain,
},
}}
theme={getSDKTheme(theme === "dark" ? "dark" : "light")}
/>
)}
</DynamicHeight>
{dialog === "pay" && account && (
<CheckoutWidget
className="!w-full"
client={props.client}
chain={txChain}
amount="0.01"
name="Buy Funds"
seller={account.address as `0x${string}`}
theme={getSDKTheme(theme === "dark" ? "dark" : "light")}
/>
)}
Comment on lines +270 to +280
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

CheckoutWidget usage: verify prop semantics; add resilience and reset behavior

  • Verify that seller={account.address} is the correct prop to direct funds to the connected wallet for “Buy Funds” use-cases. If the prop represents a merchant/recipient (not the buyer), confirm it aligns with your intended flow.
  • Consider forcing a remount when the chain or address changes to avoid stale internal state.
  • If the widget exposes success/close callbacks, wire them to setDialog(undefined) so the dialog closes on completion/cancel.

Apply this small resilience tweak (safe regardless of API details):

-            <CheckoutWidget
+            <CheckoutWidget
+              key={`${txChain.id}-${account.address}`}
               className="!w-full"
               client={props.client}
               chain={txChain}
               amount="0.01"
               name="Buy Funds"
               seller={account.address as `0x${string}`}
               theme={getSDKTheme(theme === "dark" ? "dark" : "light")}
             />

To confirm the prop semantics, please run this web query:


🌐 Web query:

What are the props and semantics of thirdweb’s React CheckoutWidget (particularly the meaning of the `seller` prop and expected format of `amount`)? Provide the relevant docs link.

💡 Result:

Short answer

  • seller — the recipient wallet (an Address) that will receive the payment. Pass the seller’s wallet address (e.g. "0x1234...abcd"). (portal.thirdweb.com)
  • amount — the purchase amount as a human‑readable string (e.g. "99" or "0.0002"). The CheckoutWidget TypeScript prop is typed as string, so prefer passing a string (examples in the docs sometimes show numeric literals, but the typed prop is string). The widget will interpret the amount relative to the other props you pass (currency / tokenAddress / supportedTokens). (portal.thirdweb.com)

Key props / semantics (most useful ones)

Recommended usage (TypeScript-friendly)

  • Pass amount as a string to match the prop type and avoid TS errors.
  • Pass seller as an address string (checksummed address string).
    Example:
    <CheckoutWidget
    client={client}
    chain={arbitrum}
    amount="99" // e.g. $99 (or "0.01" ETH depending on configuration)
    seller="0x1234...abcDEF" // wallet that should receive payouts
    name="Premium Course"
    description="Complete guide to web3 development"
    purchaseData={{ productId: "premium-course" }}
    onSuccess={() => { /* ... */ }}
    />

Relevant docs

If you want, I can:

  • paste the full prop type list from the API reference, or
  • show example permutations (fiat vs. token checkout) and how amount is interpreted in each case. Which would you prefer?

Citations:


Confirm CheckoutWidget props; implement remount key and close callbacks

  • seller={account.address} is correct: this prop directs payouts to the provided wallet.
  • amount="0.01" is the expected human-readable string format.
  • To avoid stale internal state, add a key prop that changes when txChain or account.address changes.
  • Wire the widget’s completion/cancel callbacks to setDialog(undefined) so the modal closes on success, error, or cancellation.

Proposed diff:

           {dialog === "pay" && account && (
-            <CheckoutWidget
+            <CheckoutWidget
+              key={`${txChain.id}-${account.address}`}
               className="!w-full"
               client={props.client}
               chain={txChain}
               amount="0.01"
               name="Buy Funds"
               seller={account.address as `0x${string}`}
+              onSuccess={() => setDialog(undefined)}
+              onError={() => setDialog(undefined)}
+              onCancel={() => setDialog(undefined)}
               theme={getSDKTheme(theme === "dark" ? "dark" : "light")}
             />
           )}

Reference: CheckoutWidget API – props and semantics (seller = recipient address, amount = human-readable string)
https://portal.thirdweb.com/references/typescript/v5/widgets/CheckoutWidget [1]

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{dialog === "pay" && account && (
<CheckoutWidget
className="!w-full"
client={props.client}
chain={txChain}
amount="0.01"
name="Buy Funds"
seller={account.address as `0x${string}`}
theme={getSDKTheme(theme === "dark" ? "dark" : "light")}
/>
)}
{dialog === "pay" && account && (
<CheckoutWidget
key={`${txChain.id}-${account.address}`}
className="!w-full"
client={props.client}
chain={txChain}
amount="0.01"
name="Buy Funds"
seller={account.address as `0x${string}`}
onSuccess={() => setDialog(undefined)}
onError={() => setDialog(undefined)}
onCancel={() => setDialog(undefined)}
theme={getSDKTheme(theme === "dark" ? "dark" : "light")}
/>
)}
🤖 Prompt for AI Agents
In apps/dashboard/src/@/components/tx-button/MismatchButton.tsx around lines 270
to 280, the CheckoutWidget needs a remount key and close callbacks: add a key
prop that changes when txChain or account.address changes (e.g.,
`${txChain}-${account.address}`) to force remounts when either changes, and pass
callbacks (onSuccess, onError, onCancel or the widget's equivalent) that call
setDialog(undefined) so the modal closes on completion, error, or cancellation;
keep seller as account.address and amount as "0.01".

</DialogContent>
</Dialog>
</>
Expand Down Expand Up @@ -362,11 +356,7 @@ function NoFundsDialogContent(props: {
(x) => x.enabled && x.service === "pay",
) ? (
// pay case
<Button
className="w-full"
onClick={props.openPayModal}
variant="primary"
>
<Button className="w-full" onClick={props.openPayModal}>
Buy Funds
</Button>
) : // no funds options available
Expand Down
2 changes: 1 addition & 1 deletion apps/dashboard/src/@/components/ui/DynamicHeight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function DynamicHeight(props: {
boxSizing: "border-box",
height: height ? `${height}px` : "auto",
overflow: "hidden",
transition: props.transition || "height 250ms ease",
transition: props.transition || "height 220ms ease",
}}
>
<div
Expand Down
Loading