diff --git a/.changeset/few-moments-add.md b/.changeset/few-moments-add.md new file mode 100644 index 00000000000..a709db25de1 --- /dev/null +++ b/.changeset/few-moments-add.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +Fixed a regression that prompted the user to pay the full amount in the TransactionWidget, rather than the difference from their current balance diff --git a/packages/thirdweb/src/react/core/hooks/useTransactionDetails.ts b/packages/thirdweb/src/react/core/hooks/useTransactionDetails.ts index 64ec52d18d3..a251e954a0a 100644 --- a/packages/thirdweb/src/react/core/hooks/useTransactionDetails.ts +++ b/packages/thirdweb/src/react/core/hooks/useTransactionDetails.ts @@ -81,7 +81,7 @@ export function useTransactionDetails({ const [tokenInfo, gasCostWei] = await Promise.all([ getToken( client, - erc20Value ? erc20Value.tokenAddress : NATIVE_TOKEN_ADDRESS, + erc20Value?.tokenAddress || NATIVE_TOKEN_ADDRESS, transaction.chain.id, ).catch(() => null), hasSponsoredTransactions @@ -151,9 +151,11 @@ export function useTransactionDetails({ chainMetadata.data?.nativeCurrency?.symbol || "ETH"; const tokenSymbol = tokenInfo?.symbol || nativeTokenSymbol; - const totalCostWei = erc20Value - ? erc20Value.amountWei - : (value || 0n) + (gasCostWei || 0n); + const totalCostWei = + erc20Value && + erc20Value.tokenAddress.toLowerCase() !== NATIVE_TOKEN_ADDRESS + ? erc20Value.amountWei + : (value || 0n) + (gasCostWei || 0n); const totalCost = toTokens(totalCostWei, decimal); const price = tokenInfo?.prices[currency || "USD"] || 0; diff --git a/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx b/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx index 0bc1e1ce47c..8cae9813e29 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx @@ -1,11 +1,15 @@ "use client"; +import { useQuery } from "@tanstack/react-query"; import type { Token } from "../../../../bridge/index.js"; import type { ThirdwebClient } from "../../../../client/client.js"; +import { NATIVE_TOKEN_ADDRESS } from "../../../../constants/addresses.js"; import { type Address, getAddress, shortenAddress, } from "../../../../utils/address.js"; +import { resolvePromisedValue } from "../../../../utils/promise/resolve-promised-value.js"; +import { getWalletBalance } from "../../../../wallets/utils/getWalletBalance.js"; import { useCustomTheme } from "../../../core/design-system/CustomThemeProvider.js"; import { fontSize, @@ -77,6 +81,31 @@ export function TransactionPayment({ wallet, }); + // We can't use useWalletBalance here because erc20Value is a possibly async value + const { data: userBalance } = useQuery({ + enabled: !!activeAccount?.address, + queryFn: async (): Promise => { + if (!activeAccount?.address) { + return "0"; + } + const erc20Value = await resolvePromisedValue( + uiOptions.transaction.erc20Value, + ); + const walletBalance = await getWalletBalance({ + address: activeAccount?.address, + chain: uiOptions.transaction.chain, + tokenAddress: + erc20Value?.tokenAddress.toLowerCase() !== NATIVE_TOKEN_ADDRESS + ? erc20Value?.tokenAddress + : undefined, + client, + }); + + return walletBalance.displayValue; + }, + queryKey: ["user-balance", activeAccount?.address], + }); + const contractName = transactionDataQuery.data?.contractMetadata?.name || "Unknown Contract"; const functionName = @@ -327,7 +356,11 @@ export function TransactionPayment({ onClick={() => { if (transactionDataQuery.data?.tokenInfo) { onContinue( - transactionDataQuery.data.totalCost, + Math.max( + 0, + Number(transactionDataQuery.data.totalCost) - + Number(userBalance ?? "0"), + ).toString(), transactionDataQuery.data.tokenInfo, getAddress(activeAccount.address), ); 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 48eb6f17cd4..b002c97a7db 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 @@ -3,6 +3,7 @@ import { useMemo } from "react"; import type { ThirdwebClient } from "../../../../../client/client.js"; import type { SupportedFiatCurrency } from "../../../../../pay/convert/type.js"; import { checksumAddress } from "../../../../../utils/address.js"; +import { formatNumber } from "../../../../../utils/formatNumber.js"; import { toTokens } from "../../../../../utils/units.js"; import { useCustomTheme } from "../../../../core/design-system/CustomThemeProvider.js"; import { @@ -171,9 +172,14 @@ export function FiatProviderSelection({ {quote.currency} - {toTokens( - quote.destinationAmount, - quote.destinationToken.decimals, + {formatNumber( + Number( + toTokens( + quote.destinationAmount, + quote.destinationToken.decimals, + ), + ), + 4, )}{" "} {quote.destinationToken.symbol}