class ExportTokenTransfersJob(BaseJob): def __init__(self, start_block, end_block, batch_size, web3, item_exporter, max_workers, tokens=None): validate_range(start_block, end_block) self.start_block = start_block self.end_block = end_block self.web3 = web3 self.tokens = tokens self.item_exporter = item_exporter self.batch_work_executor = BatchWorkExecutor(batch_size, max_workers) self.receipt_log_mapper = EthReceiptLogMapper() self.token_transfer_mapper = EthTokenTransferMapper() self.token_transfer_extractor = EthTokenTransferExtractor() def _start(self): self.item_exporter.open() def _export(self): self.batch_work_executor.execute( range(self.start_block, self.end_block + 1), self._export_batch, total_items=self.end_block - self.start_block + 1) def _export_batch(self, block_number_batch): assert len(block_number_batch) > 0 # https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs filter_params = { 'fromBlock': block_number_batch[0], 'toBlock': block_number_batch[-1], 'topics': [TRANSFER_EVENT_TOPIC] } if self.tokens is not None and len(self.tokens) > 0: filter_params['address'] = self.tokens event_filter = self.web3.eth.filter(filter_params) events = event_filter.get_all_entries() for event in events: log = self.receipt_log_mapper.web3_dict_to_receipt_log(event) token_transfer = self.token_transfer_extractor.extract_transfer_from_log( log) if token_transfer is not None: self.item_exporter.export_item( self.token_transfer_mapper.token_transfer_to_dict( token_transfer)) self.web3.eth.uninstallFilter(event_filter.filter_id) def _end(self): self.batch_work_executor.shutdown() self.item_exporter.close()
class ExportErc20TransfersJob(BatchExportJob): def __init__(self, start_block, end_block, batch_size, web3, output, max_workers=5, tokens=None, fields_to_export=FIELDS_TO_EXPORT): super().__init__(start_block, end_block, batch_size, max_workers) self.web3 = web3 self.output = output self.tokens = tokens self.fields_to_export = fields_to_export self.receipt_log_mapper = EthReceiptLogMapper() self.erc20_transfer_mapper = EthErc20TransferMapper() self.erc20_processor = EthErc20Processor() self.output_file = None self.exporter = None def _start(self): super()._start() self.output_file = get_file_handle(self.output, binary=True, create_parent_dirs=True) self.exporter = CsvItemExporter(self.output_file, fields_to_export=self.fields_to_export) def _export_batch(self, batch_start, batch_end): # https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs filter_params = { 'fromBlock': batch_start, 'toBlock': batch_end, 'topics': [TRANSFER_EVENT_TOPIC] } if self.tokens is not None and len(self.tokens) > 0: filter_params['address'] = self.tokens event_filter = self.web3.eth.filter(filter_params) events = event_filter.get_all_entries() for event in events: log = self.receipt_log_mapper.web3_dict_to_receipt_log(event) erc20_transfer = self.erc20_processor.filter_transfer_from_log(log) if erc20_transfer is not None: self.exporter.export_item( self.erc20_transfer_mapper.erc20_transfer_to_dict( erc20_transfer)) self.web3.eth.uninstallFilter(event_filter.filter_id) def _end(self): super()._end() close_silently(self.output_file)
class ExportErc20TransfersJob(BatchExportJob): def __init__(self, start_block, end_block, batch_size, web3, item_exporter, max_workers, tokens=None): super().__init__(start_block, end_block, batch_size, max_workers) self.web3 = web3 self.tokens = tokens self.item_exporter = item_exporter self.receipt_log_mapper = EthReceiptLogMapper() self.erc20_transfer_mapper = EthErc20TransferMapper() self.erc20_processor = EthErc20Processor() def _start(self): super()._start() self.item_exporter.open() def _export_batch(self, batch_start, batch_end): # https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs filter_params = { 'fromBlock': batch_start, 'toBlock': batch_end, 'topics': [TRANSFER_EVENT_TOPIC] } if self.tokens is not None and len(self.tokens) > 0: filter_params['address'] = self.tokens event_filter = self.web3.eth.filter(filter_params) events = event_filter.get_all_entries() for event in events: log = self.receipt_log_mapper.web3_dict_to_receipt_log(event) erc20_transfer = self.erc20_processor.filter_transfer_from_log(log) if erc20_transfer is not None: self.item_exporter.export_item( self.erc20_transfer_mapper.erc20_transfer_to_dict( erc20_transfer)) self.web3.eth.uninstallFilter(event_filter.filter_id) def _end(self): super()._end() self.item_exporter.close()
class ExportOriginJob(BaseJob): def __init__(self, start_block, end_block, batch_size, web3, ipfs_client, marketplace_listing_exporter, shop_product_exporter, max_workers): validate_range(start_block, end_block) self.start_block = start_block self.end_block = end_block self.web3 = web3 self.marketplace_listing_exporter = marketplace_listing_exporter self.shop_product_exporter = shop_product_exporter self.batch_work_executor = BatchWorkExecutor(batch_size, max_workers) self.event_extractor = OriginEventExtractor(ipfs_client) self.receipt_log_mapper = EthReceiptLogMapper() self.marketplace_listing_mapper = OriginMarketplaceListingMapper() self.shop_listing_mapper = OriginShopProductMapper() def _start(self): self.marketplace_listing_exporter.open() self.shop_product_exporter.open() def _export(self): self.batch_work_executor.execute( range(self.start_block, self.end_block + 1), self._export_batch, total_items=self.end_block - self.start_block + 1) def _export_batch(self, block_number_batch): assert len(block_number_batch) > 0 from_block = block_number_batch[0] to_block = block_number_batch[-1] # Nothing to process if the block range is older than the V0 marketplace contract's epoch. if to_block < ORIGIN_MARKETPLACE_V0_BLOCK_NUMBER_EPOCH: return # Determine the version and address of the marketplace contract to query based on the block range. batches = [] if to_block < ORIGIN_MARKETPLACE_V1_BLOCK_NUMBER_EPOCH or from_block >= ORIGIN_MARKETPLACE_V1_BLOCK_NUMBER_EPOCH: # The block range falls within a single version of the marketplace contract. version = '000' if to_block < ORIGIN_MARKETPLACE_V1_BLOCK_NUMBER_EPOCH else '001' address = ORIGIN_MARKETPLACE_V0_CONTRACT_ADDRESS if version == '000' else ORIGIN_MARKETPLACE_V1_CONTRACT_ADDRESS batches.append({ 'contract_address': address, 'contract_version': version, 'from_block': from_block, 'to_block': to_block }) else: # The block range spans across 2 versions of the marketplace contract. batches.append({ 'contract_address': ORIGIN_MARKETPLACE_V0_CONTRACT_ADDRESS, 'contract_version': '000', 'from_block': from_block, 'to_block': ORIGIN_MARKETPLACE_V1_BLOCK_NUMBER_EPOCH - 1 }) batches.append({ 'contract_address': ORIGIN_MARKETPLACE_V1_CONTRACT_ADDRESS, 'contract_version': '001', 'from_block': ORIGIN_MARKETPLACE_V1_BLOCK_NUMBER_EPOCH, 'to_block': to_block }) for batch in batches: # https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs filter_params = { 'address': batch['contract_address'], 'fromBlock': batch['from_block'], 'toBlock': batch['to_block'] } event_filter = self.web3.eth.filter(filter_params) events = event_filter.get_all_entries() for event in events: log = self.receipt_log_mapper.web3_dict_to_receipt_log(event) listing, shop_products = self.event_extractor.extract_event_from_log( log, batch['contract_version']) if listing: item = self.marketplace_listing_mapper.listing_to_dict( listing) self.marketplace_listing_exporter.export_item(item) for product in shop_products: item = self.shop_listing_mapper.product_to_dict(product) self.shop_product_exporter.export_item(item) self.web3.eth.uninstallFilter(event_filter.filter_id) def _end(self): self.batch_work_executor.shutdown() self.marketplace_listing_exporter.close() self.shop_product_exporter.close()
class ExportErc20TransfersJob(BatchExportJob): def __init__(self, start_block, end_block, batch_size, web3, output, max_workers=5, tokens=None, fields_to_export=FIELDS_TO_EXPORT): super().__init__(start_block, end_block, batch_size, max_workers) self.web3 = web3 self.output = output self.tokens = tokens self.fields_to_export = fields_to_export self.receipt_log_mapper = EthReceiptLogMapper() self.erc20_transfer_mapper = EthErc20TransferMapper() self.erc20_processor = EthErc20Processor() self.ethTransactionMapper = EthTransactionMapper() self.output_file = None # self.exporter = None self.start_block = start_block def _start(self): super()._start() self.output_file = get_file_handle(self.output, binary=True, create_parent_dirs=True) # self.exporter = CsvItemExporter(self.output_file, fields_to_export=self.fields_to_export) def _export_batch(self, batch_start, batch_end): # https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs filter_params = { 'fromBlock': batch_start, 'toBlock': batch_end, 'topics': [TRANSFER_EVENT_TOPIC] } if self.tokens is not None and len(self.tokens) > 0: filter_params['address'] = self.tokens event_filter = self.web3.eth.filter(filter_params) events = event_filter.get_all_entries() for event in events: log = self.receipt_log_mapper.web3_dict_to_receipt_log(event) erc20_transfer = self.erc20_processor.filter_transfer_from_log(log) if erc20_transfer is not None: # self.exporter.export_item(self.erc20_transfer_mapper.erc20_transfer_to_dict(erc20_transfer)) erc20_transfer_dict = self.erc20_transfer_mapper.erc20_transfer_to_dict( erc20_transfer) print(erc20_transfer_dict) erc20_transfer_dict["erc20_value"] = str( erc20_transfer_dict["erc20_value"]) block = self.web3.eth.getBlock( erc20_transfer_dict["erc20_block_number"]) erc20_transfer_dict["timestamp"] = block.timestamp receipt = self.web3.eth.getTransactionReceipt( erc20_transfer_dict.get("erc20_tx_hash")) receipt_dict = self.erc20_transfer_mapper.erc20_receipt_transfer_to_dict( receipt) transaction = self.web3.eth.getTransaction( erc20_transfer_dict.get("erc20_tx_hash")) transaction_dict = self.erc20_transfer_mapper.transaction_to_dict( transaction) erc20_transfer_dict["gasUsed"] = receipt_dict.get("gasUsed") erc20_transfer_dict["gasPrice"] = transaction_dict.get( "gasPrice") erc20_transfer_dict["status"] = 0 # 0 fail if receipt_dict.get( "blockNumber") is not None and receipt_dict.get( "gasUsed") <= transaction_dict.get("gas"): erc20_transfer_dict["status"] = 1 # 1 success if erc20_transfers.find_one( {"erc20_tx_hash": erc20_transfer_dict['erc20_tx_hash'] }) is None: erc20_transfers.insert(erc20_transfer_dict) erc20_receipt.insert(receipt_dict) erc20_transaction.insert(transaction_dict) self.web3.eth.uninstallFilter(event_filter.filter_id) def _end(self): super()._end() close_silently(self.output_file) blockConfig = eth_config.find_one({'config_id': 1}) blockConfig["export_flag"] = False blockConfig["blockid"] = self.start_block eth_config.save(blockConfig)
class ExportErc20TransfersJob(BaseJob): def __init__(self, start_block, end_block, batch_size, web3, output, max_workers=5, tokens=None, fields_to_export=FIELDS_TO_EXPORT): self.start_block = start_block self.end_block = end_block self.batch_size = batch_size self.web3 = web3 self.output = output self.max_workers = max_workers self.tokens = tokens self.fields_to_export = fields_to_export self.receipt_log_mapper = EthReceiptLogMapper() self.erc20_transfer_mapper = EthErc20TransferMapper() self.erc20_processor = EthErc20Processor() self.output_file = None self.exporter = None self.executor: FailSafeExecutor = None def _start(self): # Using bounded executor prevents unlimited queue growth # and allows monitoring in-progress futures and failing fast in case of errors. self.executor = FailSafeExecutor(BoundedExecutor(1, self.max_workers)) self.output_file = get_file_handle(self.output, binary=True) self.exporter = CsvItemExporter(self.output_file, fields_to_export=self.fields_to_export) def _export(self): for batch_start, batch_end in split_to_batches(self.start_block, self.end_block, self.batch_size): self.executor.submit(self._fail_safe_export_batch, batch_start, batch_end) def _fail_safe_export_batch(self, batch_start, batch_end): try: self._export_batch(batch_start, batch_end) except (Timeout, OSError): # try exporting one by one for block_number in range(batch_start, batch_end + 1): self._export_batch(block_number, block_number) def _export_batch(self, batch_start, batch_end): filter_params = { 'fromBlock': batch_start, 'toBlock': batch_end, 'topics': [TRANSFER_EVENT_TOPIC] } if self.tokens is not None and len(self.tokens) > 0: filter_params['address'] = self.tokens event_filter = self.web3.eth.filter(filter_params) events = event_filter.get_all_entries() for event in events: log = self.receipt_log_mapper.web3_dict_to_receipt_log(event) erc20_transfer = self.erc20_processor.filter_transfer_from_log(log) if erc20_transfer is not None: self.exporter.export_item( self.erc20_transfer_mapper.erc20_transfer_to_dict( erc20_transfer)) self.web3.eth.uninstallFilter(event_filter.filter_id) def _end(self): self.executor.shutdown() close_silently(self.output_file)