2023-04-27 17:51:26 +00:00
|
|
|
import json
|
|
|
|
from copy import deepcopy
|
2023-05-04 20:35:40 +00:00
|
|
|
from pathlib import Path
|
|
|
|
from typing import Any, Dict, Tuple
|
2023-04-27 17:51:26 +00:00
|
|
|
|
2023-04-27 19:57:04 +00:00
|
|
|
from ape import config as ape_config
|
2023-05-04 20:35:40 +00:00
|
|
|
from ape.api import DependencyAPI
|
|
|
|
from eth_typing import ChecksumAddress
|
|
|
|
from eth_utils import is_checksum_address, to_checksum_address
|
2023-04-27 17:51:26 +00:00
|
|
|
|
|
|
|
from nucypher.blockchain.eth.agents import (
|
2023-05-04 20:35:40 +00:00
|
|
|
CoordinatorAgent,
|
2023-04-27 17:51:26 +00:00
|
|
|
NucypherTokenAgent,
|
|
|
|
PREApplicationAgent,
|
|
|
|
SubscriptionManagerAgent,
|
|
|
|
)
|
|
|
|
from nucypher.blockchain.eth.registry import InMemoryContractRegistry
|
|
|
|
from tests.constants import MOCK_STAKING_CONTRACT_NAME
|
|
|
|
|
|
|
|
# order sensitive
|
|
|
|
_CONTRACTS_TO_DEPLOY_ON_TESTERCHAIN = (
|
|
|
|
NucypherTokenAgent.contract_name,
|
|
|
|
MOCK_STAKING_CONTRACT_NAME,
|
|
|
|
PREApplicationAgent.contract_name,
|
|
|
|
SubscriptionManagerAgent.contract_name,
|
|
|
|
CoordinatorAgent.contract_name,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2023-04-27 19:57:04 +00:00
|
|
|
def get_ape_project_build_path(project) -> Path:
|
2023-04-27 17:51:26 +00:00
|
|
|
build_path = Path(project.path) / '.build'
|
|
|
|
return build_path
|
|
|
|
|
|
|
|
|
2023-05-04 17:13:27 +00:00
|
|
|
def process_deployment_params(
|
|
|
|
contract_name, params, deployments, symbol: str = "::"
|
|
|
|
) -> Dict[str, Any]:
|
|
|
|
"""Process deployment params for a contract."""
|
2023-04-27 17:51:26 +00:00
|
|
|
processed_params = dict()
|
|
|
|
for k, v in params.items():
|
2023-05-04 17:13:27 +00:00
|
|
|
if isinstance(v, str) and (v.startswith(symbol) and v.endswith(symbol)):
|
|
|
|
dependency_expression = v.strip(symbol)
|
|
|
|
dependency_name, attribute_name = dependency_expression.split(".")
|
2023-04-27 17:51:26 +00:00
|
|
|
try:
|
2023-05-04 17:13:27 +00:00
|
|
|
v = getattr(deployments[dependency_name], attribute_name)
|
2023-04-27 17:51:26 +00:00
|
|
|
except KeyError:
|
|
|
|
raise ValueError(f"Contract {contract_name} not found in deployments")
|
2023-05-04 17:13:27 +00:00
|
|
|
except AttributeError:
|
|
|
|
raise ValueError(
|
|
|
|
f"Attribute {attribute_name} not found in {dependency_name}"
|
|
|
|
)
|
2023-04-27 17:51:26 +00:00
|
|
|
processed_params[k] = v
|
|
|
|
return processed_params
|
|
|
|
|
|
|
|
|
2023-05-04 17:13:27 +00:00
|
|
|
def get_deployment_params(
|
|
|
|
contract_name, config, accounts, deployments
|
|
|
|
) -> Tuple[Dict, ChecksumAddress]:
|
2023-04-27 17:51:26 +00:00
|
|
|
"""
|
|
|
|
Get deployment params for a contract.
|
|
|
|
"""
|
|
|
|
config = deepcopy(config)
|
|
|
|
while config:
|
|
|
|
params = config.pop()
|
2023-05-04 17:13:27 +00:00
|
|
|
deployer_address = params.pop("address")
|
2023-04-27 17:51:26 +00:00
|
|
|
name = params.pop("contract_type")
|
2023-05-04 17:13:27 +00:00
|
|
|
if not is_checksum_address(deployer_address):
|
|
|
|
try:
|
|
|
|
deployer_address = ChecksumAddress(accounts[int(deployer_address)])
|
|
|
|
except IndexError:
|
|
|
|
raise ValueError(f"Invalid deployer account index {deployer_address}")
|
|
|
|
except ValueError:
|
|
|
|
raise ValueError(
|
|
|
|
f"Invalid configuration value for {name}'s deployment account: {deployer_address}"
|
|
|
|
)
|
2023-04-27 17:51:26 +00:00
|
|
|
if name == contract_name:
|
|
|
|
params = process_deployment_params(contract_name, params, deployments)
|
2023-05-04 17:13:27 +00:00
|
|
|
return params, deployer_address
|
2023-04-27 17:51:26 +00:00
|
|
|
else:
|
|
|
|
# there are no deployment params for this contract
|
2023-05-04 17:13:27 +00:00
|
|
|
return dict(), ChecksumAddress(deployer_address)
|
2023-04-27 17:51:26 +00:00
|
|
|
|
|
|
|
|
2023-05-04 17:13:27 +00:00
|
|
|
def deploy_contracts(nucypher_contracts: DependencyAPI, accounts):
|
2023-04-27 17:51:26 +00:00
|
|
|
"""Deploy contracts o via ape's API for testing."""
|
|
|
|
config = ape_config.get_config("deployments")["ethereum"]["local"]
|
|
|
|
deployments = dict()
|
|
|
|
for name in _CONTRACTS_TO_DEPLOY_ON_TESTERCHAIN:
|
2023-05-04 17:13:27 +00:00
|
|
|
params, deployer_account = get_deployment_params(
|
|
|
|
name, deployments=deployments, config=config, accounts=accounts
|
|
|
|
)
|
2023-04-27 17:51:26 +00:00
|
|
|
dependency_contract = getattr(nucypher_contracts, name)
|
|
|
|
deployed_contract = deployer_account.deploy(dependency_contract, *params.values())
|
|
|
|
deployments[name] = deployed_contract
|
|
|
|
return deployments
|
|
|
|
|
|
|
|
|
2023-04-28 02:12:51 +00:00
|
|
|
def registry_from_ape_deployments(nucypher_contracts: DependencyAPI, deployments: Dict) -> InMemoryContractRegistry:
|
2023-04-27 17:51:26 +00:00
|
|
|
"""Creates a registry from ape deployments."""
|
|
|
|
|
2023-04-28 02:12:51 +00:00
|
|
|
# Get the raw abi from the cached manifest
|
|
|
|
manifest = json.loads(nucypher_contracts.cached_manifest.json())
|
|
|
|
contract_data = manifest['contractTypes']
|
2023-04-27 17:51:26 +00:00
|
|
|
|
|
|
|
data = list()
|
|
|
|
for contract_name, deployment in deployments.items():
|
2023-04-28 02:12:51 +00:00
|
|
|
abi = contract_data[contract_name]['abi']
|
2023-04-27 17:51:26 +00:00
|
|
|
entry = [
|
|
|
|
contract_name,
|
|
|
|
'v0.0.0', # TODO: get version from contract
|
|
|
|
to_checksum_address(deployment.address),
|
|
|
|
abi
|
|
|
|
]
|
|
|
|
data.append(entry)
|
|
|
|
registry = InMemoryContractRegistry()
|
|
|
|
registry.write(data)
|
|
|
|
return registry
|