Skip to content

Commit f48d800

Browse files
[SDK] Optimize payment token fetching in payment widgets (#7536)
1 parent 20e323d commit f48d800

File tree

6 files changed

+151
-154
lines changed

6 files changed

+151
-154
lines changed

.changeset/happy-pans-sneeze.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+
Optimize fetching payment tokens in payment widgets

packages/thirdweb/src/bridge/Chains.ts

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { ThirdwebClient } from "../client/client.js";
22
import { getThirdwebBaseUrl } from "../utils/domains.js";
33
import { getClientFetch } from "../utils/fetch.js";
4+
import { withCache } from "../utils/promise/withCache.js";
45
import type { Chain } from "./types/Chain.js";
56
import { ApiError } from "./types/Errors.js";
67

@@ -54,22 +55,30 @@ import { ApiError } from "./types/Errors.js";
5455
export async function chains(options: chains.Options): Promise<chains.Result> {
5556
const { client } = options;
5657

57-
const clientFetch = getClientFetch(client);
58-
const url = new URL(`${getThirdwebBaseUrl("bridge")}/v1/chains`);
58+
return withCache(
59+
async () => {
60+
const clientFetch = getClientFetch(client);
61+
const url = new URL(`${getThirdwebBaseUrl("bridge")}/v1/chains`);
5962

60-
const response = await clientFetch(url.toString());
61-
if (!response.ok) {
62-
const errorJson = await response.json();
63-
throw new ApiError({
64-
code: errorJson.code || "UNKNOWN_ERROR",
65-
correlationId: errorJson.correlationId || undefined,
66-
message: errorJson.message || response.statusText,
67-
statusCode: response.status,
68-
});
69-
}
63+
const response = await clientFetch(url.toString());
64+
if (!response.ok) {
65+
const errorJson = await response.json();
66+
throw new ApiError({
67+
code: errorJson.code || "UNKNOWN_ERROR",
68+
correlationId: errorJson.correlationId || undefined,
69+
message: errorJson.message || response.statusText,
70+
statusCode: response.status,
71+
});
72+
}
7073

71-
const { data }: { data: Chain[] } = await response.json();
72-
return data;
74+
const { data }: { data: Chain[] } = await response.json();
75+
return data;
76+
},
77+
{
78+
cacheKey: "bridge-chains",
79+
cacheTime: 1000 * 60 * 60 * 1, // 1 hours
80+
},
81+
);
7382
}
7483

7584
export declare namespace chains {

packages/thirdweb/src/chains/types.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,6 @@ export type ChainMetadata = {
8888
stackType: string;
8989
};
9090

91-
/**
92-
* @chain
93-
*/
94-
export type ChainService = {
95-
service: string;
96-
enabled: boolean;
97-
};
98-
9991
/**
10092
* @chain
10193
*/

packages/thirdweb/src/chains/utils.ts

Lines changed: 10 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import type {
77
Chain,
88
ChainMetadata,
99
ChainOptions,
10-
ChainService,
1110
LegacyChain,
1211
} from "./types.js";
1312

@@ -323,62 +322,22 @@ export function getChainMetadata(chain: Chain): Promise<ChainMetadata> {
323322
);
324323
}
325324

326-
type FetchChainServiceResponse =
327-
| {
328-
data: {
329-
services: ChainService[];
330-
};
331-
error?: never;
332-
}
333-
| {
334-
data?: never;
335-
error: unknown;
336-
};
337-
338-
/**
339-
* Retrieves a list of services available on a given chain
340-
* @param chain - The chain object containing the chain ID.
341-
* @returns A Promise that resolves to chain services.
342-
* @throws If there is an error fetching the chain services.
343-
* @example
344-
* ```ts
345-
* const chain = defineChain({ id: 1 });
346-
* const chainServices = await getChainServices(chain);
347-
* console.log(chainServices);
348-
* ```
349-
* @chain
350-
*/
351-
export function getChainServices(chain: Chain): Promise<ChainService[]> {
352-
const chainId = chain.id;
325+
export async function getInsightEnabledChainIds(): Promise<number[]> {
353326
return withCache(
354327
async () => {
355-
try {
356-
const res = await fetch(
357-
`https://api.thirdweb.com/v1/chains/${chainId}/services`,
328+
const res = await fetch(
329+
`https://api.thirdweb.com/v1/chains/services?service=insight`,
330+
);
331+
if (!res.ok) {
332+
throw new Error(
333+
`Failed to fetch services. ${res.status} ${res.statusText}`,
358334
);
359-
if (!res.ok) {
360-
throw new Error(
361-
`Failed to fetch services for chainId ${chainId}. ${res.status} ${res.statusText}`,
362-
);
363-
}
364-
365-
const response = (await res.json()) as FetchChainServiceResponse;
366-
if (response.error) {
367-
throw new Error(`Failed to fetch services for chainId ${chainId}`);
368-
}
369-
if (!response.data) {
370-
throw new Error(`Failed to fetch services for chainId ${chainId}`);
371-
}
372-
373-
const services = response.data.services;
374-
375-
return services;
376-
} catch {
377-
throw new Error(`Failed to fetch services for chainId ${chainId}`);
378335
}
336+
const response = (await res.json()) as { data: Record<number, boolean> };
337+
return Object.keys(response.data).map((chainId) => Number(chainId));
379338
},
380339
{
381-
cacheKey: `chain:${chainId}:services`,
340+
cacheKey: `chain:insight-enabled`,
382341
cacheTime: 24 * 60 * 60 * 1000, // 1 day
383342
},
384343
);
Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,21 @@
11
import type { Chain } from "../chains/types.js";
2-
import { getChainServices } from "../chains/utils.js";
2+
import { getInsightEnabledChainIds } from "../chains/utils.js";
33

44
export async function assertInsightEnabled(chains: Chain[]) {
5-
const chainData = await Promise.all(
6-
chains.map((chain) =>
7-
isInsightEnabled(chain).then((enabled) => ({
8-
chain,
9-
enabled,
10-
})),
11-
),
12-
);
13-
14-
const insightEnabled = chainData.every((c) => c.enabled);
5+
const chainIds = await getInsightEnabledChainIds();
6+
const insightEnabled = chains.every((c) => chainIds.includes(c.id));
157

168
if (!insightEnabled) {
179
throw new Error(
18-
`Insight is not available for chains ${chainData
19-
.filter((c) => !c.enabled)
20-
.map((c) => c.chain.id)
10+
`Insight is not available for chains ${chains
11+
.filter((c) => !chainIds.includes(c.id))
12+
.map((c) => c.id)
2113
.join(", ")}`,
2214
);
2315
}
2416
}
2517

2618
export async function isInsightEnabled(chain: Chain) {
27-
const chainData = await getChainServices(chain);
28-
return chainData.some((c) => c.service === "insight" && c.enabled);
19+
const chainIds = await getInsightEnabledChainIds();
20+
return chainIds.includes(chain.id);
2921
}

0 commit comments

Comments
 (0)