def use_default_provider( self, provider_settings: Optional[Dict] = None ) -> ProviderContextManager: """ Temporarily connect and use the default provider. When entering the context, it calls method :meth:`ape.api.providers.ProviderAPI.connect` and when exiting, it calls method :meth:`ape.api.providers.ProviderAPI.disconnect`. **NOTE**: If multiple providers exist, uses whatever was "first" registered. Usage example:: from ape import networks mainnet = networks.ethereum.mainnet # An instance of NetworkAPI with mainnet.use_default_provider(): ... Args: provider_settings (dict, optional): Settings to override the provider. Returns: :class:`~ape.api.networks.ProviderContextManager` """ if self.default_provider: return self.use_provider(self.default_provider, provider_settings=provider_settings) raise NetworkError(f"No providers for network '{self.name}'.")
def networks(self) -> Dict[str, "NetworkAPI"]: """ A dictionary of network names mapped to their API implementation. Returns: Dict[str, :class:`~ape.api.networks.NetworkAPI`] """ networks = {} for _, (ecosystem_name, network_name, network_class) in self.plugin_manager.networks: if ecosystem_name == self.name: network_folder = self.data_folder / network_name networks[network_name] = network_class( name=network_name, ecosystem=self, data_folder=network_folder, request_header=self.request_header, ) if len(networks) > 0: return networks else: raise NetworkError("No networks found")
def _validate_filter(arg: Optional[Union[List[str], str]], options: Set[str]): filters = arg or [] if isinstance(filters, str): filters = [filters] for _filter in filters: if _filter not in options: raise NetworkError(f"Unknown option '{_filter}'.") return filters
def get_provider( self, provider_name: Optional[str] = None, provider_settings: dict = None, ): """ Get a provider for the given name. If given ``None``, returns the default provider. Args: provider_name (str, optional): The name of the provider to get. Defaults to ``None``. When ``None``, returns the default provider. provider_settings (dict, optional): Settings to apply to the provider. Defaults to ``None``. Returns: :class:`~ape.api.providers.ProviderAPI` """ provider_name = provider_name or self.default_provider if not provider_name: raise NetworkError( f"No default provider for network '{self.name}'. " f"Set one in your ape-config.yaml:\n" f"\n{self.ecosystem.name}:" f"\n {self.name}:" f"\n default_provider: <DEFAULT_PROVIDER>") provider_settings = provider_settings or {} if ":" in provider_name: # NOTE: Shortcut that allows `--network ecosystem:network:http://...` to work provider_settings["uri"] = provider_name provider_name = provider_name.split(":")[0] if provider_name in self.providers: return self.providers[provider_name]( provider_settings=provider_settings) else: message = f"'{provider_name}' is not a valid provider for network '{self.name}'" raise NetworkError(message)
def set_default_network(self, network_name: str): """ Change the default network. Raises: :class:`~ape.exceptions.NetworkError`: When the network does not exist. Args: network_name (str): The name of the default network to switch to. """ if network_name in self.networks: self._default_network = network_name else: message = f"'{network_name}' is not a valid network for ecosystem '{self.name}'." raise NetworkError(message)
def set_default_provider(self, provider_name: str): """ Change the default provider. Raises: :class:`~ape.exceptions.NetworkError`: When the given provider is not found. Args: provider_name (str): The name of the provider to switch to. """ if provider_name in self.providers: self._default_provider = provider_name else: raise NetworkError( f"Provider '{provider_name}' not found in network '{self.name}'." )
def set_default_ecosystem(self, ecosystem_name: str): """ Change the default ecosystem. Raises: :class:`~ape.exceptions.NetworkError`: When the given ecosystem name is unknown. Args: ecosystem_name (str): The name of the ecosystem to set as the default. """ if ecosystem_name in self.ecosystem_names: self._default = ecosystem_name else: raise NetworkError( f"Ecosystem '{ecosystem_name}' is not a registered ecosystem.")
def get_ecosystem(self, ecosystem_name: str) -> EcosystemAPI: """ Get the ecosystem for the given name. Args: ecosystem_name (str): The name of the ecosystem to get. Raises: :class:`~ape.exceptions.NetworkError`: When the ecosystem is not found. Returns: :class:`~ape.api.networks.EcosystemAPI` """ if ecosystem_name not in self.ecosystem_names: raise NetworkError(f"Ecosystem '{ecosystem_name}' not found.") return self.ecosystems[ecosystem_name]
def __getitem__(self, ecosystem_name: str) -> EcosystemAPI: """ Get an ecosystem by name. Raises: :class:`~ape.exceptions.NetworkError`: When the given ecosystem name is unknown. Args: ecosystem_name (str): The name of the ecosystem to get. Returns: :class:`~ape.api.networks.EcosystemAPI` """ if ecosystem_name not in self.ecosystems: raise NetworkError(f"Unknown ecosystem '{ecosystem_name}'.") return self.ecosystems[ecosystem_name]
def add_network(self, network_name: str, network: "NetworkAPI"): """ Attach a new network to an ecosystem (e.g. L2 networks like Optimism). Raises: :class:`ape.exceptions.NetworkError`: When the network already exists. Args: network_name (str): The name of the network to add. Returns: :class:`~ape.api.networks.NetworkAPI` """ if network_name in self.networks: raise NetworkError( f"Unable to overwrite existing network '{network_name}'.") else: self.networks[network_name] = network
def default_ecosystem(self) -> EcosystemAPI: """ The default ecosystem. Call :meth:`~ape.managers.networks.NetworkManager.set_default_ecosystem` to change the default ecosystem. If a default is not set and there is only a single ecosystem installed, such as Ethereum, then get that ecosystem. """ ecosystems = self.ecosystems # NOTE: Also will load defaults if self._default: return ecosystems[self._default] # If explicit default is not set, use first registered ecosystem elif len(ecosystems) > 0: return list(ecosystems.values())[0] else: raise NetworkError("No ecosystems installed.")
def chain_id(self) -> int: """ The ID of the blockchain. **NOTE**: Unless overridden, returns same as :py:attr:`ape.api.providers.ProviderAPI.chain_id`. Returns: int """ provider = self.ecosystem.network_manager.active_provider if not provider: message = ( "Cannot determine 'chain_id', please make sure you are connected to a provider." ) raise NetworkError(message) return provider.chain_id
def get_provider_from_choice( self, network_choice: Optional[str] = None, provider_settings: Optional[Dict] = None, ) -> ProviderAPI: """ Get a :class:`~ape.api.providers.ProviderAPI` from a network choice. A network choice is any value returned from :meth:`~ape.managers.networks.NetworkManager.get_network_choices`. Use the CLI command ``ape networks list`` to list all the possible network combinations. Raises: :class:`~ape.exceptions.NetworkError`: When the given network choice does not match any known network. Args: network_choice (str, optional): The network choice (see :meth:`~ape.managers.networks.NetworkManager.get_network_choices`). Defaults to the default ecosystem, network, and provider combination. provider_settings (dict, optional): Settings for the provider. Defaults to None. Returns: :class:`~ape.api.providers.ProviderAPI` """ if network_choice is None: default_network = self.default_ecosystem.default_network return self.default_ecosystem[default_network].get_provider( provider_settings=provider_settings) selections = network_choice.split(":") # NOTE: Handle case when URI is passed e.g. "http://..." if len(selections) > 3: selections[2] = ":".join(selections[2:]) if selections == network_choice or len(selections) == 1: # Either split didn't work (in which case it matches the start) # or there was nothing after the ``:`` (e.g. "ethereum:") ecosystem = self.get_ecosystem(selections[0] or self.default_ecosystem.name) # By default, the "local" network should be specified for # any ecosystem (this should not correspond to a production chain) default_network = ecosystem.default_network return ecosystem[default_network].get_provider( provider_settings=provider_settings) elif len(selections) == 2: # Only ecosystem and network were specified, not provider ecosystem_name, network_name = selections ecosystem = self.get_ecosystem(ecosystem_name or self.default_ecosystem.name) network = ecosystem.get_network(network_name or ecosystem.default_network) return network.get_provider(provider_settings=provider_settings) elif len(selections) == 3: # Everything is specified, use specified provider for ecosystem and network ecosystem_name, network_name, provider_name = selections ecosystem = self.get_ecosystem(ecosystem_name or self.default_ecosystem.name) network = ecosystem.get_network(network_name or ecosystem.default_network) return network.get_provider(provider_name=provider_name, provider_settings=provider_settings) else: # NOTE: Might be unreachable raise NetworkError("Invalid network selection.")
def __post_init__(self): if len(self.networks) == 0: raise NetworkError("Must define at least one network in ecosystem")