Skip to content

Commit 170c377

Browse files
Handle token balance retrieval failures (#7600)
Co-authored-by: Cursor Agent <[email protected]>
1 parent 4cbf671 commit 170c377

File tree

2 files changed

+62
-13
lines changed

2 files changed

+62
-13
lines changed

.changeset/fallback-native-balance.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
Add fallback mechanism to usePaymentMethods hook for getOwnedTokens failures
6+
7+
When getOwnedTokens batches fail in the usePaymentMethods hook, the system now falls back to getting native token balances for each chain using getWalletBalance. This ensures users can still access their native tokens as payment methods even when the insight API is experiencing issues, providing a more resilient user experience.
8+
9+
The fallback mechanism:
10+
- Catches getOwnedTokens failures and logs warnings
11+
- Falls back to native balance fetching using getWalletBalance for each chain
12+
- Transforms results to match the expected format
13+
- Continues normal processing flow seamlessly

packages/thirdweb/src/react/core/hooks/usePaymentMethods.ts

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import type { ThirdwebClient } from "../../../client/client.js";
1010
import { getOwnedTokens } from "../../../insight/get-tokens.js";
1111
import { toTokens } from "../../../utils/units.js";
1212
import type { Wallet } from "../../../wallets/interfaces/wallet.js";
13+
import {
14+
type GetWalletBalanceResult,
15+
getWalletBalance,
16+
} from "../../../wallets/utils/getWalletBalance.js";
1317
import type { PaymentMethod } from "../machines/paymentMachine.js";
1418
import { useActiveWallet } from "./wallets/useActiveWallet.js";
1519

@@ -80,16 +84,42 @@ export function usePaymentMethods(options: {
8084
const limit = 500;
8185

8286
while (true) {
83-
const batch = await getOwnedTokens({
84-
chains: insightEnabledChains.map((c) => getCachedChain(c.chainId)),
85-
client,
86-
ownerAddress: wallet.getAccount()?.address || "",
87-
queryOptions: {
88-
limit,
89-
metadata: "false",
90-
page,
91-
},
92-
});
87+
let batch: GetWalletBalanceResult[];
88+
try {
89+
batch = await getOwnedTokens({
90+
chains: insightEnabledChains.map((c) => getCachedChain(c.chainId)),
91+
client,
92+
ownerAddress: wallet.getAccount()?.address || "",
93+
queryOptions: {
94+
limit,
95+
metadata: "false",
96+
page,
97+
},
98+
});
99+
} catch (error) {
100+
// If the batch fails, fall back to getting native balance for each chain
101+
console.warn(`Failed to get owned tokens for batch ${page}:`, error);
102+
103+
const chainsInBatch = insightEnabledChains.map((c) =>
104+
getCachedChain(c.chainId),
105+
);
106+
const nativeBalances = await Promise.allSettled(
107+
chainsInBatch.map(async (chain) => {
108+
const balance = await getWalletBalance({
109+
address: wallet.getAccount()?.address || "",
110+
chain,
111+
client,
112+
});
113+
return balance;
114+
}),
115+
);
116+
117+
// Transform successful native balances into the same format as getOwnedTokens results
118+
batch = nativeBalances
119+
.filter((result) => result.status === "fulfilled")
120+
.map((result) => result.value)
121+
.filter((balance) => balance.value > 0n);
122+
}
93123

94124
if (batch.length === 0) {
95125
break;
@@ -126,7 +156,9 @@ export function usePaymentMethods(options: {
126156

127157
// Add destination token if included
128158
if (includeDestinationToken) {
129-
const tokenKey = `${destinationToken.chainId}-${destinationToken.address.toLowerCase()}`;
159+
const tokenKey = `${
160+
destinationToken.chainId
161+
}-${destinationToken.address.toLowerCase()}`;
130162
allValidOriginTokens.set(tokenKey, destinationToken);
131163
}
132164

@@ -155,7 +187,9 @@ export function usePaymentMethods(options: {
155187
) {
156188
continue;
157189
}
158-
const tokenKey = `${route.originToken.chainId}-${route.originToken.address.toLowerCase()}`;
190+
const tokenKey = `${
191+
route.originToken.chainId
192+
}-${route.originToken.address.toLowerCase()}`;
159193
allValidOriginTokens.set(tokenKey, route.originToken);
160194
}
161195
} catch (error) {
@@ -169,7 +203,9 @@ export function usePaymentMethods(options: {
169203
const validOwnedTokens: OwnedTokenWithQuote[] = [];
170204

171205
for (const ownedToken of allOwnedTokens) {
172-
const tokenKey = `${ownedToken.originToken.chainId}-${ownedToken.originToken.address.toLowerCase()}`;
206+
const tokenKey = `${
207+
ownedToken.originToken.chainId
208+
}-${ownedToken.originToken.address.toLowerCase()}`;
173209
const validOriginToken = allValidOriginTokens.get(tokenKey);
174210

175211
if (validOriginToken) {

0 commit comments

Comments
 (0)