def _get_theme_lst(theme_input): theme_lst = [] if isinstance(theme_input, str): theme_lst.append(theme_input) elif isinstance(theme_input, list): for theme in theme_input: if not isinstance(theme, str): raise SciplotException( "Incorrect theme input type in list for theme '" + str(theme) + "': '" + str(type(theme_input)) + "'. Correct input type is 'str'.") theme_lst = theme_input else: raise SciplotException("Incorrect theme input type: '" + str(type(theme_input)) + "'. Correct input type is 'str' or 'list'.") # Remove double entries and make theme inputs lowercase theme_lst = [theme.lower() for theme in OrderedDict.fromkeys(theme_lst)] return theme_lst
def make_table(key): try: key = str(key) except Exception as e: print("Invalid input! Cannot convert to string!!!") print(e) # Build the encryption table using the key table = (key + ALPHABET).lower() # Remove invalid characters table = re.sub(r"[\W]", "", table) # Turn the string into an ordered dictionary to remove duplicates # then read its keys and make it into a string again table = "".join(OrderedDict.fromkeys(table).keys()) # The extended table (english alphabet + numbers) has 36 characters # Recovering the index of a character is as easy as dividing its # position by 6 (floor is the row) and getting the rest (column) return table
def txs_create_or_update_from_tx_hashes(self, tx_hashes: List[Union[str, bytes]]) -> List['EthereumTx']: # Search first in database ethereum_txs_dict = OrderedDict.fromkeys([HexBytes(tx_hash).hex() for tx_hash in tx_hashes]) db_ethereum_txs = EthereumTx.objects.filter(tx_hash__in=tx_hashes).exclude(block=None) for db_ethereum_tx in db_ethereum_txs: ethereum_txs_dict[db_ethereum_tx.tx_hash] = db_ethereum_tx # Retrieve from the node the txs missing from database tx_hashes_not_in_db = [tx_hash for tx_hash, ethereum_tx in ethereum_txs_dict.items() if not ethereum_tx] if not tx_hashes_not_in_db: return list(ethereum_txs_dict.values()) self.ethereum_client = EthereumClientProvider() # Get receipts for hashes not in db tx_receipts = [] for tx_hash, tx_receipt in zip(tx_hashes_not_in_db, self.ethereum_client.get_transaction_receipts(tx_hashes_not_in_db)): tx_receipt = tx_receipt or self.ethereum_client.get_transaction_receipt(tx_hash) # Retry fetching if failed if not tx_receipt: raise TransactionNotFoundException(f'Cannot find tx-receipt with tx-hash={HexBytes(tx_hash).hex()}') elif tx_receipt.get('blockNumber') is None: raise TransactionWithoutBlockException(f'Cannot find blockNumber for tx-receipt with ' f'tx-hash={HexBytes(tx_hash).hex()}') else: tx_receipts.append(tx_receipt) # Get transactions for hashes not in db txs = self.ethereum_client.get_transactions(tx_hashes_not_in_db) block_numbers = set() for tx_hash, tx in zip(tx_hashes_not_in_db, txs): tx = tx or self.ethereum_client.get_transaction(tx_hash) # Retry fetching if failed if not tx: raise TransactionNotFoundException(f'Cannot find tx with tx-hash={HexBytes(tx_hash).hex()}') elif tx.get('blockNumber') is None: raise TransactionWithoutBlockException(f'Cannot find blockNumber for tx with ' f'tx-hash={HexBytes(tx_hash).hex()}') block_numbers.add(tx['blockNumber']) blocks = self.ethereum_client.get_blocks(block_numbers) block_dict = {} for block_number, block in zip(block_numbers, blocks): block = block or self.ethereum_client.get_block(block_number) # Retry fetching if failed if not block: raise BlockNotFoundException(f'Block with number={block_number} was not found') assert block_number == block['number'] block_dict[block['number']] = block # Create new transactions or update them if they have no receipt current_block_number = self.ethereum_client.current_block_number for tx, tx_receipt in zip(txs, tx_receipts): block = block_dict.get(tx['blockNumber']) confirmed = (current_block_number - block['number']) >= self.eth_reorg_blocks ethereum_block: EthereumBlock = EthereumBlock.objects.get_or_create_from_block(block, confirmed=confirmed) if HexBytes(ethereum_block.block_hash) != block['hash']: raise EthereumBlockHashMismatch(f'Stored block={ethereum_block.number} ' f'with hash={ethereum_block.block_hash} ' f'is not marching retrieved hash={block["hash"].hex()}') try: ethereum_tx = EthereumTx.objects.get(tx_hash=tx['hash']) # For txs stored before being mined ethereum_tx.update_with_block_and_receipt(ethereum_block, tx_receipt) ethereum_txs_dict[ethereum_tx.tx_hash] = ethereum_tx except EthereumTx.DoesNotExist: ethereum_tx = EthereumTx.objects.create_from_tx_dict(tx, tx_receipt=tx_receipt, ethereum_block=ethereum_block) ethereum_txs_dict[HexBytes(ethereum_tx.tx_hash).hex()] = ethereum_tx return list(ethereum_txs_dict.values())
def remove_duplicates(sequence: Iterable) -> list: return list(OrderedDict.fromkeys(sequence))
def unique(lst: List[Any]) -> List[Any]: """uniquify list while preserving order""" return list(OrderedDict.fromkeys(lst))
def txs_create_or_update_from_tx_hashes( self, tx_hashes: Collection[Union[str, bytes]]) -> List["EthereumTx"]: # Search first in database ethereum_txs_dict = OrderedDict.fromkeys( [HexBytes(tx_hash).hex() for tx_hash in tx_hashes]) db_ethereum_txs = EthereumTx.objects.filter( tx_hash__in=tx_hashes).exclude(block=None) for db_ethereum_tx in db_ethereum_txs: ethereum_txs_dict[db_ethereum_tx.tx_hash] = db_ethereum_tx # Retrieve from the node the txs missing from database tx_hashes_not_in_db = [ tx_hash for tx_hash, ethereum_tx in ethereum_txs_dict.items() if not ethereum_tx ] if not tx_hashes_not_in_db: return list(ethereum_txs_dict.values()) self.ethereum_client = EthereumClientProvider() # Get receipts for hashes not in db tx_receipts = [] for tx_hash, tx_receipt in zip( tx_hashes_not_in_db, self.ethereum_client.get_transaction_receipts( tx_hashes_not_in_db), ): tx_receipt = tx_receipt or self.ethereum_client.get_transaction_receipt( tx_hash) # Retry fetching if failed if not tx_receipt: raise TransactionNotFoundException( f"Cannot find tx-receipt with tx-hash={HexBytes(tx_hash).hex()}" ) if tx_receipt.get("blockHash") is None: raise TransactionWithoutBlockException( f"Cannot find blockHash for tx-receipt with " f"tx-hash={HexBytes(tx_hash).hex()}") tx_receipts.append(tx_receipt) # Get transactions for hashes not in db fetched_txs = self.ethereum_client.get_transactions( tx_hashes_not_in_db) block_hashes = set() txs = [] for tx_hash, tx in zip(tx_hashes_not_in_db, fetched_txs): tx = tx or self.ethereum_client.get_transaction( tx_hash) # Retry fetching if failed if not tx: raise TransactionNotFoundException( f"Cannot find tx with tx-hash={HexBytes(tx_hash).hex()}") if tx.get("blockHash") is None: raise TransactionWithoutBlockException( f"Cannot find blockHash for tx with " f"tx-hash={HexBytes(tx_hash).hex()}") block_hashes.add(tx["blockHash"].hex()) txs.append(tx) blocks = self.ethereum_client.get_blocks(block_hashes) block_dict = {} for block_hash, block in zip(block_hashes, blocks): block = block or self.ethereum_client.get_block( block_hash) # Retry fetching if failed if not block: raise BlockNotFoundException( f"Block with hash={block_hash} was not found") assert block_hash == block["hash"].hex() block_dict[block["hash"]] = block # Create new transactions or update them if they have no receipt current_block_number = self.ethereum_client.current_block_number for tx, tx_receipt in zip(txs, tx_receipts): block = block_dict[tx["blockHash"]] confirmed = (current_block_number - block["number"]) >= self.eth_reorg_blocks ethereum_block: EthereumBlock = ( EthereumBlock.objects.get_or_create_from_block( block, confirmed=confirmed)) try: with transaction.atomic(): ethereum_tx = EthereumTx.objects.create_from_tx_dict( tx, tx_receipt=tx_receipt, ethereum_block=ethereum_block) ethereum_txs_dict[HexBytes( ethereum_tx.tx_hash).hex()] = ethereum_tx except IntegrityError: # Tx exists ethereum_tx = EthereumTx.objects.get(tx_hash=tx["hash"]) # For txs stored before being mined ethereum_tx.update_with_block_and_receipt( ethereum_block, tx_receipt) ethereum_txs_dict[ethereum_tx.tx_hash] = ethereum_tx return list(ethereum_txs_dict.values())