From 83a84d1e4c24451c052e5c618f9ab644aaed2ab8 Mon Sep 17 00:00:00 2001 From: gregfromstl Date: Thu, 7 Aug 2025 13:21:52 -0700 Subject: [PATCH 1/5] fix: skip payment method selection when balance is sufficient --- .changeset/fluffy-bobcats-walk.md | 5 +++++ .../react/core/hooks/useTransactionDetails.ts | 3 +-- .../src/react/core/machines/paymentMachine.ts | 4 +++- .../web/ui/Bridge/BridgeOrchestrator.tsx | 1 + .../web/ui/Bridge/TransactionPayment.tsx | 19 +++++++++++++++++++ .../react/web/ui/Bridge/TransactionWidget.tsx | 2 +- 6 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 .changeset/fluffy-bobcats-walk.md diff --git a/.changeset/fluffy-bobcats-walk.md b/.changeset/fluffy-bobcats-walk.md new file mode 100644 index 00000000000..24c19e79bf7 --- /dev/null +++ b/.changeset/fluffy-bobcats-walk.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +Skips payment selection in the TransactionWidget if the user's balance is sufficient to complete the transaction. diff --git a/packages/thirdweb/src/react/core/hooks/useTransactionDetails.ts b/packages/thirdweb/src/react/core/hooks/useTransactionDetails.ts index da8f3360e68..0cc5c75f746 100644 --- a/packages/thirdweb/src/react/core/hooks/useTransactionDetails.ts +++ b/packages/thirdweb/src/react/core/hooks/useTransactionDetails.ts @@ -64,7 +64,6 @@ export function useTransactionDetails({ return useQuery({ enabled: !!transaction.to && !!chainMetadata.data, queryFn: async (): Promise => { - // Create contract instance for metadata fetching const contract = getContract({ address: transaction.to as string, chain: transaction.chain, @@ -84,7 +83,7 @@ export function useTransactionDetails({ client, erc20Value?.tokenAddress || NATIVE_TOKEN_ADDRESS, transaction.chain.id, - ).catch(() => null), + ), hasSponsoredTransactions ? 0n : getTransactionGasCost(transaction).catch(() => null), diff --git a/packages/thirdweb/src/react/core/machines/paymentMachine.ts b/packages/thirdweb/src/react/core/machines/paymentMachine.ts index 337db24c424..b0b1915dcb5 100644 --- a/packages/thirdweb/src/react/core/machines/paymentMachine.ts +++ b/packages/thirdweb/src/react/core/machines/paymentMachine.ts @@ -70,7 +70,7 @@ export interface PaymentMachineContext { /** * Events that can be sent to the payment machine */ -type PaymentMachineEvent = +export type PaymentMachineEvent = | { type: "DESTINATION_CONFIRMED"; destinationToken: Token; @@ -230,6 +230,8 @@ export function usePaymentMachine( if (event.type === "DESTINATION_CONFIRMED") return "methodSelection"; if (event.type === "ERROR_OCCURRED") return "error"; + if (event.type === "CONTINUE_TO_TRANSACTION") + return "post-buy-transaction"; break; case "methodSelection": diff --git a/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx b/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx index baa04fc6195..5ea34974a3f 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx @@ -288,6 +288,7 @@ export function BridgeOrchestrator({ client={client} connectOptions={modifiedConnectOptions} onContinue={handleRequirementsResolved} + sendEvent={send} showThirdwebBranding={showThirdwebBranding} uiOptions={uiOptions} /> diff --git a/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx b/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx index 9da849d6d31..2cfa3084add 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx @@ -1,5 +1,6 @@ "use client"; import { useQuery } from "@tanstack/react-query"; +import type { PaymentMachineEvent } from "src/react/core/machines/paymentMachine.js"; import type { Token } from "../../../../bridge/index.js"; import type { ThirdwebClient } from "../../../../client/client.js"; import { NATIVE_TOKEN_ADDRESS } from "../../../../constants/addresses.js"; @@ -48,6 +49,11 @@ export interface TransactionPaymentProps { */ onContinue: (amount: string, token: Token, receiverAddress: Address) => void; + /** + * Send arbitrary payment events for UI flow control + */ + sendEvent: (event: PaymentMachineEvent) => void; + /** * Connect options for wallet connection */ @@ -64,6 +70,7 @@ export function TransactionPayment({ uiOptions, client, onContinue, + sendEvent, connectOptions, showThirdwebBranding = true, }: TransactionPaymentProps) { @@ -378,6 +385,18 @@ export function TransactionPayment({ return; } + // If the user has enough to pay, skip the payment step altogether + if ( + userBalance && + Number(userBalance) >= + Number(transactionDataQuery.data.totalCost) + ) { + sendEvent({ + type: "CONTINUE_TO_TRANSACTION", + }); + return; + } + // otherwise, use the full transaction cost onContinue( transactionDataQuery.data.totalCost, diff --git a/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx b/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx index df7da902b93..2d246b99efd 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx @@ -218,7 +218,7 @@ type UIOptionsResult = * @example * ### Default configuration * - * By default, the `TransactionWidget` component will allows users to fund their wallets with crypto or fiat on any of the supported chains.. + * By default, the `TransactionWidget` component allows users to fund their wallets with crypto or fiat on any of the supported chains. * * ```tsx * Date: Thu, 7 Aug 2025 13:39:47 -0700 Subject: [PATCH 2/5] fix build --- .../thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx | 2 +- .../thirdweb/src/stories/Bridge/TransactionPayment.stories.tsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx b/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx index 2cfa3084add..fbc880ac581 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx @@ -1,6 +1,5 @@ "use client"; import { useQuery } from "@tanstack/react-query"; -import type { PaymentMachineEvent } from "src/react/core/machines/paymentMachine.js"; import type { Token } from "../../../../bridge/index.js"; import type { ThirdwebClient } from "../../../../client/client.js"; import { NATIVE_TOKEN_ADDRESS } from "../../../../constants/addresses.js"; @@ -21,6 +20,7 @@ import { useChainMetadata } from "../../../core/hooks/others/useChainQuery.js"; import { useTransactionDetails } from "../../../core/hooks/useTransactionDetails.js"; import { useActiveAccount } from "../../../core/hooks/wallets/useActiveAccount.js"; import { useActiveWallet } from "../../../core/hooks/wallets/useActiveWallet.js"; +import type { PaymentMachineEvent } from "../../../core/machines/paymentMachine.js"; import { ConnectButton } from "../ConnectWallet/ConnectButton.js"; import { PoweredByThirdweb } from "../ConnectWallet/PoweredByTW.js"; import { Container, Line } from "../components/basic.js"; diff --git a/packages/thirdweb/src/stories/Bridge/TransactionPayment.stories.tsx b/packages/thirdweb/src/stories/Bridge/TransactionPayment.stories.tsx index bb2b00646a8..14d84c297a7 100644 --- a/packages/thirdweb/src/stories/Bridge/TransactionPayment.stories.tsx +++ b/packages/thirdweb/src/stories/Bridge/TransactionPayment.stories.tsx @@ -29,6 +29,7 @@ const TransactionPaymentWithTheme = ( const meta = { args: { client: storyClient, + sendEvent: (_event) => {}, onContinue: (_amount, _token, _receiverAddress) => {}, theme: "dark", uiOptions: TRANSACTION_UI_OPTIONS.ethTransfer, From 4fdccea0143c081a88748fa147a5f583a7226a24 Mon Sep 17 00:00:00 2001 From: gregfromstl Date: Thu, 7 Aug 2025 16:36:18 -0700 Subject: [PATCH 3/5] fix: thirdweb domain overrides --- packages/thirdweb/src/bridge/Token.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/thirdweb/src/bridge/Token.ts b/packages/thirdweb/src/bridge/Token.ts index 39c7ef18b3b..59a761c5f4d 100644 --- a/packages/thirdweb/src/bridge/Token.ts +++ b/packages/thirdweb/src/bridge/Token.ts @@ -1,5 +1,5 @@ import type { ThirdwebClient } from "../client/client.js"; -import { getThirdwebBaseUrl } from "../utils/domains.js"; +import { getThirdwebDomains } from "../utils/domains.js"; import { getClientFetch } from "../utils/fetch.js"; import { ApiError } from "./types/Errors.js"; import type { Token } from "./types/Token.js"; @@ -133,7 +133,7 @@ export async function tokens(options: tokens.Options): Promise { options; const clientFetch = getClientFetch(client); - const url = new URL(`${getThirdwebBaseUrl("bridge")}/v1/tokens`); + const url = new URL(`${getThirdwebDomains().bridge}/v1/tokens`); if (chainId !== null && chainId !== undefined) { url.searchParams.set("chainId", chainId.toString()); @@ -229,7 +229,7 @@ export async function add(options: add.Options): Promise { const { client, chainId, tokenAddress } = options; const clientFetch = getClientFetch(client); - const url = `${getThirdwebBaseUrl("bridge")}/v1/tokens`; + const url = `${getThirdwebDomains().bridge}/v1/tokens`; const requestBody = { chainId, From c4c07443f375daf90eceba3613abd2bc6ba87290 Mon Sep 17 00:00:00 2001 From: gregfromstl Date: Thu, 7 Aug 2025 16:53:59 -0700 Subject: [PATCH 4/5] Revert "fix: thirdweb domain overrides" This reverts commit 4fdccea0143c081a88748fa147a5f583a7226a24. --- packages/thirdweb/src/bridge/Token.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/thirdweb/src/bridge/Token.ts b/packages/thirdweb/src/bridge/Token.ts index 59a761c5f4d..39c7ef18b3b 100644 --- a/packages/thirdweb/src/bridge/Token.ts +++ b/packages/thirdweb/src/bridge/Token.ts @@ -1,5 +1,5 @@ import type { ThirdwebClient } from "../client/client.js"; -import { getThirdwebDomains } from "../utils/domains.js"; +import { getThirdwebBaseUrl } from "../utils/domains.js"; import { getClientFetch } from "../utils/fetch.js"; import { ApiError } from "./types/Errors.js"; import type { Token } from "./types/Token.js"; @@ -133,7 +133,7 @@ export async function tokens(options: tokens.Options): Promise { options; const clientFetch = getClientFetch(client); - const url = new URL(`${getThirdwebDomains().bridge}/v1/tokens`); + const url = new URL(`${getThirdwebBaseUrl("bridge")}/v1/tokens`); if (chainId !== null && chainId !== undefined) { url.searchParams.set("chainId", chainId.toString()); @@ -229,7 +229,7 @@ export async function add(options: add.Options): Promise { const { client, chainId, tokenAddress } = options; const clientFetch = getClientFetch(client); - const url = `${getThirdwebDomains().bridge}/v1/tokens`; + const url = `${getThirdwebBaseUrl("bridge")}/v1/tokens`; const requestBody = { chainId, From 9b3fa48b53a77d23f215fb8a1398eae37f1f476c Mon Sep 17 00:00:00 2001 From: gregfromstl Date: Thu, 7 Aug 2025 16:55:07 -0700 Subject: [PATCH 5/5] Revert "fix: thirdweb domain overrides" This reverts commit 4fdccea0143c081a88748fa147a5f583a7226a24. --- packages/thirdweb/src/bridge/Token.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/thirdweb/src/bridge/Token.ts b/packages/thirdweb/src/bridge/Token.ts index 59a761c5f4d..39c7ef18b3b 100644 --- a/packages/thirdweb/src/bridge/Token.ts +++ b/packages/thirdweb/src/bridge/Token.ts @@ -1,5 +1,5 @@ import type { ThirdwebClient } from "../client/client.js"; -import { getThirdwebDomains } from "../utils/domains.js"; +import { getThirdwebBaseUrl } from "../utils/domains.js"; import { getClientFetch } from "../utils/fetch.js"; import { ApiError } from "./types/Errors.js"; import type { Token } from "./types/Token.js"; @@ -133,7 +133,7 @@ export async function tokens(options: tokens.Options): Promise { options; const clientFetch = getClientFetch(client); - const url = new URL(`${getThirdwebDomains().bridge}/v1/tokens`); + const url = new URL(`${getThirdwebBaseUrl("bridge")}/v1/tokens`); if (chainId !== null && chainId !== undefined) { url.searchParams.set("chainId", chainId.toString()); @@ -229,7 +229,7 @@ export async function add(options: add.Options): Promise { const { client, chainId, tokenAddress } = options; const clientFetch = getClientFetch(client); - const url = `${getThirdwebDomains().bridge}/v1/tokens`; + const url = `${getThirdwebBaseUrl("bridge")}/v1/tokens`; const requestBody = { chainId,