def get_proxy_contract(self, registry: BaseContractRegistry, target_address: str, proxy_name: str) -> VersionedContract: # Lookup proxies; Search for a registered proxy that targets this contract record records = registry.search(contract_name=proxy_name) dispatchers = list() for name, version, address, abi in records: proxy_contract = self.client.w3.eth.contract( abi=abi, address=address, version=version, ContractFactoryClass=self._CONTRACT_FACTORY) # Read this dispatchers target address from the blockchain proxy_live_target_address = proxy_contract.functions.target().call( ) if proxy_live_target_address == target_address: dispatchers.append(proxy_contract) if len(dispatchers) > 1: message = f"Multiple Dispatcher deployments are targeting {target_address}" raise self.InterfaceError(message) try: return dispatchers[0] except IndexError: raise self.UnknownContract( f"No registered Dispatcher deployments target {target_address}" )
def get_contract_by_name( self, registry: BaseContractRegistry, contract_name: str, contract_version: str = None, enrollment_version: Union[int, str] = None, proxy_name: str = None, use_proxy_address: bool = True) -> VersionedContract: """ Instantiate a deployed contract from registry data, and assimilate it with its proxy if it is upgradeable. """ target_contract_records = registry.search( contract_name=contract_name, contract_version=contract_version) if not target_contract_records: raise self.UnknownContract( f"No such contract records with name {contract_name}:{contract_version}." ) if proxy_name: # Lookup proxies; Search for a published proxy that targets this contract record proxy_records = registry.search(contract_name=proxy_name) results = list() for proxy_name, proxy_version, proxy_address, proxy_abi in proxy_records: proxy_contract = self.client.w3.eth.contract( abi=proxy_abi, address=proxy_address, version=proxy_version, ContractFactoryClass=self._CONTRACT_FACTORY) # Read this dispatcher's target address from the blockchain proxy_live_target_address = proxy_contract.functions.target( ).call() for target_name, target_version, target_address, target_abi in target_contract_records: if target_address == proxy_live_target_address: if use_proxy_address: triplet = (proxy_address, target_version, target_abi) else: triplet = (target_address, target_version, target_abi) else: continue results.append(triplet) if len(results) > 1: address, _version, _abi = results[0] message = "Multiple {} deployments are targeting {}".format( proxy_name, address) raise self.InterfaceError(message.format(contract_name)) else: try: selected_address, selected_version, selected_abi = results[ 0] except IndexError: raise self.UnknownContract( f"There are no Dispatcher records targeting '{contract_name}':{contract_version}" ) else: # TODO: use_proxy_address doesnt' work in this case. Should we raise if used? # NOTE: 0 must be allowed as a valid version number if len(target_contract_records) != 1: if enrollment_version is None: m = f"{len(target_contract_records)} records enrolled " \ f"for contract {contract_name}:{contract_version} " \ f"and no version index was supplied." raise self.InterfaceError(m) enrollment_version = self.__get_enrollment_version_index( name=contract_name, contract_version=contract_version, version_index=enrollment_version, enrollments=len(target_contract_records)) else: enrollment_version = -1 # default _contract_name, selected_version, selected_address, selected_abi = target_contract_records[ enrollment_version] # Create the contract from selected sources unified_contract = self.client.w3.eth.contract( abi=selected_abi, address=selected_address, version=selected_version, ContractFactoryClass=self._CONTRACT_FACTORY) return unified_contract
def get_contract_by_name( self, registry: BaseContractRegistry, name: str, version: int = None, proxy_name: str = None, use_proxy_address: bool = True) -> Union[Contract, List[tuple]]: """ Instantiate a deployed contract from registry data, and assimilate it with its proxy if it is upgradeable, or return all registered records if use_proxy_address is False. """ target_contract_records = registry.search(contract_name=name) if not target_contract_records: raise self.UnknownContract( f"No such contract records with name {name}.") if proxy_name: # Lookup proxies; Search for a published proxy that targets this contract record proxy_records = registry.search(contract_name=proxy_name) results = list() for proxy_name, proxy_addr, proxy_abi in proxy_records: proxy_contract = self.client.w3.eth.contract( abi=proxy_abi, address=proxy_addr, ContractFactoryClass=self._contract_factory) # Read this dispatcher's target address from the blockchain proxy_live_target_address = proxy_contract.functions.target( ).call() for target_name, target_addr, target_abi in target_contract_records: if target_addr == proxy_live_target_address: if use_proxy_address: pair = (proxy_addr, target_abi) else: pair = (target_addr, target_abi) else: continue results.append(pair) if len(results) > 1: address, abi = results[0] message = "Multiple {} deployments are targeting {}".format( proxy_name, address) raise self.InterfaceError(message.format(name)) else: try: selected_address, selected_abi = results[0] except IndexError: raise self.UnknownContract( f"There are no Dispatcher records targeting '{name}'") else: # NOTE: 0 must be allowed as a valid version number if len(target_contract_records) != 1: if version is None: m = f"{len(target_contract_records)} records enrolled for contract {name} " \ f"and no version index was supplied." raise self.InterfaceError(m) version = self.__get_version_index( name=name, version_index=version, enrollments=len(target_contract_records)) else: version = -1 # default _target_contract_name, selected_address, selected_abi = target_contract_records[ version] # Create the contract from selected sources unified_contract = self.client.w3.eth.contract( abi=selected_abi, address=selected_address, ContractFactoryClass=self._contract_factory) return unified_contract