From aea2245eab4aa7f7107084f4b6be4df9160d3ae4 Mon Sep 17 00:00:00 2001 From: gregfromstl Date: Wed, 25 Jun 2025 13:03:21 -0700 Subject: [PATCH 1/8] chore: remove onrampTokenAddress set to ETH --- packages/thirdweb/src/pay/buyWithFiat/getQuote.ts | 2 +- packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts b/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts index 2f7dc0648c1..a5851030826 100644 --- a/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts +++ b/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts @@ -326,7 +326,7 @@ export async function getBuyWithFiatQuote( maxSteps: 2, onramp: onrampProvider, onrampChainId: params.onrampChainId, - onrampTokenAddress: params.onrampTokenAddress ?? NATIVE_TOKEN_ADDRESS, + onrampTokenAddress: params.onrampTokenAddress, paymentLinkId: params.paymentLinkId, purchaseData: params.purchaseData, receiver: params.toAddress, // force onramp to native token to avoid missing gas issues diff --git a/packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx b/packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx index e71cc1ca6f7..fe2603a01e2 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/QuoteLoader.tsx @@ -4,7 +4,6 @@ import { useEffect } from "react"; import { trackPayEvent } from "../../../../analytics/track/pay.js"; import type { Token } from "../../../../bridge/types/Token.js"; import type { ThirdwebClient } from "../../../../client/client.js"; -import { NATIVE_TOKEN_ADDRESS } from "../../../../constants/addresses.js"; import { toUnits } from "../../../../utils/units.js"; import { type BridgePrepareRequest, @@ -191,7 +190,6 @@ function getBridgeParams(args: { currency: paymentMethod.currency, enabled: !!(destinationToken && amount && client), onramp: paymentMethod.onramp || "coinbase", - onrampTokenAddress: NATIVE_TOKEN_ADDRESS, paymentLinkId: args.paymentLinkId, purchaseData: args.purchaseData, receiver, From 61fed8cf58de4cfa956d469f273c6ce4f6a5cdea Mon Sep 17 00:00:00 2001 From: gregfromstl Date: Wed, 25 Jun 2025 13:10:30 -0700 Subject: [PATCH 2/8] fix: onramp step label Fixes TOOL-4871 --- packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx b/packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx index 0e5690fb70f..c0c5266271a 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/StepRunner.tsx @@ -322,7 +322,8 @@ export function StepRunner({ - TEST + {request.onramp.slice(0, 1).toUpperCase() + + request.onramp.slice(1)} {getStepStatusText(onrampStatus)} From 9f42f55fae12c304f7734fb5b8a7b01aa4ccbc55 Mon Sep 17 00:00:00 2001 From: gregfromstl Date: Wed, 25 Jun 2025 13:34:01 -0700 Subject: [PATCH 3/8] fix: onramp transactions missing chain and client --- packages/thirdweb/src/bridge/Onramp.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/thirdweb/src/bridge/Onramp.ts b/packages/thirdweb/src/bridge/Onramp.ts index e56aba9b738..2382888061d 100644 --- a/packages/thirdweb/src/bridge/Onramp.ts +++ b/packages/thirdweb/src/bridge/Onramp.ts @@ -6,6 +6,7 @@ import { stringify } from "../utils/json.js"; import { ApiError } from "./types/Errors.js"; import type { RouteStep } from "./types/Route.js"; import type { Token } from "./types/Token.js"; +import { defineChain } from "../chains/utils.js"; // export status within the Onramp module export { status } from "./OnrampStatus.js"; @@ -237,6 +238,8 @@ export async function prepare( originAmount: BigInt(step.originAmount), transactions: step.transactions.map((tx) => ({ ...tx, + chain: defineChain(tx.chainId), + client, value: tx.value ? BigInt(tx.value) : undefined, })), })); From 3562a50404f86e43453df8c6bb7fc3dd21b599e6 Mon Sep 17 00:00:00 2001 From: gregfromstl Date: Wed, 25 Jun 2025 13:34:18 -0700 Subject: [PATCH 4/8] fix: slight delay after fee and approvals for rpc catch up --- packages/thirdweb/src/react/core/hooks/useStepExecutor.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/thirdweb/src/react/core/hooks/useStepExecutor.ts b/packages/thirdweb/src/react/core/hooks/useStepExecutor.ts index 53bad596148..86b703e9abf 100644 --- a/packages/thirdweb/src/react/core/hooks/useStepExecutor.ts +++ b/packages/thirdweb/src/react/core/hooks/useStepExecutor.ts @@ -27,9 +27,9 @@ export type CompletedStatusResult = | ({ type: "sell" } & Extract) | ({ type: "transfer" } & Extract) | ({ type: "onramp" } & Extract< - OnrampStatus.Result, - { status: "COMPLETED" } - >); + OnrampStatus.Result, + { status: "COMPLETED" } + >); /** * Options for the step executor hook @@ -237,6 +237,7 @@ export function useStepExecutor( if (tx.action === "approval" || tx.action === "fee") { // don't poll status for approval transactions, just wait for confirmation await waitForReceipt(result); + await new Promise((resolve) => setTimeout(resolve, 1000)); // Add an extra second delay for RPC to catch up to new state return; } From befed3046611d94624cf328f2be347e5ef09f142 Mon Sep 17 00:00:00 2001 From: gregfromstl Date: Wed, 25 Jun 2025 13:34:49 -0700 Subject: [PATCH 5/8] changeset --- .changeset/old-bats-love.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/old-bats-love.md diff --git a/.changeset/old-bats-love.md b/.changeset/old-bats-love.md new file mode 100644 index 00000000000..a6d8628e0a6 --- /dev/null +++ b/.changeset/old-bats-love.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +A number of important fixes for payment widgets From 3d8869aeef221e45392b1cbc4d83998737b11bd3 Mon Sep 17 00:00:00 2001 From: gregfromstl Date: Wed, 25 Jun 2025 13:36:37 -0700 Subject: [PATCH 6/8] lint --- packages/thirdweb/src/bridge/Onramp.ts | 2 +- packages/thirdweb/src/react/core/hooks/useStepExecutor.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/thirdweb/src/bridge/Onramp.ts b/packages/thirdweb/src/bridge/Onramp.ts index 2382888061d..582ef5337be 100644 --- a/packages/thirdweb/src/bridge/Onramp.ts +++ b/packages/thirdweb/src/bridge/Onramp.ts @@ -1,4 +1,5 @@ import type { Address as ox__Address } from "ox"; +import { defineChain } from "../chains/utils.js"; import type { ThirdwebClient } from "../client/client.js"; import { getThirdwebBaseUrl } from "../utils/domains.js"; import { getClientFetch } from "../utils/fetch.js"; @@ -6,7 +7,6 @@ import { stringify } from "../utils/json.js"; import { ApiError } from "./types/Errors.js"; import type { RouteStep } from "./types/Route.js"; import type { Token } from "./types/Token.js"; -import { defineChain } from "../chains/utils.js"; // export status within the Onramp module export { status } from "./OnrampStatus.js"; diff --git a/packages/thirdweb/src/react/core/hooks/useStepExecutor.ts b/packages/thirdweb/src/react/core/hooks/useStepExecutor.ts index 86b703e9abf..4754b1aae13 100644 --- a/packages/thirdweb/src/react/core/hooks/useStepExecutor.ts +++ b/packages/thirdweb/src/react/core/hooks/useStepExecutor.ts @@ -27,9 +27,9 @@ export type CompletedStatusResult = | ({ type: "sell" } & Extract) | ({ type: "transfer" } & Extract) | ({ type: "onramp" } & Extract< - OnrampStatus.Result, - { status: "COMPLETED" } - >); + OnrampStatus.Result, + { status: "COMPLETED" } + >); /** * Options for the step executor hook From 920c7e04ccef9d51611189735c736212c8f375c1 Mon Sep 17 00:00:00 2001 From: gregfromstl Date: Wed, 25 Jun 2025 13:46:20 -0700 Subject: [PATCH 7/8] fix: error message when no onramp quotes exist --- .../Bridge/payment-selection/FiatProviderSelection.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/FiatProviderSelection.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/FiatProviderSelection.tsx index c9107df5fbf..d76b27717fd 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/FiatProviderSelection.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/FiatProviderSelection.tsx @@ -71,6 +71,16 @@ export function FiatProviderSelection({ return quoteQueries.map((q) => q.data).filter((q) => !!q); }, [quoteQueries]); + if (quoteQueries.every((q) => q.isError)) { + return ( + + + No quotes available + + + ); + } + // TODO: add a "remember my choice" checkbox return ( From e9a77730244cd9e36f6a4889c66f9c96553d151d Mon Sep 17 00:00:00 2001 From: gregfromstl Date: Wed, 25 Jun 2025 14:12:20 -0700 Subject: [PATCH 8/8] feat: cleanup step preview ui --- .../Bridge/payment-details/PaymentDetails.tsx | 55 +++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx index b15b369b28a..9ce301eb502 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx @@ -1,9 +1,11 @@ "use client"; import { useQuery } from "@tanstack/react-query"; +import { useMemo } from "react"; import { trackPayEvent } from "../../../../../analytics/track/pay.js"; import type { ThirdwebClient } from "../../../../../client/client.js"; import { useCustomTheme } from "../../../../core/design-system/CustomThemeProvider.js"; import { radius, spacing } from "../../../../core/design-system/index.js"; +import { useChainsQuery } from "../../../../core/hooks/others/useChainQuery.js"; import type { BridgePrepareResult } from "../../../../core/hooks/useBridgePrepare.js"; import type { PaymentMethod } from "../../../../core/machines/paymentMachine.js"; import { @@ -102,6 +104,15 @@ export function PaymentDetails({ queryKey: ["payment_details", preparedQuote.type], }); + const chainsQuery = useChainsQuery( + preparedQuote.steps.flatMap((s) => s.transactions.map((t) => t.chain)), + 10, + ); + const chainsMetadata = useMemo( + () => chainsQuery.map((c) => c.data), + [chainsQuery], + ).filter((c) => !!c); + // Extract common data based on quote type const getDisplayData = () => { switch (preparedQuote.type) { @@ -321,12 +332,48 @@ export function PaymentDetails({ > - {step.originToken.symbol} →{" "} - {step.destinationToken.symbol} + {step.destinationToken.chainId !== + step.originToken.chainId ? ( + <> + Bridge{" "} + {step.originToken.symbol === + step.destinationToken.symbol + ? step.originToken.symbol + : `${step.originToken.symbol} to ${step.destinationToken.symbol}`} + + ) : ( + <> + Swap {step.originToken.symbol} to{" "} + {step.destinationToken.symbol} + + )} - {step.originToken.name} to{" "} - {step.destinationToken.name} + {step.originToken.chainId !== + step.destinationToken.chainId ? ( + <> + { + chainsMetadata.find( + (c) => c.chainId === step.originToken.chainId, + )?.name + }{" "} + to{" "} + { + chainsMetadata.find( + (c) => + c.chainId === step.destinationToken.chainId, + )?.name + } + + ) : ( + <> + { + chainsMetadata.find( + (c) => c.chainId === step.originToken.chainId, + )?.name + } + + )}