import { ChainDisconnectedError, createTransport, type EIP1193Parameters, type EIP1193Provider, type EIP1193RequestFn, hexToNumber, ProviderDisconnectedError, type TransportConfig, type WalletRpcSchema, withRetry, withTimeout, } from 'viem' import type { Connector, Transport } from '../createConfig.js' export type ConnectorTransportConfig = { /** The key of the transport. */ key?: TransportConfig['key'] | undefined /** The name of the transport. */ name?: TransportConfig['name'] | undefined /** The max number of times to retry. */ retryCount?: TransportConfig['retryCount'] | undefined /** The base delay (in ms) between retries. */ retryDelay?: TransportConfig['retryDelay'] | undefined } export type ConnectorTransport = Transport export function unstable_connector( connector: Pick, config: ConnectorTransportConfig = {}, ): Transport<'connector'> { const { type } = connector const { key = 'connector', name = 'Connector', retryDelay } = config return (parameters) => { const { chain, connectors } = parameters const retryCount = config.retryCount ?? parameters.retryCount const request: EIP1193RequestFn = async ({ method, params }) => { const connector = connectors?.getState().find((c) => c.type === type) if (!connector) throw new ProviderDisconnectedError( new Error( `Could not find connector of type "${type}" in \`connectors\` passed to \`createConfig\`.`, ), ) const provider = (await connector.getProvider({ chainId: chain?.id, })) as EIP1193Provider | undefined if (!provider) throw new ProviderDisconnectedError( new Error('Provider is disconnected.'), ) // We are applying a retry & timeout strategy here as some injected wallets (e.g. MetaMask) fail to // immediately resolve a JSON-RPC request on page load. const chainId = hexToNumber( await withRetry(() => withTimeout(() => provider.request({ method: 'eth_chainId' }), { timeout: 100, }), ), ) if (chain && chainId !== chain.id) throw new ChainDisconnectedError( new Error( `The current chain of the connector (id: ${chainId}) does not match the target chain for the request (id: ${chain.id} – ${chain.name}).`, ), ) const body = { method, params } as EIP1193Parameters return provider.request(body) } return createTransport({ key, name, request, retryCount, retryDelay, type: 'connector', }) } }