Skip to content

Commit 4c5696e

Browse files
[SDK] Add caching and timeout for fetching capabilities (#8485)
1 parent 9e43da4 commit 4c5696e

File tree

4 files changed

+55
-9
lines changed

4 files changed

+55
-9
lines changed

.changeset/twelve-grapes-drop.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+
Add caching and timeout for fetching capabilities

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

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,16 @@ export function useStepExecutor(
383383

384384
// get tx hash
385385
const callsStatus = await waitForCallsReceipt(result);
386+
387+
if (callsStatus.status === "failure") {
388+
throw new ApiError({
389+
code: "UNKNOWN_ERROR",
390+
message:
391+
"Transaction failed. Please try a different payment token or amount.",
392+
statusCode: 500,
393+
});
394+
}
395+
386396
const lastReceipt =
387397
callsStatus.receipts?.[callsStatus.receipts.length - 1];
388398

@@ -714,14 +724,41 @@ export function useStepExecutor(
714724
};
715725
}
716726

717-
async function supportsAtomic(account: Account, chainId: number) {
727+
// Cache for supportsAtomic results, keyed by `${accountAddress}_${chainId}`
728+
const supportsAtomicCache = new Map<string, boolean>();
729+
730+
async function supportsAtomic(
731+
account: Account,
732+
chainId: number,
733+
): Promise<boolean> {
734+
const cacheKey = `${account.address}_${chainId}`;
735+
const cached = supportsAtomicCache.get(cacheKey);
736+
if (cached !== undefined) {
737+
return cached;
738+
}
739+
718740
const capabilitiesFn = account.getCapabilities;
719741
if (!capabilitiesFn) {
742+
supportsAtomicCache.set(cacheKey, false);
743+
return false;
744+
}
745+
746+
try {
747+
// 5s max timeout for capabilities fetch
748+
const capabilities = await Promise.race([
749+
capabilitiesFn({ chainId }),
750+
new Promise<never>((_, reject) =>
751+
setTimeout(() => reject(new Error("Timeout")), 5000),
752+
),
753+
]);
754+
const atomic = capabilities[chainId]?.atomic as
755+
| { status: "supported" | "ready" | "unsupported" }
756+
| undefined;
757+
const result = atomic?.status === "supported" || atomic?.status === "ready";
758+
supportsAtomicCache.set(cacheKey, result);
759+
return result;
760+
} catch (error) {
761+
// Timeout or error fetching capabilities, assume not supported, but dont cache the result
720762
return false;
721763
}
722-
const capabilities = await capabilitiesFn({ chainId });
723-
const atomic = capabilities[chainId]?.atomic as
724-
| { status: "supported" | "ready" | "unsupported" }
725-
| undefined;
726-
return atomic?.status === "supported" || atomic?.status === "ready";
727764
}

packages/thirdweb/src/wallets/eip5792/wait-for-calls-receipt.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,9 @@ export function waitForCallsReceipt(
9494
resolve(result);
9595
return;
9696
}
97-
} catch {
98-
// noop, we'll try again on the next blocks
97+
} catch (error) {
98+
// we'll try again on the next blocks
99+
console.error("waitForCallsReceipt error", error);
99100
}
100101
},
101102
});

packages/thirdweb/src/wallets/injected/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,10 @@ function createAccount({
378378
try {
379379
const result = await provider.request({
380380
method: "wallet_getCapabilities",
381-
params: [getAddress(account.address)],
381+
params: [
382+
getAddress(account.address),
383+
chainIdFilter ? [numberToHex(chainIdFilter)] : undefined,
384+
],
382385
});
383386
return toGetCapabilitiesResult(result, chainIdFilter);
384387
} catch (error: unknown) {

0 commit comments

Comments
 (0)