|
1 |
| -'use server' |
2 |
| -import type { PublicClient, Chain } from 'viem' |
3 |
| -import { createPublicClient, http, extractChain } from 'viem' |
| 1 | +import type { PublicClient, Chain, Transport } from 'viem' |
| 2 | +import { createPublicClient, http, extractChain, fallback } from 'viem' |
4 | 3 | import * as chains from 'viem/chains'
|
5 | 4 |
|
6 | 5 | import { PUBLIC_CLIENTS_BY_CHAIN, rpcUrls } from '@/constants'
|
7 | 6 |
|
8 | 7 | const allChains = Object.values(chains)
|
9 | 8 | export type ChainId = (typeof allChains)[number]['id']
|
10 | 9 |
|
11 |
| -export const getPublicClient = async (chainId: ChainId): Promise<PublicClient> => { |
| 10 | +/** |
| 11 | + * Returns viem transport with fallback |
| 12 | + * |
| 13 | + * @see https://viem.sh/docs/clients/transports/fallback#fallback-transport |
| 14 | + */ |
| 15 | +export function getTransportWithFallback(chainId: ChainId): Transport { |
| 16 | + const providerUrls = rpcUrls[chainId] |
| 17 | + if (!providerUrls) { |
| 18 | + // If no premium providers are configured, viem will use a default one |
| 19 | + return http() |
| 20 | + } |
| 21 | + return fallback( |
| 22 | + providerUrls.map((u) => http(u)), |
| 23 | + // Viem checks the status of the provider every 60 seconds and notes latency |
| 24 | + // and stability. The provider that viem will try first depend on this |
| 25 | + // ranking |
| 26 | + { rank: { interval: 60_000 } } |
| 27 | + ) |
| 28 | +} |
| 29 | + |
| 30 | +export function getPublicClient(chainId: ChainId): PublicClient { |
12 | 31 | let client: PublicClient | undefined = PUBLIC_CLIENTS_BY_CHAIN[chainId]?.client
|
13 | 32 | if (client) return client
|
14 | 33 | const chain: Chain = extractChain({ chains: allChains, id: chainId })
|
15 | 34 | if (!chain) throw new Error(`No chain found for chainId ${chainId}`)
|
16 | 35 | return createPublicClient({
|
17 |
| - transport: http(rpcUrls[chainId][0]), |
| 36 | + transport: getTransportWithFallback(chainId), |
18 | 37 | chain,
|
19 | 38 | })
|
20 | 39 | }
|
0 commit comments