def find_matching_func(contract_abi, fn_name, fn_type): """ :param contract_abi: :param fn_name: :param fn_type: :return: { "inputs":[ { "name":"_organizationName", "type":"string" }, { "name":"_members", "type":"address[]" } ], "payable":true, "stateMutability":"payable", "type":"constructor", "name":"Association" } """ if fn_name: abi = filter_by_name(fn_name, contract_abi) elif fn_type: abi = filter_by_type(fn_type, contract_abi) else: raise Exception("invalid parameters") if len(abi) == 0: raise Exception(f"no match function: {fn_name}") if len(abi) > 1: raise Exception(f"multiple match functions: {fn_name}") return abi[0]
def _find_matching_fn_abi(cls, fn_name=None, args=None, kwargs=None): filters = [] if fn_name: filters.append(functools.partial(filter_by_name, fn_name)) if args is not None or kwargs is not None: if args is None: args = tuple() if kwargs is None: kwargs = {} num_arguments = len(args) + len(kwargs) filters.extend([ functools.partial(filter_by_argument_count, num_arguments), functools.partial(filter_by_encodability, args, kwargs), ]) function_candidates = filter_by_type('function', cls.abi) for filter_fn in filters: function_candidates = filter_fn(function_candidates) if len(function_candidates) == 1: return function_candidates[0] elif not function_candidates: break if not function_candidates: raise ValueError("No matching functions found") else: raise ValueError("Multiple functions found")
def _find_matching_fn_abi(cls, fn_name=None, args=None, kwargs=None): filters = [] if fn_name: filters.append(functools.partial(filter_by_name, fn_name)) if args is not None or kwargs is not None: if args is None: args = tuple() if kwargs is None: kwargs = {} num_arguments = len(args) + len(kwargs) filters.extend([ functools.partial(filter_by_argument_count, num_arguments), functools.partial(filter_by_encodability, args, kwargs), ]) function_candidates = filter_by_type('function', cls.abi) for filter_fn in filters: function_candidates = filter_fn(function_candidates) if len(function_candidates) == 1: return function_candidates[0] elif not function_candidates: break if not function_candidates: raise ValueError("No matching functions found") else: raise ValueError("Multiple functions found")
def filter_events(self, filter_params: Dict, name_to_callback: Dict): """ Filter events for given event names Params: filter_params: arguments for the filter call name_to_callback: dict that maps event name to callbacks executed if the event is emmited """ for id, (topics, callback) in name_to_callback.items(): events = get_events( web3=self.web3, contract_address=self.contract_address, topics=topics, **filter_params, ) events_abi = filter_by_type( "event", self.contract_manager.get_contract_abi(self.contract_name)) topic_to_event_abi = { event_abi_to_log_topic(event_abi): event_abi for event_abi in events_abi } for raw_event in events: decoded_event = decode_event( topic_to_event_abi=topic_to_event_abi, log_entry=raw_event, ) log.debug('Received confirmed event: \n%s', decoded_event) callback(decoded_event)
def __init__(self, abi, web3, address=None): if abi: self.function_methods = filter_by_type('function', abi) for method in self.function_methods: self._method_names.append(method['name']) setattr( self, method['name'], ContractMethod.factory(web3=web3, contract_abi=abi, address=address, method_name=method['name']))
def topics_to_abi(project): from web3.utils.abi import ( filter_by_type, event_abi_to_log_topic, ) all_events_abi = filter_by_type('event', itertools.chain.from_iterable( contract['abi'] for contract in project.compiled_contracts.values() )) _topic_to_abi = { event_abi_to_log_topic(abi): abi for abi in all_events_abi } return _topic_to_abi
def __init__(self, abi, web3, address=None): if abi: self.abi = abi self._functions = filter_by_type('function', self.abi) for func in self._functions: self._function_names.append(func['name']) setattr( self, func['name'], ContractFunction.factory(func['name'], web3=web3, contract_abi=self.abi, address=address, function_identifier=func['name']))
def __init__(self, abi, web3, address=None): if abi: self.abi = abi self._events = filter_by_type('event', self.abi) for event in self._events: self._event_names.append(event['name']) setattr( self, event['name'], ContractEvent.factory(event['name'], web3=web3, contract_abi=self.abi, address=address, event_name=event['name']))
def decode_event(abi: Dict, log: Dict): """Helper function to unpack event data using a provided ABI""" if isinstance(log['topics'][0], str): log['topics'][0] = decode_hex(log['topics'][0]) elif isinstance(log['topics'][0], int): log['topics'][0] = decode_hex(hex(log['topics'][0])) event_id = log['topics'][0] events = filter_by_type('event', abi) topic_to_event_abi = { event_abi_to_log_topic(event_abi): event_abi for event_abi in events } event_abi = topic_to_event_abi[event_id] return get_event_data(event_abi, log)
def topics_to_abi(project): from web3.utils.abi import ( filter_by_type, event_abi_to_log_topic, ) all_events_abi = filter_by_type( 'event', itertools.chain.from_iterable( contract['abi'] for contract in project.compiled_contracts.values())) _topic_to_abi = { event_abi_to_log_topic(abi): abi for abi in all_events_abi } return _topic_to_abi
def __init__(self, abi, web3, address=None): if abi: self.abi = abi self._functions = filter_by_type('function', self.abi) for function in self._functions: self._function_names.append(function['name']) setattr( self, function['name'], ContractFunction.factory( function['name'], web3=web3, contract_abi=self.abi, address=address, function_name=function['name']))
def __init__(self, abi, web3, address=None): if abi: self.abi = abi self._events = filter_by_type('event', self.abi) for event in self._events: self._event_names.append(event['name']) setattr( self, event['name'], ContractEvent.factory( event['name'], web3=web3, contract_abi=self.abi, address=address, event_name=event['name']))
def validate_abi(abi): """ Helper function for validating an ABI """ if not is_list_like(abi): raise ValueError("'abi' is not a list") if not all(is_dict(e) for e in abi): raise ValueError("'abi' is not a list of dictionaries") functions = filter_by_type('function', abi) selectors = groupby(compose(encode_hex, function_abi_to_4byte_selector), functions) duplicates = valfilter(lambda funcs: len(funcs) > 1, selectors) if duplicates: raise ValueError('Abi contains functions with colliding selectors. ' 'Functions {0}'.format( _prepare_selector_collision_msg(duplicates)))
def decode_event(abi: ABI, log_: Dict) -> Dict: """ Helper function to unpack event data using a provided ABI Args: abi: The ABI of the contract, not the ABI of the event log_: The raw event data Returns: The decoded event """ if isinstance(log_["topics"][0], str): log_["topics"][0] = decode_hex(log_["topics"][0]) elif isinstance(log_["topics"][0], int): log_["topics"][0] = decode_hex(hex(log_["topics"][0])) event_id = log_["topics"][0] events = filter_by_type("event", abi) topic_to_event_abi = {event_abi_to_log_topic(event_abi): event_abi for event_abi in events} event_abi = topic_to_event_abi[event_id] return get_event_data(event_abi, log_)
def query_blockchain_events( web3: Web3, contract_manager: ContractManager, contract_address: Address, contract_name: str, topics: List, from_block: BlockNumber, to_block: BlockNumber, ) -> List[Dict]: """Returns events emmitted by a contract for a given event name, within a certain range. Args: web3: A Web3 instance contract_manager: A contract manager contract_address: The address of the contract to be filtered, can be `None` contract_name: The name of the contract topics: The topics to filter for from_block: The block to start search events to_block: The block to stop searching for events Returns: All matching events """ events_abi = filter_by_type( "event", contract_manager.get_contract_abi(contract_name)) topic_to_event_abi = { event_abi_to_log_topic(event_abi): event_abi for event_abi in events_abi } filter_params = { "fromBlock": from_block, "toBlock": to_block, "address": to_checksum_address(contract_address), "topics": topics, } events = web3.eth.getLogs(filter_params) return [ decode_event(topic_to_event_abi, log_entry) for log_entry in events ]
def find_matching_abi(cls, fn_name, arguments): filters = [ functools.partial(filter_by_name, fn_name), functools.partial(filter_by_argument_count, arguments), functools.partial(filter_by_encodability, arguments), ] function_candidates = filter_by_type('function', cls.abi) for filter_fn in filters: function_candidates = filter_fn(function_candidates) if len(function_candidates) == 1: return function_candidates[0] elif not function_candidates: break if not function_candidates: raise ValueError("No matching functions found") else: raise ValueError("Multiple functions found")
def decode_event(abi: Dict, log: Dict): """ Helper function to unpack event data using a provided ABI Args: abi: The ABI of the contract, not the ABI of the event log: The raw event data Returns: The decoded event """ if isinstance(log['topics'][0], str): log['topics'][0] = decode_hex(log['topics'][0]) elif isinstance(log['topics'][0], int): log['topics'][0] = decode_hex(hex(log['topics'][0])) event_id = log['topics'][0] events = filter_by_type('event', abi) topic_to_event_abi = { event_abi_to_log_topic(event_abi): event_abi for event_abi in events } event_abi = topic_to_event_abi[event_id] return get_event_data(event_abi, log)
def transaction_request_abi(self): return ( self.compiled_assets['TransactionRequest']['abi'] + filter_by_type('event', self.request_lib_abi) )