Skip to content

Commit 59bc1b6

Browse files
committed
SDK: Show error in BuyWidget and SwapWidget UI if fetching token details fails
1 parent f9283f3 commit 59bc1b6

File tree

5 files changed

+80
-25
lines changed

5 files changed

+80
-25
lines changed

.changeset/rare-buckets-fly.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
Show error in BuyWidget and SwapWidget UI if fetching token details fails

packages/thirdweb/src/react/web/ui/Bridge/FundWallet.tsx

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -251,11 +251,15 @@ export function FundWallet(props: FundWalletProps) {
251251
? tokenQuery.data.token
252252
: undefined,
253253
isFetching: tokenQuery.isFetching,
254+
isError:
255+
tokenQuery.isError ||
256+
tokenQuery.data?.type === "error" ||
257+
tokenQuery.data?.type === "unsupported_token",
254258
}
255259
: undefined
256260
}
257261
balance={{
258-
data: tokenBalanceQuery.data?.value,
262+
data: tokenBalanceQuery.data,
259263
isFetching: tokenBalanceQuery.isFetching,
260264
}}
261265
client={props.client}
@@ -279,6 +283,23 @@ export function FundWallet(props: FundWalletProps) {
279283

280284
<Spacer y="md" />
281285

286+
{(tokenQuery.isError ||
287+
tokenQuery.data?.type === "error" ||
288+
tokenQuery.data?.type === "unsupported_token") && (
289+
<div
290+
style={{
291+
border: `1px solid ${theme.colors.borderColor}`,
292+
borderRadius: radius.full,
293+
padding: spacing.xs,
294+
marginBottom: spacing.md,
295+
}}
296+
>
297+
<Text size="sm" color="danger" center>
298+
Failed to fetch token details
299+
</Text>
300+
</div>
301+
)}
302+
282303
{/* Continue Button */}
283304
{activeWalletInfo ? (
284305
<Button
@@ -373,6 +394,7 @@ function TokenSection(props: {
373394
| {
374395
data: TokenWithPrices | undefined;
375396
isFetching: boolean;
397+
isError: boolean;
376398
}
377399
| undefined;
378400
currency: SupportedFiatCurrency;
@@ -381,7 +403,14 @@ function TokenSection(props: {
381403
title: string;
382404
isConnected: boolean;
383405
balance: {
384-
data: bigint | undefined;
406+
data:
407+
| {
408+
value: bigint;
409+
decimals: number;
410+
symbol: string;
411+
name: string;
412+
}
413+
| undefined;
385414
isFetching: boolean;
386415
};
387416
onWalletClick: () => void;
@@ -565,17 +594,16 @@ function TokenSection(props: {
565594
<Text size="xs" color="secondaryText">
566595
Current Balance
567596
</Text>
568-
{props.balance.data === undefined ||
569-
props.selectedToken.data === undefined ? (
597+
{props.balance.data === undefined ? (
570598
<Skeleton height={fontSize.xs} width="100px" />
571599
) : (
572600
<Text size="xs" color="primaryText">
573601
{formatTokenAmount(
574-
props.balance.data,
575-
props.selectedToken.data.decimals,
602+
props.balance.data.value,
603+
props.balance.data.decimals,
576604
5,
577605
)}{" "}
578-
{props.selectedToken.data.symbol}
606+
{props.balance.data.symbol}
579607
</Text>
580608
)}
581609
</div>

packages/thirdweb/src/react/web/ui/Bridge/common/selected-token-button.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export function SelectedTokenButton(props: {
2121
| {
2222
data: TokenWithPrices | undefined;
2323
isFetching: boolean;
24+
isError: boolean;
2425
}
2526
| undefined;
2627
client: ThirdwebClient;
@@ -47,7 +48,7 @@ export function SelectedTokenButton(props: {
4748
{/* icons */}
4849
<Container relative color="secondaryText">
4950
{/* token icon */}
50-
{props.selectedToken ? (
51+
{props.selectedToken && !props.selectedToken.isError ? (
5152
<Img
5253
key={props.selectedToken?.data?.iconUri}
5354
src={
@@ -112,7 +113,7 @@ export function SelectedTokenButton(props: {
112113
</Container>
113114

114115
{/* token symbol and chain name */}
115-
{props.selectedToken ? (
116+
{props.selectedToken && !props.selectedToken.isError ? (
116117
<Container flex="column" style={{ gap: "3px" }}>
117118
{props.selectedToken?.isFetching ? (
118119
<Skeleton width="60px" height={fontSize.md} />

packages/thirdweb/src/react/web/ui/Bridge/common/token-query.ts

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ type TokenQueryResult =
88
| { type: "success"; token: TokenWithPrices }
99
| {
1010
type: "unsupported_token";
11+
}
12+
| {
13+
type: "error";
14+
message: string;
1115
};
1216

1317
export function useTokenQuery(params: {
@@ -22,24 +26,29 @@ export function useTokenQuery(params: {
2226
throw new Error("Chain ID is required");
2327
}
2428
const tokenAddress = params.tokenAddress || NATIVE_TOKEN_ADDRESS;
25-
const token = await getToken(
26-
params.client,
27-
tokenAddress,
28-
params.chainId,
29-
).catch((err) => {
30-
err.message.includes("not supported") ? undefined : Promise.reject(err);
31-
});
29+
try {
30+
const token = await getToken(
31+
params.client,
32+
tokenAddress,
33+
params.chainId,
34+
);
3235

33-
if (!token) {
3436
return {
35-
type: "unsupported_token",
37+
token: token,
38+
type: "success",
3639
};
40+
} catch (error) {
41+
if (error instanceof Error && error.message.includes("not supported")) {
42+
return {
43+
type: "unsupported_token",
44+
};
45+
} else {
46+
return {
47+
type: "error",
48+
message: error instanceof Error ? error.message : "Unknown error",
49+
};
50+
}
3751
}
38-
39-
return {
40-
token: token,
41-
type: "success",
42-
};
4352
},
4453
queryKey: ["bridge.getToken", params],
4554
refetchOnWindowFocus: false,

packages/thirdweb/src/react/web/ui/Bridge/swap-widget/swap-ui.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ function useTokenPrice(options: {
9696
);
9797
},
9898
refetchOnMount: false,
99+
retry: false,
99100
refetchOnWindowFocus: false,
100101
});
101102
}
@@ -320,6 +321,7 @@ export function SwapUI(props: SwapUIProps) {
320321
? {
321322
data: sellTokenQuery.data,
322323
isFetching: sellTokenQuery.isFetching,
324+
isError: sellTokenQuery.isError,
323325
}
324326
: undefined
325327
}
@@ -372,6 +374,7 @@ export function SwapUI(props: SwapUIProps) {
372374
? {
373375
data: buyTokenQuery.data,
374376
isFetching: buyTokenQuery.isFetching,
377+
isError: buyTokenQuery.isError,
375378
}
376379
: undefined
377380
}
@@ -389,7 +392,9 @@ export function SwapUI(props: SwapUIProps) {
389392
/>
390393

391394
{/* error message */}
392-
{preparedResultQuery.error ? (
395+
{preparedResultQuery.error ||
396+
buyTokenQuery.isError ||
397+
sellTokenQuery.isError ? (
393398
<Text
394399
size="sm"
395400
color="danger"
@@ -398,7 +403,13 @@ export function SwapUI(props: SwapUIProps) {
398403
paddingBlock: spacing.md,
399404
}}
400405
>
401-
Failed to get a quote
406+
{preparedResultQuery.error
407+
? "Failed to get a quote"
408+
: buyTokenQuery.isError
409+
? "Failed to fetch buy token details"
410+
: sellTokenQuery.isError
411+
? "Failed to fetch sell token details"
412+
: "Failed to get a quote"}
402413
</Text>
403414
) : (
404415
<Spacer y="md" />
@@ -626,6 +637,7 @@ function TokenSection(props: {
626637
| {
627638
data: TokenWithPrices | undefined;
628639
isFetching: boolean;
640+
isError: boolean;
629641
}
630642
| undefined;
631643
currency: SupportedFiatCurrency;

0 commit comments

Comments
 (0)