diff --git a/tplus/client/clearingengine/assetregistry.py b/tplus/client/clearingengine/assetregistry.py index 2c12d7b..d99a9c5 100644 --- a/tplus/client/clearingengine/assetregistry.py +++ b/tplus/client/clearingengine/assetregistry.py @@ -42,3 +42,16 @@ async def update_risk_parameters(self): Request that the clearing engine updates its registered risk parameters. """ await self._post("params/update") + + async def update_fee_account(self): + """ + Request that the clearing engine update its fee account. + """ + await self._post("fee-account/update") + + async def get_fee_account(self) -> str: + """ + Get the fee account. + """ + account = await self._get("fee-account") + return f"{account}" diff --git a/tplus/evm/contracts.py b/tplus/evm/contracts.py index 0c4cc0a..fb5e0ee 100644 --- a/tplus/evm/contracts.py +++ b/tplus/evm/contracts.py @@ -193,7 +193,7 @@ def __init__( address: str | None = None, tplus_contracts_version: str | None = None, ) -> None: - self._deployments: dict[int, ContractInstance] = {} + self._deployments: dict[str, ContractInstance] = {} self._default_deployer = default_deployer if isinstance(chain_id, int): @@ -202,6 +202,7 @@ def __init__( self._chain_id = chain_id self._address = address self._tplus_contracts_version = tplus_contracts_version + self._attempted_deploy_dev = False if address is not None and chain_id is not None: self._deployments[f"{chain_id}"] = self._contract_container.at(address) @@ -233,6 +234,13 @@ def deploy_dev(cls, **kwargs): owner = kwargs.get("sender") or get_dev_default_owner() return cls.deploy(owner, sender=owner) + def deploy_dev_and_set_deployment(self) -> "TPlusContract": + self._attempted_deploy_dev = True + instance = self.deploy_dev() + self._address = instance.address + self._deployments[f"{instance.chain_id}"] = instance + return instance + def __repr__(self) -> str: return f"<{self.name}>" @@ -241,14 +249,18 @@ def __getattr__(self, attr_name: str): # First, try a regular attribute on the class return self.__getattribute__(attr_name) except AttributeError: - # Resort to something defined on the contract. + if attr_name.startswith("_"): + # Ignore internals, causes integration issues. + raise + + # Try something defined on the contract. return getattr(self.contract, attr_name) @property def name(self) -> str: return self.__class__.NAME - @property + @cached_property def chain_id(self) -> ChainID: return self._chain_id or ChainID.evm(self.chain_manager.chain_id) @@ -257,8 +269,7 @@ def address(self) -> str: if address := self._address: return address - chain_id = self._chain_id or ChainID.evm(self.chain_manager.chain_id) - return self.get_address(chain_id=chain_id) + return self.get_address(chain_id=self.chain_id) @property def tplus_contracts_project(self) -> "Project": @@ -277,15 +288,16 @@ def contract(self) -> "ContractInstance": try: return self.get_contract() except ContractNotExists: - if self.chain_manager.provider.network.is_local: + if self.is_local_network and not self._attempted_deploy_dev: # If simulating, deploy it now. - instance = self.deploy_dev() - self._address = instance.address - self._deployments[self.chain_manager.chain_id] = instance - return instance + return self.deploy_dev_and_set_deployment() raise # This error. + @property + def is_local_network(self) -> bool: + return self.chain_manager.provider.network.is_local + @property def default_deployer(self) -> AccountAPI: if deployer := self._default_deployer: @@ -322,7 +334,7 @@ def get_contract(self, chain_id: ChainID | None = None) -> "ContractInstance": Returns: ContractInstance """ - chain_id = chain_id or self._chain_id or ChainID.evm(self.chain_manager.chain_id) + chain_id = chain_id or self.chain_id if chain_id in self._deployments: # Get previously cached instance. return self._deployments[chain_id] @@ -339,11 +351,14 @@ def get_address(self, chain_id: ChainID | None = None) -> str: if self._address and self._chain_id and chain_id == self._chain_id: return self._address - chain_id = chain_id or self._chain_id or ChainID.evm(self.chain_manager.chain_id) + chain_id = chain_id or self.chain_id try: return TPLUS_DEPLOYMENTS[chain_id][self.name] - except KeyError: - raise ContractNotExists(f"{self.name} not deployed on chain '{chain_id}'.") + except KeyError as err: + if self.is_local_network and not self._attempted_deploy_dev: + return self.deploy_dev_and_set_deployment().address + + raise ContractNotExists(f"{self.name} not deployed on chain '{chain_id}'.") from err class Registry(TPlusContract): @@ -500,7 +515,9 @@ def deploy_dev(cls, sender: AccountAPI | None = None, **kwargs) -> TPlusContract """ Deploy and set up a development vault. """ - credman = kwargs.get("credential_manager") or ZERO_ADDRESS + if not (credman := kwargs.get("credential_manager")): + credman = credential_manager.address + sender = sender or cls.account_manager.test_accounts[0] contract = cast(DepositVault, cls.deploy(sender, credman, sender=sender)) @@ -553,7 +570,10 @@ def deploy_dev(cls, **kwargs) -> "ReceiptAPI": owner = kwargs.get("sender") or get_dev_default_owner() operators = kwargs.get("operators", [owner.address]) threshold = kwargs.get("quorum_threshold") or len(operators) - registry_address = kwargs.get("registry") or ZERO_ADDRESS + + if not (registry_address := kwargs.get("registry")): + registry_address = registry.address + measurements = kwargs.get("measurements") or [] automata_verifier = kwargs.get("automata_verifier") or ZERO_ADDRESS