UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

157 lines 6.53 kB
import { objFilter, objMap, pick, rootLogger, } from '@hyperlane-xyz/utils'; import { multiProtocolTestChainMetadata } from '../consts/testChains.js'; import { ChainMetadataManager } from '../metadata/ChainMetadataManager.js'; import { MultiProvider } from './MultiProvider.js'; import { PROTOCOL_TO_DEFAULT_PROVIDER_TYPE, ProviderType, } from './ProviderType.js'; import { defaultProviderBuilderMap, } from './providerBuilders.js'; import { estimateTransactionFee, } from './transactionFeeEstimators.js'; /** * A version of MultiProvider that can support different * provider types across different protocol types. * * This uses a different interface for provider/signer related methods * so it isn't strictly backwards compatible with MultiProvider. * * Unlike MultiProvider, this class does not support signer/signing methods (yet). * @typeParam MetaExt - Extra metadata fields for chains (such as contract addresses) */ export class MultiProtocolProvider extends ChainMetadataManager { options; // Chain name -> provider type -> provider providers; // Chain name -> provider type -> signer signers = {}; // TODO signer support providerBuilders; logger; constructor(chainMetadata, options = {}) { super(chainMetadata, options); this.options = options; this.logger = options?.logger || rootLogger.child({ module: 'MultiProtocolProvider', }); this.providers = options.providers || {}; this.providerBuilders = options.providerBuilders || defaultProviderBuilderMap; } static fromMultiProvider(mp, options = {}) { const newMp = new MultiProtocolProvider(mp.metadata, options); const typedProviders = objMap(mp.providers, (_, provider) => ({ type: ProviderType.EthersV5, provider, })); newMp.setProviders(typedProviders); return newMp; } toMultiProvider(options) { const newMp = new MultiProvider(this.metadata, options); const providers = objMap(this.providers, (_, typeToProviders) => typeToProviders[ProviderType.EthersV5]?.provider); const filteredProviders = objFilter(providers, (_, p) => !!p); newMp.setProviders(filteredProviders); return newMp; } extendChainMetadata(additionalMetadata) { const newMetadata = super.extendChainMetadata(additionalMetadata).metadata; const newMp = new MultiProtocolProvider(newMetadata, { ...this.options, providers: this.providers, }); return newMp; } tryGetProvider(chainNameOrId, type) { const metadata = this.tryGetChainMetadata(chainNameOrId); if (!metadata) return null; const { protocol, name, chainId, rpcUrls } = metadata; type = type || PROTOCOL_TO_DEFAULT_PROVIDER_TYPE[protocol]; if (!type) return null; if (this.providers[name]?.[type]) return this.providers[name][type]; const builder = this.providerBuilders[type]; if (!rpcUrls.length || !builder) return null; const provider = builder(rpcUrls, chainId); this.providers[name] ||= {}; this.providers[name][type] = provider; return provider; } getProvider(chainNameOrId, type) { const provider = this.tryGetProvider(chainNameOrId, type); if (!provider) throw new Error(`No provider available for ${chainNameOrId}`); return provider; } getSpecificProvider(chainNameOrId, type) { const provider = this.getProvider(chainNameOrId, type); if (provider.type !== type) throw new Error(`Invalid provider type, expected ${type} but found ${provider.type}`); return provider.provider; } getEthersV5Provider(chainNameOrId) { return this.getSpecificProvider(chainNameOrId, ProviderType.EthersV5); } getViemProvider(chainNameOrId) { return this.getSpecificProvider(chainNameOrId, ProviderType.Viem); } getSolanaWeb3Provider(chainNameOrId) { return this.getSpecificProvider(chainNameOrId, ProviderType.SolanaWeb3); } getCosmJsProvider(chainNameOrId) { return this.getSpecificProvider(chainNameOrId, ProviderType.CosmJs); } getCosmJsWasmProvider(chainNameOrId) { return this.getSpecificProvider(chainNameOrId, ProviderType.CosmJsWasm); } getCosmJsNativeProvider(chainNameOrId) { return this.getSpecificProvider(chainNameOrId, ProviderType.CosmJsNative); } getStarknetProvider(chainNameOrId) { return this.getSpecificProvider(chainNameOrId, ProviderType.Starknet); } setProvider(chainNameOrId, provider) { const chainName = this.getChainName(chainNameOrId); this.providers[chainName] ||= {}; this.providers[chainName][provider.type] = provider; return provider; } setProviders(providers) { for (const chain of Object.keys(providers)) { this.setProvider(chain, providers[chain]); } } estimateTransactionFee({ chainNameOrId, transaction, sender, senderPubKey, }) { const provider = this.getProvider(chainNameOrId, transaction.type); const chainMetadata = this.getChainMetadata(chainNameOrId); return estimateTransactionFee({ transaction, provider, chainMetadata, sender, senderPubKey, }); } intersect(chains, throwIfNotSubset = false) { const { intersection, result } = super.intersect(chains, throwIfNotSubset); const multiProvider = new MultiProtocolProvider(result.metadata, { ...this.options, providers: pick(this.providers, intersection), }); return { intersection, result: multiProvider }; } /** * Creates a MultiProvider for test networks */ static createTestMultiProtocolProvider(metadata = multiProtocolTestChainMetadata, providers = {}) { const mp = new MultiProtocolProvider(metadata); const providerMap = {}; for (const [protocol, provider] of Object.entries(providers)) { const chains = Object.values(metadata).filter((m) => m.protocol === protocol); chains.forEach((c) => (providerMap[c.name] = provider)); } mp.setProviders(providerMap); return mp; } } //# sourceMappingURL=MultiProtocolProvider.js.map