def get_events_from_receipt(contract, tx_receipt): result = {} for i in contract.events._events: name = i['name'] matching_abi = contract._find_matching_event_abi(name) # n_matches = len(contract.events.__dict__[name]().processReceipt(tx_receipt)) # print(i['name'], len(contract.events.__dict__[name]().processReceipt(tx_receipt))) for log in tx_receipt['logs']: try: get_event_data(matching_abi, log) abi_matches = True except: abi_matches = False if log['address'] == contract.address and abi_matches: if not name in result: result[name] = 0 result[name] += 1 return result
def populate_roi(infos: List[ExchangeInfo]) -> List[ExchangeInfo]: for info in infos: info.roi = list() exchange = web3.eth.contract(abi=UNISWAP_EXCHANGE_ABI, address=info.exchange_address) i = 0 eth_balance, token_balance = 0, 0 for block_number in get_chart_range(): dm_numerator, dm_denominator, trade_volume = 1, 1, 0 while i < len( info.logs) and info.logs[i]['blockNumber'] < block_number: log = info.logs[i] i += 1 topic = log['topics'][0].hex() if topic == EVENT_TRANSFER: continue elif topic == EVENT_ADD_LIQUIDITY: event = get_event_data( exchange.events.AddLiquidity._get_event_abi(), log) eth_balance += event['args']['eth_amount'] token_balance += event['args']['token_amount'] elif topic == EVENT_REMOVE_LIQUIDITY: event = get_event_data( exchange.events.RemoveLiquidity._get_event_abi(), log) eth_balance -= event['args']['eth_amount'] token_balance -= event['args']['token_amount'] elif topic == EVENT_ETH_PURCHASE: event = get_event_data( exchange.events.EthPurchase._get_event_abi(), log) eth_new_balance = eth_balance - event['args']['eth_bought'] token_new_balance = token_balance + event['args'][ 'tokens_sold'] dm_numerator *= eth_new_balance * token_new_balance dm_denominator *= eth_balance * token_balance trade_volume += event['args']['eth_bought'] / 0.997 eth_balance = eth_new_balance token_balance = token_new_balance else: event = get_event_data( exchange.events.TokenPurchase._get_event_abi(), log) eth_new_balance = eth_balance + event['args']['eth_sold'] token_new_balance = token_balance - event['args'][ 'tokens_bought'] dm_numerator *= eth_new_balance * token_new_balance dm_denominator *= eth_balance * token_balance trade_volume += event['args']['eth_sold'] eth_balance = eth_new_balance token_balance = token_new_balance try: info.roi.append( RoiInfo(sqrt(dm_numerator / dm_denominator), eth_balance, token_balance, trade_volume)) except ValueError: print(info.token_symbol, info.exchange_address) logging.info('Loaded info about roi of {} exchanges'.format(len(infos))) return infos
def populate_volume(infos: List[ExchangeInfo]) -> List[ExchangeInfo]: for info in infos: volume = list() info.volume = list() exchange = web3.eth.contract(abi=UNISWAP_EXCHANGE_ABI, address=info.exchange_address) i = 0 total_trade_volume = defaultdict(int) for block_number in get_chart_range(): trade_volume = defaultdict(int) while i < len( info.logs) and info.logs[i]['blockNumber'] < block_number: log = info.logs[i] i += 1 topic = log['topics'][0].hex() if topic == EVENT_ETH_PURCHASE: event = get_event_data( exchange.events.EthPurchase._get_event_abi(), log) trade_volume[event['args'][ 'buyer']] += event['args']['eth_bought'] / 0.997 total_trade_volume[event['args'][ 'buyer']] += event['args']['eth_bought'] / 0.997 elif topic == EVENT_TOKEN_PURCHASE: event = get_event_data( exchange.events.TokenPurchase._get_event_abi(), log) trade_volume[event['args'] ['buyer']] += event['args']['eth_sold'] total_trade_volume[event['args'] ['buyer']] += event['args']['eth_sold'] volume.append(trade_volume) total_volume = sum(total_trade_volume.values()) valuable_traders = { t for (t, v) in total_trade_volume.items() if v > total_volume / 1000 } info.valuable_traders = list(valuable_traders) for vol in volume: filtered_vol = defaultdict(int) for (t, v) in vol.items(): if t in valuable_traders: filtered_vol[t] = v else: filtered_vol['Other'] += v info.volume.append(filtered_vol) logging.info('Volumes of {} exchanges populated'.format(len(infos))) return infos
def get_mix_results(web3: Any, mixer_instance: Any, start_block: int, end_block: int, batch_size: Optional[int] = None) -> Iterator[MixResult]: """ Iterator for all events generated by 'mix' executions, over some block range (inclusive of `end_block`). Batch eth RPC calls to avoid too many calls, and holding huge lists of events in memory. """ contract_address = mixer_instance.address event_abi = find_matching_event_abi(mixer_instance.abi, event_name="LogMix") batch_size = batch_size or SYNC_BLOCKS_PER_BATCH while start_block <= end_block: # Filters are *inclusive* wrt "toBlock", hence the -1 here, and + 1 to # set start_block before iterating. to_block = min(start_block + batch_size - 1, end_block) filter_params = { 'fromBlock': start_block, 'toBlock': to_block, 'address': contract_address, } logs = web3.eth.getLogs(filter_params) for log in logs: event_data = get_event_data(event_abi, log) yield _event_args_to_mix_result(event_data.args) start_block = to_block + 1
def _get_all_event_data(log_entries): all_event_data = [ get_event_data(topics_to_abi[log_entry['topics'][0]], log_entry) for log_entry in log_entries if log_entry['topics'] and log_entry['topics'][0] in topics_to_abi ] return all_event_data
def standard_token_network_contract( web3, contracts_manager, wait_for_transaction, token_network_registry_contract, standard_token_contract, contract_deployer_address ): """Return instance of a deployed TokenNetwork for HumanStandardToken.""" txid = token_network_registry_contract.functions.createERC20TokenNetwork( standard_token_contract.address ).transact({'from': contract_deployer_address}) tx_receipt = wait_for_transaction(txid) assert len(tx_receipt['logs']) == 1 event_abi = contracts_manager.get_event_abi( CONTRACT_TOKEN_NETWORK_REGISTRY, EVENT_TOKEN_NETWORK_CREATED, ) decoded_event = get_event_data(event_abi, tx_receipt['logs'][0]) assert decoded_event is not None assert is_address(decoded_event['args']['token_address']) assert is_address(decoded_event['args']['token_network_address']) token_network_address = decoded_event['args']['token_network_address'] token_network_abi = contracts_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK) return web3.eth.contract(abi=token_network_abi, address=token_network_address)
def test_dynamic_length_argument_extraction(web3, emitter, wait_for_transaction, emitter_log_topics, emitter_event_ids): string_0 = "this-is-the-first-string-which-exceeds-32-bytes-in-length" string_1 = "this-is-the-second-string-which-exceeds-32-bytes-in-length" txn_hash = emitter.functions.logDynamicArgs(string_0, string_1).transact() txn_receipt = wait_for_transaction(web3, txn_hash) assert len(txn_receipt['logs']) == 1 log_entry = txn_receipt['logs'][0] event_abi = emitter._find_matching_event_abi('LogDynamicArgs') event_topic = emitter_log_topics.LogDynamicArgs assert event_topic in log_entry['topics'] string_0_topic = web3.sha3(text=string_0) assert string_0_topic in log_entry['topics'] event_data = get_event_data(event_abi, log_entry) expected_args = { "arg0": string_0_topic, "arg1": string_1, } assert event_data['args'] == expected_args assert event_data['blockHash'] == txn_receipt['blockHash'] assert event_data['blockNumber'] == txn_receipt['blockNumber'] assert event_data['transactionIndex'] == txn_receipt['transactionIndex'] assert is_same_address(event_data['address'], emitter.address) assert event_data['event'] == 'LogDynamicArgs'
def get_start_order_logs( self, web3, consumer_address=None, from_block=0, to_block="latest", from_all_tokens=False, ): topic0 = self.get_event_signature(self.ORDER_STARTED_EVENT) topics = [topic0] if consumer_address: topic1 = f"0x000000000000000000000000{consumer_address[2:].lower()}" topics = [topic0, None, topic1] filter_params = { "fromBlock": from_block, "toBlock": to_block, "topics": topics } if not from_all_tokens: # get logs only for this token address filter_params["address"] = self.address e = getattr(self.events, self.ORDER_STARTED_EVENT) event_abi = e().abi logs = web3.eth.getLogs(filter_params) parsed_logs = [] for lg in logs: parsed_logs.append(get_event_data(event_abi, lg)) return parsed_logs
def standard_token_network_contract( web3, contracts_manager, wait_for_transaction, token_network_registry_contract, standard_token_contract, contract_deployer_address ): txid = token_network_registry_contract.transact( {'from': contract_deployer_address} ).createERC20TokenNetwork( standard_token_contract.address ) tx_receipt = wait_for_transaction(txid) assert len(tx_receipt['logs']) == 1 event_abi = get_event_from_abi( token_network_registry_contract.abi, 'TokenNetworkCreated' ) decoded_event = get_event_data(event_abi, tx_receipt['logs'][0]) assert decoded_event is not None assert is_address(decoded_event['args']['token_address']) assert is_address(decoded_event['args']['token_network_address']) token_network_address = decoded_event['args']['token_network_address'] token_network_abi = contracts_manager.get_contract_abi('TokenNetwork') return web3.eth.contract(abi=token_network_abi, address=token_network_address)
def decode_log(event_name, log): event_log = get_event_data(event_abi(event_name), log) decoded_logs = dict(event_log.args) decoded_logs["block_number"] = event_log.blockNumber decoded_logs["transaction_index"] = event_log.transactionIndex decoded_logs["event"] = event_log.event return decoded_logs
def test_event_data_extraction(web3, emitter, wait_for_transaction, emitter_log_topics, emitter_event_ids, contract_fn, event_name, call_args, expected_args): function = getattr(emitter.functions, contract_fn) event_id = getattr(emitter_event_ids, event_name) txn_hash = function(event_id, *call_args).transact() txn_receipt = wait_for_transaction(web3, txn_hash) assert len(txn_receipt['logs']) == 1 log_entry = txn_receipt['logs'][0] event_abi = emitter._find_matching_event_abi(event_name) event_topic = getattr(emitter_log_topics, event_name) is_anonymous = event_abi['anonymous'] if is_anonymous: assert event_topic not in log_entry['topics'] else: assert event_topic in log_entry['topics'] event_data = get_event_data(event_abi, log_entry) assert event_data['args'] == expected_args assert event_data['blockHash'] == txn_receipt['blockHash'] assert event_data['blockNumber'] == txn_receipt['blockNumber'] assert event_data['transactionIndex'] == txn_receipt['transactionIndex'] assert is_same_address(event_data['address'], emitter.address) assert event_data['event'] == event_name
def test_get_log(self): topic, decoded_log = self.decoder.decode_log(self.test_logs[0]) self.assertEqual(topic, encode_hex(keccak(self.event_signature))) self.assertEqual( decoded_log, get_event_data(settings.ETHEREUM_EVENTS[0]['EVENT_ABI'], self.test_logs[0]))
def open_channel(self, partner_address: Address) -> int: """Opens channel with a single partner Parameters: partner_address - a valid ethereum address of the partner Return: channel_id - id of the channel """ assert is_checksum_address(partner_address) assert partner_address in self.client_registry # disallow multiple open channels with a same partner if partner_address in self.partner_to_channel_id: return self.partner_to_channel_id[partner_address] # if it doesn't exist, register new channel txid = self.contract.functions.openChannel( self.address, partner_address, 15).transact({'from': self.address}) assert txid is not None tx = self.web3.eth.getTransactionReceipt(txid) assert tx is not None assert len(tx['logs']) == 1 event = get_event_data( get_event_from_abi(self.contract.abi, 'ChannelOpened'), tx['logs'][0]) channel_id = event['args']['channel_identifier'] assert channel_id > 0 assert (is_same_address(event['args']['participant1'], self.address) or is_same_address(event['args']['participant2'], self.address)) assert (is_same_address(event['args']['participant1'], partner_address) or is_same_address(event['args']['participant2'], partner_address)) self.partner_to_channel_id[partner_address] = channel_id self.client_registry[partner_address].open_channel(self.address) return channel_id
def _parse_logs(self, txn_receipt): for log in txn_receipt['logs']: try: decoded_log = get_event_data(self.abi, log) except MismatchedABI: continue yield decoded_log
def get_logs( contract: Contract, event_name: str, from_block: Union[int, str] = 0, to_block: Union[int, str] = 'pending', argument_filters: Dict[str, Any] = None ): event_abi = [ abi_element for abi_element in contract.abi if abi_element['type'] == 'event' and abi_element['name'] == event_name ] assert len(event_abi) == 1, 'No event found matching name {}.'.format(event_name) event_abi = event_abi[0] if argument_filters is None: argument_filters = {} filter_params = input_filter_params_formatter(construct_event_filter_params( event_abi, argument_filters=argument_filters, address=contract.address, fromBlock=from_block, toBlock=to_block )[1]) response = _get_logs_raw(contract, filter_params) logs = log_array_formatter(response) logs = [dict(log) for log in logs] for log in logs: log['args'] = get_event_data(event_abi, log)['args'] return logs
def get_logs(self, event_name, from_block=0, to_block='latest', filters=None): filter_kwargs = { 'fromBlock': from_block, 'toBlock': to_block, 'address': self.contract_addr } event_abi = [ i for i in self.auction_contract.abi if i['type'] == 'event' and i['name'] == event_name ][0] assert event_abi filters = filters if filters else {} filter_ = construct_event_filter_params(event_abi, argument_filters=filters, **filter_kwargs)[1] filter_params = input_filter_params_formatter(filter_) response = self.chain.web3._requestManager.request_blocking( 'eth_getLogs', [filter_params]) logs = log_array_formatter(response) logs = [dict(log) for log in logs] for log in logs: log['args'] = get_event_data(event_abi, log)['args'] return logs
def __init__(self, receipt): self.raw_receipt = receipt self.transaction_hash = receipt['transactionHash'] self.gas_used = receipt['gasUsed'] self.transfers = [] self.result = None receipt_logs = receipt['logs'] if (receipt_logs is not None) and (len(receipt_logs) > 0): self.successful = True for receipt_log in receipt_logs: if len(receipt_log['topics']) > 0 and receipt_log['topics'][ 0] == '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef': from pymaker.token import ERC20Token transfer_abi = [ abi for abi in ERC20Token.abi if abi.get('name') == 'Transfer' ][0] event_data = get_event_data(transfer_abi, receipt_log) self.transfers.append( Transfer(token_address=Address(event_data['address']), from_address=Address( event_data['args']['from']), to_address=Address(event_data['args']['to']), value=Wad(event_data['args']['value']))) else: self.successful = False
def test_event_data_extraction(web3, emitter, wait_for_transaction, emitter_log_topics, emitter_event_ids, contract_fn, event_name, call_args, expected_args): emitter_fn = getattr(emitter.functions, contract_fn) event_id = getattr(emitter_event_ids, event_name) txn_hash = emitter_fn(event_id, *call_args).transact() txn_receipt = wait_for_transaction(web3, txn_hash) assert len(txn_receipt['logs']) == 1 log_entry = txn_receipt['logs'][0] event_abi = emitter._find_matching_event_abi(event_name) event_topic = getattr(emitter_log_topics, event_name) is_anonymous = event_abi['anonymous'] if is_anonymous: assert event_topic not in log_entry['topics'] else: assert event_topic in log_entry['topics'] event_data = get_event_data(event_abi, log_entry) assert event_data['args'] == expected_args assert event_data['blockHash'] == txn_receipt['blockHash'] assert event_data['blockNumber'] == txn_receipt['blockNumber'] assert event_data['transactionIndex'] == txn_receipt['transactionIndex'] assert is_same_address(event_data['address'], emitter.address) assert event_data['event'] == event_name
def __init__(self, receipt): self.raw_receipt = receipt self.transaction_hash = receipt['transactionHash'] self.gas_used = receipt['gasUsed'] self.transfers = [] self.result = None receipt_logs = receipt['logs'] if (receipt_logs is not None) and (len(receipt_logs) > 0): self.successful = True for receipt_log in receipt_logs: if len(receipt_log['topics']) > 0: # $ seth keccak $(seth --from-ascii "Transfer(address,address,uint256)") # 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef if receipt_log['topics'][0] == HexBytes('0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'): from pymaker.token import ERC20Token transfer_abi = [abi for abi in ERC20Token.abi if abi.get('name') == 'Transfer'][0] event_data = get_event_data(transfer_abi, receipt_log) self.transfers.append(Transfer(token_address=Address(event_data['address']), from_address=Address(event_data['args']['from']), to_address=Address(event_data['args']['to']), value=Wad(event_data['args']['value']))) # $ seth keccak $(seth --from-ascii "Mint(address,uint256)") # 0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885 if receipt_log['topics'][0] == HexBytes('0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885'): from pymaker.token import DSToken transfer_abi = [abi for abi in DSToken.abi if abi.get('name') == 'Mint'][0] event_data = get_event_data(transfer_abi, receipt_log) self.transfers.append(Transfer(token_address=Address(event_data['address']), from_address=Address('0x0000000000000000000000000000000000000000'), to_address=Address(event_data['args']['guy']), value=Wad(event_data['args']['wad']))) # $ seth keccak $(seth --from-ascii "Burn(address,uint256)") # 0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5 if receipt_log['topics'][0] == HexBytes('0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5'): from pymaker.token import DSToken transfer_abi = [abi for abi in DSToken.abi if abi.get('name') == 'Burn'][0] event_data = get_event_data(transfer_abi, receipt_log) self.transfers.append(Transfer(token_address=Address(event_data['address']), from_address=Address(event_data['args']['guy']), to_address=Address('0x0000000000000000000000000000000000000000'), value=Wad(event_data['args']['wad']))) else: self.successful = False
def from_event(cls, event: dict): assert(isinstance(event, dict)) topics = event.get('topics') if topics and topics[0] == HexBytes('0x0bcc4c97732e47d9946f229edb95f5b6323f601300e4690de719993f3c371129'): log_fill_abi = [abi for abi in ZrxExchange.abi if abi.get('name') == 'LogFill'][0] event_data = get_event_data(log_fill_abi, event) return LogFill(event_data)
def _get_all_filtered_channels(self, topics_without_signature): """ get all filtered chanels from blockchain logs """ mpe_address = self.get_mpe_address() event_signature = self.ident.w3.sha3(text="ChannelOpen(uint256,uint256,address,address,address,bytes32,uint256,uint256)").hex() topics = [event_signature] + topics_without_signature logs = self.ident.w3.eth.getLogs({"fromBlock" : self.args.from_block, "address" : mpe_address, "topics" : topics}) abi = get_contract_def("MultiPartyEscrow") event_abi = abi_get_element_by_name(abi, "ChannelOpen") channels_ids = [get_event_data(event_abi, l)["args"]["channelId"] for l in logs] return channels_ids
def get_event(web3contract, event_name, rcpt): print(rcpt) if len(rcpt.logs) < 1: return None abi = event_abi(web3contract.abi, event_name) for log in rcpt.logs: evnt_data = get_event_data(abi, log) return evnt_data return None
def from_event(cls, event: dict): assert isinstance(event, dict) topics = event.get('topics') if topics and topics[0] == HexBytes('0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8'): log_bite_abi = [abi for abi in Cat.abi if abi.get('name') == 'Bite'][0] event_data = get_event_data(log_bite_abi, event) return Cat.LogBite(event_data) else: logging.warning(f'[from_event] Invalid topic in {event}')
def from_event(cls, event: dict): assert (isinstance(event, dict)) topics = event.get('topics') if topics and topics[0] == HexBytes('0x259b30ca39885c6d801a0b5dbc988640f3c25e2f37531fe138c5c5af8955d41b'): log_created_abi = [abi for abi in DSProxyFactory.abi if abi.get('name') == 'Created'][0] event_data = get_event_data(log_created_abi, event) return LogCreated(event_data) else: raise Exception(f'[from_event] Invalid topic in {event}')
def get_event_data(self, event_name, tx_hash): tx_logs = self.w3.eth.getTransactionReceipt(tx_hash)['logs'] event_abi = self.contract._find_matching_event_abi(event_name) matched = [] for log in tx_logs: try: d = get_event_data(event_abi, log) except Exception as e: continue matched.append(d) return matched
def _decode_event_log(self, event: EventAbi, log) -> EventLog: data = get_event_data(event.abi, log) args = [] for inp in event.abi["inputs"]: args.append(data["args"][inp["name"]]) return EventLog(unitname=event.unitname, contractname=event.contractname, name=event.name, address=log["address"], args=args, data=data)
def from_event(cls, event: dict, contract_abi: list): assert isinstance(event, dict) assert isinstance(contract_abi, list) topics = event.get('topics') if topics: log_note_abi = [abi for abi in contract_abi if abi.get('name') == 'LogNote'][0] event_data = get_event_data(log_note_abi, event) return LogNote(event_data) else: logging.warning(f'[from_event] Invalid topic in {event}')
def from_event(cls, event: dict): assert (isinstance(event, dict)) topics = event.get('topics') if topics and topics[ 0] == '0x0d0b9391970d9a25552f37d436d2aae2925e2bfe1b2a923754bada030c498cb3': log_fill_abi = [ abi for abi in ZrxExchange.abi if abi.get('name') == 'LogFill' ][0] event_data = get_event_data(log_fill_abi, event) return LogFill(event_data)
def from_event(cls, event: dict): assert (isinstance(event, dict)) topics = event.get('topics') if topics and topics[ 0] == '0x3383e3357c77fd2e3a4b30deea81179bc70a795d053d14d5b7f2f01d0fd4596f': log_take_abi = [ abi for abi in SimpleMarket.abi if abi.get('name') == 'LogTake' ][0] event_data = get_event_data(log_take_abi, event) return LogTake(event_data)
def from_event(cls, event: dict, contract_abi: list): assert isinstance(event, dict) assert isinstance(contract_abi, list) log_note_abi = [ abi for abi in contract_abi if abi.get('name') == 'LogNote' ][0] try: event_data = get_event_data(log_note_abi, event) return LogNote(event_data) except ValueError: # event is not a LogNote return None
def _make_order_id_result_function(receipt): receipt_logs = receipt['logs'] if receipt_logs is not None: for receipt_log in receipt_logs: if len(receipt_log['topics']) > 0 and receipt_log['topics'][ 0] == '0x773ff502687307abfa024ac9f62f9752a0d210dac2ffd9a29e38e12e2ea82c82': log_make_abi = [ abi for abi in SimpleMarket.abi if abi.get('name') == 'LogMake' ][0] event_data = get_event_data(log_make_abi, receipt_log) return bytes_to_int(event_data['args']['id']) return None
def decode_log(self, log): """Decodes a retrieved relevant log. Decoding is performed with the `web3.utils.events.get_event_data` function. Args: log (:obj:`dict`): the event log to decode Returns: The decoded log. """ log_topic = log['topics'][0] return log_topic, get_event_data( self.topics_map[log_topic]['EVENT_ABI'], log)
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 set_log_data(self, log): log['args'] = get_event_data(self.event_abi, log)['args'] log['event'] = self.event_name return log