diff --git a/operate/cli.py b/operate/cli.py index 6db9fe3df..eda13dd37 100644 --- a/operate/cli.py +++ b/operate/cli.py @@ -436,7 +436,7 @@ async def _build_service_locally(request: Request) -> JSONResponse: ) .deployment ) - deployment.build() + deployment.build(force=False) return JSONResponse(content=deployment.json) @app.post("/api/services/{service}/deployment/start") @@ -450,7 +450,7 @@ async def _start_service_locally(request: Request) -> JSONResponse: ) .deployment ) - deployment.build() + deployment.build(force=False) operate.service_manager().fund_service(hash=request.path_params["service"]) deployment.start() return JSONResponse(content=deployment.json) diff --git a/operate/services/manage.py b/operate/services/manage.py index b730bbb06..4b87f83ca 100644 --- a/operate/services/manage.py +++ b/operate/services/manage.py @@ -362,10 +362,12 @@ def fund_service(self, hash: str) -> None: ledger_api = wallet.ledger_api(chain_type=service.ledger_config.chain) agent_fund_requirement = service.chain_data.user_params.fund_requirements.agent - self.logger.info("Funding agents") for key in service.keys: agent_balance = ledger_api.get_balance(address=key.address) + self.logger.info(f"Agent {key.address} balance: {agent_balance}") + self.logger.info(f"Required balance: {agent_fund_requirement}") if agent_balance < agent_fund_requirement: + self.logger.info("Funding agents") to_transfer = agent_fund_requirement - agent_balance self.logger.info(f"Transferring {to_transfer} units to {key.address}") wallet.transfer( @@ -374,19 +376,23 @@ def fund_service(self, hash: str) -> None: chain_type=service.ledger_config.chain, ) - self.logger.info("Funding safe") + safe_balanace = ledger_api.get_balance(service.chain_data.multisig) safe_fund_requirement = service.chain_data.user_params.fund_requirements.safe - safe_balanace = ledger_api.get_balance(wallet.safe) + self.logger.info(f"Safe {service.chain_data.multisig} balance: {safe_balanace}") + self.logger.info(f"Required balance: {safe_fund_requirement}") if safe_balanace < safe_fund_requirement: + self.logger.info("Funding safe") to_transfer = safe_fund_requirement - safe_balanace - self.logger.info(f"Transferring {to_transfer} units to {wallet.safe}") + self.logger.info( + f"Transferring {to_transfer} units to {service.chain_data.multisig}" + ) wallet.transfer( - to=t.cast(str, wallet.safe), + to=t.cast(str, service.chain_data.multisig), amount=to_transfer, chain_type=service.ledger_config.chain, ) - def deploy_service_locally(self, hash: str, force: bool = False) -> Deployment: + def deploy_service_locally(self, hash: str, force: bool = True) -> Deployment: """ Deploy service locally diff --git a/operate/services/service.py b/operate/services/service.py index 36d6be14d..ac83b5067 100644 --- a/operate/services/service.py +++ b/operate/services/service.py @@ -90,16 +90,22 @@ def mkdirs(build_dir: Path) -> None: continue -def remove_service_network(service_name: str) -> None: +def remove_service_network(service_name: str, force: bool = True) -> None: """Remove service network cache.""" client = from_env() network_names = ( f"deployment_service_{service_name}_localnet", f"abci_build_service_{service_name}_localnet", ) - for network in client.networks.list(): + for network in client.networks.list(greedy=True): if network.attrs["Name"] not in network_names: continue + + if force: + for container in network.attrs["Containers"]: + print(f"Killing {container}") + client.api.kill(container=container) + print("Deleting network: " + network.attrs["Name"]) client.api.remove_network(net_id=network.attrs["Id"]) @@ -216,6 +222,7 @@ def build(self, force: bool = True) -> None: # if the service is still running so we can do an early exit remove_service_network( service_name=service.helper.config.name, + force=force, ) build = self.path / DEPLOYMENT diff --git a/operate/wallet/master.py b/operate/wallet/master.py index 8237e4323..70c6644ba 100644 --- a/operate/wallet/master.py +++ b/operate/wallet/master.py @@ -26,7 +26,9 @@ from aea.crypto.base import Crypto, LedgerApi from aea.crypto.registries import make_ledger_api -from aea_ledger_ethereum.ethereum import EthereumCrypto +from aea_ledger_ethereum.ethereum import EthereumApi, EthereumCrypto +from autonomy.chain.config import ChainType as ChainProfile +from autonomy.chain.tx import TxSettler from web3 import Account from operate.ledger import get_default_rpc @@ -85,24 +87,7 @@ def ledger_api( def transfer(self, to: str, amount: int, chain_type: ChainType) -> None: """Transfer funds to the given account.""" - ledger_api = self.ledger_api(chain_type=chain_type) - tx = ledger_api.get_transfer_transaction( - sender_address=self.crypto.address, - destination_address=to, - amount=amount, - tx_fee=50000, - tx_nonce=ledger_api.generate_tx_nonce( - seller=self.crypto.address, - client=to, - ), - ) - tx = ledger_api.update_with_gas_estimate(tx) - tx = self.crypto.sign_transaction(tx) - ledger_api.get_transaction_receipt( - tx_digest=ledger_api.send_signed_transaction( - tx_signed=tx, - ) - ) + raise NotImplementedError() @staticmethod def new(password: str, path: Path) -> t.Tuple["MasterWallet", t.List[str]]: @@ -135,13 +120,36 @@ class EthereumMasterWallet(MasterWallet): _key = ledger_type.key_file _crypto_cls = EthereumCrypto - def get_crypto_obj(self, password: str) -> EthereumCrypto: - """Load ethereum crypto object.""" - return EthereumCrypto( - private_key_path=self.path / self._key, - password=password, + def transfer(self, to: str, amount: int, chain_type: ChainType) -> None: + """Transfer funds to the given account.""" + ledger_api = t.cast(EthereumApi, self.ledger_api(chain_type=chain_type)) + tx_helper = TxSettler( + ledger_api=ledger_api, + crypto=self.crypto, + chain_type=ChainProfile.CUSTOM, ) + def _build_tx( # pylint: disable=unused-argument + *args: t.Any, **kwargs: t.Any + ) -> t.Dict: + """Build transaction""" + tx = ledger_api.get_transfer_transaction( + sender_address=self.crypto.address, + destination_address=to, + amount=amount, + tx_fee=50000, + tx_nonce="0x", + chain_id=chain_type.id, + raise_on_try=True, + ) + return ledger_api.update_with_gas_estimate( + transaction=tx, + raise_on_try=True, + ) + + setattr(tx_helper, "build", _build_tx) # noqa: B010 + tx_helper.transact(lambda x: x, "", kwargs={}) + @classmethod def new( cls, password: str, path: Path