Skip to content

Commit

Permalink
fix: configuring custom ecosystems (#1910)
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Feb 2, 2024
1 parent 8b53652 commit a3e14db
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 6 deletions.
16 changes: 16 additions & 0 deletions docs/userguides/networks.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,22 @@ ethereum:

For a full list of network configurations like this (for both custom and plugin-based networks), [see this section](#configuring-networks).

**NOTE**: This also works if configuring a custom ecosystem.
If using a custom ecosystem, use the custom ecosystem name as the top-level config key instead:

```yaml
networks:
custom:
- name: mainnet
ecosystem: shibarium
base_ecosystem_plugin: polygon # Closest base class.
chain_id: 109 # This must be correct or txns will fail.
shibarium:
mainnet:
default_transaction_type: 0 # Use static-fee transactions for Shibarium.
```

### Custom Networks by CLI

Ape also lets you connect to custom networks on-the-fly!
Expand Down
22 changes: 22 additions & 0 deletions src/ape/managers/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,15 @@ def _plugin_configs(self) -> Dict[str, PluginConfig]:
}
)

ethereum_config_cls = None
for plugin_name, config_class in self.plugin_manager.config_class:
# `or {}` to handle the case when the empty config is `None`.
user_override = user_config.pop(plugin_name, {}) or {}

# Store ethereum's class for custom network config loading.
if plugin_name == "ethereum":
ethereum_config_cls = config_class

if config_class != ConfigDict:
# NOTE: Will raise if improperly provided keys
config = config_class.from_overrides(user_override) # type: ignore
Expand All @@ -223,6 +229,22 @@ def _plugin_configs(self) -> Dict[str, PluginConfig]:

configs[plugin_name] = config

# Load custom ecosystem configs.
if ethereum_config_cls is not None and user_config:
custom_ecosystem_names = {
x.get("ecosystem")
for x in configs.get("networks", {}).get("custom", [])
if x.get("ecosystem") and x["ecosystem"] not in configs
}
custom_ecosystem_configs = {
n: cfg for n, cfg in user_config.items() if n in custom_ecosystem_names
}

for ecosystem_name, cfg in custom_ecosystem_configs.items():
config = ethereum_config_cls.from_overrides(cfg) # type: ignore
configs[ecosystem_name] = config
del user_config[ecosystem_name]

remaining_keys = user_config.keys()
if len(remaining_keys) > 0:
remaining_keys_str = ", ".join(remaining_keys)
Expand Down
2 changes: 1 addition & 1 deletion src/ape_ethereum/ecosystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ class Ethereum(EcosystemAPI):

@property
def config(self) -> EthereumConfig:
return cast(EthereumConfig, self.config_manager.get_config("ethereum"))
return cast(EthereumConfig, self.config_manager.get_config(self.name))

@property
def default_transaction_type(self) -> TransactionType:
Expand Down
30 changes: 25 additions & 5 deletions tests/functional/test_ecosystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,16 @@ def event_abi(vyper_contract_instance):


@pytest.fixture
def custom_ecosystem_config(custom_networks_config_dict, temp_config, networks):
def custom_ecosystem_config(
custom_networks_config_dict, temp_config, networks, custom_network_name_0
):
data = copy.deepcopy(custom_networks_config_dict)
data["networks"]["custom"][0]["ecosystem"] = CUSTOM_ECOSYSTEM_NAME

# Also ensure we can configure the custom ecosystem as if
# it were from a plugin.
data[CUSTOM_ECOSYSTEM_NAME] = {"default_network": custom_network_name_0}

with temp_config(data):
yield

Expand Down Expand Up @@ -438,10 +445,6 @@ def test_decode_etherscan_receipt(eth_tester_provider, ethereum):
assert receipt.gas_price == 1499999989


def test_default_transaction_type(ethereum):
assert ethereum.default_transaction_type == TransactionType.DYNAMIC


def test_default_transaction_type_not_connected_used_default_network(
temp_config, ethereum, networks
):
Expand Down Expand Up @@ -487,6 +490,10 @@ class Subconfig(BaseEthereumConfig):
assert config.mainnet_fork.default_transaction_type.value == 0


def test_default_transaction_type_configured_from_custom_network():
pass


@pytest.mark.parametrize("network_name", (LOCAL_NETWORK_NAME, "mainnet-fork", "mainnet_fork"))
def test_gas_limit_local_networks(ethereum, network_name):
network = ethereum.get_network(network_name)
Expand Down Expand Up @@ -720,3 +727,16 @@ def test_getattr_custom_networks(ethereum, custom_networks_config, custom_networ
actual = getattr(ethereum, custom_network_name_0)
assert actual.name == custom_network_name_0
assert isinstance(actual, NetworkAPI)


def test_default_network(ethereum):
assert ethereum.default_network_name == LOCAL_NETWORK_NAME


def test_default_network_when_custom_and_set_in_config(
custom_ecosystem_config, networks, custom_network_name_0
):
ecosystem = networks.get_ecosystem(CUSTOM_ECOSYSTEM_NAME)
# Force it to use config value (in case was set from previous test)
ecosystem._default_network = None
assert ecosystem.default_network_name == custom_network_name_0
22 changes: 22 additions & 0 deletions tests/functional/test_network_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,25 @@ def test_config_custom_networks(
cfg_by_get = ethereum_config.get("apenet")
assert cfg_by_get is not None
assert cfg_by_get.default_transaction_type == TransactionType.STATIC


def test_config_networks_from_custom_ecosystem(
networks, custom_networks_config_dict, temp_config, custom_network_name_0
):
data = copy.deepcopy(custom_networks_config_dict)
data["networks"]["custom"][0]["ecosystem"] = "custom-ecosystem"
data["networks"]["custom"][1]["ecosystem"] = "custom-ecosystem"
data["custom-ecosystem"] = {
custom_network_name_0: {"default_transaction_type": TransactionType.STATIC.value}
}
with temp_config(data):
custom_ecosystem = networks.get_ecosystem("custom-ecosystem")
network = custom_ecosystem.get_network("apenet")
ethereum_config = network.config
cfg_by_attr = ethereum_config.apenet
assert cfg_by_attr.default_transaction_type == TransactionType.STATIC

assert "apenet" in ethereum_config
cfg_by_get = ethereum_config.get("apenet")
assert cfg_by_get is not None
assert cfg_by_get.default_transaction_type == TransactionType.STATIC

0 comments on commit a3e14db

Please sign in to comment.