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
8 changes: 8 additions & 0 deletions .changeset/moody-pants-play.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"thirdweb": patch
---

Miscellaneous PayEmbed error improvements:
- Adds title and message to PayEmbed errors
- Prevents propagating raw errors to the user when in purchase or transaction mode
- Fixes bubble alignment on pulsing animation
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@
const PulsingDot = /* @__PURE__ */ StyledDiv(() => {
return {
background: "currentColor",
width: "9px",
height: "9px",
width: "10px",
height: "10px",

Check warning on line 76 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/Stepper.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/Stepper.tsx#L75-L76

Added lines #L75 - L76 were not covered by tests
borderRadius: "50%",
'&[data-active="true"]': {
animation: `${pulseAnimation} 1s infinite`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,14 @@
) : activeAccount ? (
<Container flex="column" gap="sm">
{insufficientFunds && (
<Text size="sm" color="danger" style={{ textAlign: "center" }}>
Insufficient funds
</Text>
<div>
<Text color="danger" size="xs" center multiline>

Check warning on line 190 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.tsx#L189-L190

Added lines #L189 - L190 were not covered by tests
Insufficient Funds
</Text>
<Text size="xs" center multiline>

Check warning on line 193 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.tsx#L192-L193

Added lines #L192 - L193 were not covered by tests
Select another token or pay with a debit card.
</Text>
</div>

Check warning on line 196 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.tsx#L195-L196

Added lines #L195 - L196 were not covered by tests
)}
<Container
flex="row"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@
import type { PayUIOptions } from "../../../../../../core/hooks/connection/ConnectButtonProps.js";
import { useBuyWithFiatQuote } from "../../../../../../core/hooks/pay/useBuyWithFiatQuote.js";
import { PREFERRED_FIAT_PROVIDER_STORAGE_KEY } from "../../../../../../core/utils/storage.js";
import {
defaultMessage,
getErrorMessage,
} from "../../../../../utils/errors.js";
import { getErrorMessage } from "../../../../../utils/errors.js";
import {
Drawer,
DrawerOverlay,
Expand Down Expand Up @@ -180,7 +177,7 @@
)}

<Container flex="column" gap="sm">
<Text size="sm">Pay with credit card</Text>
<Text size="sm">Pay with a debit card</Text>

Check warning on line 180 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx#L180

Added line #L180 was not covered by tests
<div>
<PayWithCreditCard
isLoading={fiatQuoteQuery.isLoading}
Expand Down Expand Up @@ -242,9 +239,14 @@
/>
</Text>
) : (
<Text color="danger" size="sm" center multiline>
{errorMsg.message || defaultMessage}
</Text>
<div>
<Text color="danger" size="xs" center multiline>
{errorMsg.title}
</Text>
<Text size="xs" center multiline>
{errorMsg.message}
</Text>
</div>

Check warning on line 249 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx#L242-L249

Added lines #L242 - L249 were not covered by tests
)}
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { CrossCircledIcon } from "@radix-ui/react-icons";
import { useState } from "react";
import { useMemo, useState } from "react";
import { trackPayEvent } from "../../../../../../../analytics/track/pay.js";
import type { Chain } from "../../../../../../../chains/types.js";
import type { ThirdwebClient } from "../../../../../../../client/client.js";
Expand All @@ -13,7 +12,6 @@
waitForReceipt,
} from "../../../../../../../transaction/actions/wait-for-tx-receipt.js";
import { useCustomTheme } from "../../../../../../core/design-system/CustomThemeProvider.js";
import { iconSize } from "../../../../../../core/design-system/index.js";
import { Spacer } from "../../../../components/Spacer.js";
import { Spinner } from "../../../../components/Spinner.js";
import { StepBar } from "../../../../components/StepBar.js";
Expand All @@ -25,6 +23,7 @@
import type { ERC20OrNativeToken } from "../../nativeToken.js";
import { Step } from "../Stepper.js";
import type { PayerInfo } from "../types.js";
import { ErrorText } from "./ErrorText.js";
import { SwapSummary } from "./SwapSummary.js";
import { addPendingTx } from "./pendingSwapTx.js";

Expand Down Expand Up @@ -59,13 +58,46 @@
const initialStep = needsApprovalStep ? "approval" : "swap";

const [step, setStep] = useState<"approval" | "swap">(initialStep);
const [error, setError] = useState<string | undefined>();

Check warning on line 61 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx#L61

Added line #L61 was not covered by tests
const [status, setStatus] = useState<
"pending" | "success" | "error" | "idle"
>("idle");

const receiver = props.quote.swapDetails.toAddress;
const sender = props.quote.swapDetails.fromAddress;

const uiErrorMessage = useMemo(() => {
if (step === "approval" && status === "error" && error) {
if (error.toLowerCase().includes("user rejected")) {
return {
title: "Failed to Approve",
message: "Your wallet rejected the approval request.",
};
}
return {
title: "Failed to Approve",
message:
"Your wallet failed to approve the transaction for an unknown reason. Please try again or contact support.",
};
}

Check warning on line 82 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx#L69-L82

Added lines #L69 - L82 were not covered by tests

if (step === "swap" && status === "error" && error) {
if (error.toLowerCase().includes("user rejected")) {
return {
title: "Failed to Confirm",
message: "Your wallet rejected the confirmation request.",
};
}
return {
title: "Failed to Confirm",
message:
"Your wallet failed to confirm the transaction for an unknown reason. Please try again or contact support.",
};
}

Check warning on line 96 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx#L84-L96

Added lines #L84 - L96 were not covered by tests

return undefined;
}, [error, step, status]);

Check warning on line 99 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx#L98-L99

Added lines #L98 - L99 were not covered by tests

return (
<Container p="lg">
<ModalHeader title={props.title} onBack={props.onBack} />
Expand Down Expand Up @@ -128,15 +160,12 @@
</>
)}

{status === "error" && (
{uiErrorMessage && (

Check warning on line 163 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx#L163

Added line #L163 was not covered by tests
<>
<Container flex="row" gap="xs" center="both" color="danger">
<CrossCircledIcon width={iconSize.sm} height={iconSize.sm} />
<Text color="danger" size="sm">
{step === "approval" ? "Failed to Approve" : "Failed to Confirm"}
</Text>
</Container>

<ErrorText
title={uiErrorMessage.title}
message={uiErrorMessage.message}
/>

Check warning on line 168 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx#L165-L168

Added lines #L165 - L168 were not covered by tests
<Spacer y="md" />
</>
)}
Expand Down Expand Up @@ -224,6 +253,7 @@
setStatus("idle");
} catch (e) {
console.error(e);
setError((e as Error).message);

Check warning on line 256 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx#L256

Added line #L256 was not covered by tests
setStatus("error");
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { CrossCircledIcon } from "@radix-ui/react-icons";
import { iconSize } from "../../../../../../core/design-system/index.js";
import { Container } from "../../../../components/basic.js";
import { Text } from "../../../../components/text.js";

export function ErrorText(props: {
title: string;
message: string;
}) {
return (
<Container gap="xxs" flex="column">
<Container flex="row" gap="xxs" center="both" color="danger">
<CrossCircledIcon width={iconSize.sm} height={iconSize.sm} />
<Text color="danger" size="sm">
{props.title}
</Text>
</Container>
<Text center size="xs">
{props.message}
</Text>
</Container>

Check warning on line 21 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ErrorText.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ErrorText.tsx#L9-L21

Added lines #L9 - L21 were not covered by tests
);
}

Check warning on line 23 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ErrorText.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ErrorText.tsx#L23

Added line #L23 was not covered by tests
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@
import type { PayUIOptions } from "../../../../../../core/hooks/connection/ConnectButtonProps.js";
import { useWalletBalance } from "../../../../../../core/hooks/others/useWalletBalance.js";
import { useBuyWithCryptoQuote } from "../../../../../../core/hooks/pay/useBuyWithCryptoQuote.js";
import {
defaultMessage,
getErrorMessage,
} from "../../../../../utils/errors.js";
import { getErrorMessage } from "../../../../../utils/errors.js";
import type { PayEmbedConnectOptions } from "../../../../PayEmbed.js";
import {
Drawer,
Expand Down Expand Up @@ -301,17 +298,25 @@
/>
</Text>
) : (
<Text color="danger" size="xs" center multiline>
{errorMsg.message || defaultMessage}
</Text>
<div>
<Text color="danger" size="xs" center multiline>
{errorMsg.title}
</Text>
<Text size="xs" center multiline>
{errorMsg.message}
</Text>
</div>

Check warning on line 308 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.tsx#L301-L308

Added lines #L301 - L308 were not covered by tests
)}
</div>
)}

{!errorMsg && isNotEnoughBalance && (
<div>
<Text color="danger" size="xs" center multiline>
Insufficient funds
Insufficient Funds
</Text>
<Text size="xs" center multiline>

Check warning on line 318 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.tsx#L317-L318

Added lines #L317 - L318 were not covered by tests
Select another token or pay with a debit card.
</Text>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ export function TokenSelectorScreen(props: {
>
<CardStackIcon width={iconSize.md} height={iconSize.md} />
<Text size="sm" color="primaryText">
Pay with credit card
Pay with a debit card
</Text>
</Container>
</Button>
Expand Down Expand Up @@ -362,7 +362,7 @@ function WalletRowWithBalances(props: {
) : (
<Container style={{ padding: spacing.sm }}>
<Text size="sm" color="secondaryText">
Insufficient funds
Insufficient Funds
</Text>
</Container>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CheckCircledIcon } from "@radix-ui/react-icons";
import { useQuery } from "@tanstack/react-query";
import { useState } from "react";
import { useMemo, useState } from "react";
import type { Chain } from "../../../../../../../chains/types.js";
import { getCachedChain } from "../../../../../../../chains/utils.js";
import type { ThirdwebClient } from "../../../../../../../client/client.js";
Expand Down Expand Up @@ -34,6 +34,7 @@
import { Step } from "../Stepper.js";
import type { PayerInfo } from "../types.js";
import { ConnectorLine } from "./ConfirmationScreen.js";
import { ErrorText } from "./ErrorText.js";
import { SwapSummary } from "./SwapSummary.js";

type TransferConfirmationScreenProps = {
Expand Down Expand Up @@ -109,6 +110,42 @@
refetchInterval: 30 * 1000,
});

const uiErrorMessage = useMemo(() => {
if (step === "approve" && status.id === "error" && status.error) {
if (status.error.toLowerCase().includes("user rejected")) {
return {
title: "Failed to Approve",
message: "Your wallet rejected the approval request.",
};
}
return {
title: "Failed to Approve",
message:
"Your wallet failed to approve the transaction for an unknown reason. Please try again or contact support.",
};
}

Check warning on line 126 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx#L113-L126

Added lines #L113 - L126 were not covered by tests

if (
(step === "transfer" || step === "execute") &&
status.id === "error" &&
status.error
) {
if (status.error.toLowerCase().includes("user rejected")) {
return {
title: "Failed to Confirm",
message: "Your wallet rejected the confirmation request.",
};
}
return {
title: "Failed to Confirm",
message:
"Your wallet failed to confirm the transaction for an unknown reason. Please try again or contact support.",
};
}

Check warning on line 144 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx#L128-L144

Added lines #L128 - L144 were not covered by tests

return undefined;
}, [step, status]);

Check warning on line 147 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx#L146-L147

Added lines #L146 - L147 were not covered by tests

if (transferQuery.isLoading) {
return (
<Container p="lg">
Expand Down Expand Up @@ -190,15 +227,12 @@
</>
)}

{status.id === "error" && (
{uiErrorMessage && (

Check warning on line 230 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx#L230

Added line #L230 was not covered by tests
<>
<Container flex="row" gap="xs" center="both" color="danger">
<Text color="danger" size="sm" style={{ textAlign: "center" }}>
{step === "transfer"
? `${status.error || "Failed to Transfer"}`
: "Failed to Execute"}
</Text>
</Container>
<ErrorText
title={uiErrorMessage.title}
message={uiErrorMessage.message}
/>

Check warning on line 235 in packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx#L232-L235

Added lines #L232 - L235 were not covered by tests
<Spacer y="md" />
</>
)}
Expand Down
15 changes: 11 additions & 4 deletions packages/thirdweb/src/react/web/utils/errors.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
type ApiError = {
code: string;
message?: string;
title: string;
message: string;
data?: {
minimumAmountUSDCents?: string;
requestedAmountUSDCents?: string;
Expand All @@ -9,19 +10,25 @@
};
};

export const defaultMessage = "Unable to get price quote";
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
export function getErrorMessage(err: any): ApiError {
if (typeof err.error === "object" && err.error.code) {
if (err.error.code === "MINIMUM_PURCHASE_AMOUNT") {
return {
code: "MINIMUM_PURCHASE_AMOUNT",
message: "Purchase amount is too low",
title: "Amount Too Low",
message:
"The requested amount is less than the minimum purchase. Try another provider or amount.",

Check warning on line 21 in packages/thirdweb/src/react/web/utils/errors.ts

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/utils/errors.ts#L19-L21

Added lines #L19 - L21 were not covered by tests
};
}
}

console.error(err);

Check warning on line 26 in packages/thirdweb/src/react/web/utils/errors.ts

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/utils/errors.ts#L26

Added line #L26 was not covered by tests

return {
code: "UNABLE_TO_GET_PRICE_QUOTE",
message: defaultMessage,
title: "Failed to Find Quote",
message:
"We couldn't get a quote for this token pair. Select another token or pay with a debit card.",

Check warning on line 32 in packages/thirdweb/src/react/web/utils/errors.ts

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/utils/errors.ts#L30-L32

Added lines #L30 - L32 were not covered by tests
};
}