def add_settings_to_test_db( db: DBHandler, db_settings: Optional[Dict[str, Any]], ignored_assets: Optional[List[Asset]], data_migration_version: Optional[int], ) -> None: settings = { # DO not submit usage analytics during tests 'submit_usage_analytics': False, 'main_currency': DEFAULT_TESTS_MAIN_CURRENCY, } # Set the given db_settings. The pre-set values have priority unless overriden here if db_settings is not None: for key, value in db_settings.items(): settings[key] = value db.set_settings(ModifiableDBSettings(**settings)) # type: ignore if ignored_assets: for asset in ignored_assets: db.add_to_ignored_assets(asset) if data_migration_version is not None: db.conn.cursor().execute( 'INSERT OR REPLACE INTO settings(name, value) VALUES(?, ?)', ('last_data_migration', data_migration_version), ) db.conn.commit()
def _init_database( data_dir: FilePath, password: str, msg_aggregator: MessagesAggregator, db_settings: Optional[Dict[str, Any]], ignored_assets: Optional[List[Asset]], blockchain_accounts: BlockchainAccounts, ) -> DBHandler: db = DBHandler(data_dir, password, msg_aggregator) settings = { # DO not submit usage analytics during tests 'submit_usage_analytics': False, 'main_currency': DEFAULT_TESTS_MAIN_CURRENCY, } # Set the given db_settings. The pre-set values have priority unless overriden here if db_settings is not None: for key, value in db_settings.items(): settings[key] = value db.set_settings(ModifiableDBSettings(**settings)) if ignored_assets: for asset in ignored_assets: db.add_to_ignored_assets(asset) # Make sure that the fixture provided accounts are in the blockchain db.add_blockchain_accounts(SupportedBlockchain.ETHEREUM, blockchain_accounts.eth) db.add_blockchain_accounts(SupportedBlockchain.BITCOIN, blockchain_accounts.btc) return db
def _init_database( data_dir: FilePath, password: str, msg_aggregator: MessagesAggregator, db_settings: Optional[Dict[str, Any]], ignored_assets: Optional[List[Asset]], blockchain_accounts: BlockchainAccounts, include_etherscan_key: bool, ) -> DBHandler: db = DBHandler(data_dir, password, msg_aggregator) settings = { # DO not submit usage analytics during tests 'submit_usage_analytics': False, 'main_currency': DEFAULT_TESTS_MAIN_CURRENCY, } # Set the given db_settings. The pre-set values have priority unless overriden here if db_settings is not None: for key, value in db_settings.items(): settings[key] = value db.set_settings(ModifiableDBSettings(**settings)) if ignored_assets: for asset in ignored_assets: db.add_to_ignored_assets(asset) # Make sure that the fixture provided accounts are in the blockchain db.add_blockchain_accounts( SupportedBlockchain.ETHEREUM, [BlockchainAccountData(address=x) for x in blockchain_accounts.eth], ) db.add_blockchain_accounts( SupportedBlockchain.BITCOIN, [BlockchainAccountData(address=x) for x in blockchain_accounts.btc], ) if include_etherscan_key: # Add the tests only etherscan API key db.add_external_service_credentials([ ExternalServiceApiCredentials( service=ExternalService.ETHERSCAN, api_key=ApiKey('8JT7WQBB2VQP5C3416Y8X3S8GBA3CVZKP4'), ) ]) return db
def add_settings_to_test_db( db: DBHandler, db_settings: Optional[Dict[str, Any]], ignored_assets: Optional[List[Asset]], ) -> None: settings = { # DO not submit usage analytics during tests 'submit_usage_analytics': False, 'main_currency': DEFAULT_TESTS_MAIN_CURRENCY, } # Set the given db_settings. The pre-set values have priority unless overriden here if db_settings is not None: for key, value in db_settings.items(): settings[key] = value db.set_settings(ModifiableDBSettings(**settings)) # type: ignore if ignored_assets: for asset in ignored_assets: db.add_to_ignored_assets(asset)
class DataHandler(object): def __init__(self, data_directory): self.data_directory = data_directory self.db = None self.eth_tokens = get_all_eth_tokens() def unlock(self, username, password, create_new): user_data_dir = os.path.join(self.data_directory, username) if create_new: if os.path.exists(user_data_dir): raise AuthenticationError( 'User {} already exists'.format(username)) else: os.mkdir(user_data_dir) else: if not os.path.exists(user_data_dir): raise AuthenticationError( 'User {} does not exist'.format(username)) if not os.path.exists(os.path.join(user_data_dir, 'rotkehlchen.db')): # This is bad. User directory exists but database is missing. # Make a backup of the directory that user should probably remove # on his own. At the same time delete the directory so that a new # user account can be created shutil.move( user_data_dir, os.path.join(self.data_directory, 'backup_%s' % username)) raise AuthenticationError( 'User {} exists but DB is missing. Somehow must have been manually ' 'deleted or is corrupt. Please recreate the user account.'. format(username)) self.db = DBHandler(user_data_dir, username, password) self.user_data_dir = user_data_dir return user_data_dir def main_currency(self): return self.db.get_main_currency() def save_balances_data(self, data): self.db.write_balances_data(data) def write_owned_eth_tokens(self, tokens): self.db.write_owned_tokens(tokens) def add_blockchain_account(self, blockchain, account): self.db.add_blockchain_account(blockchain, account) def remove_blockchain_account(self, blockchain, account): self.db.remove_blockchain_account(blockchain, account) def add_ignored_asset(self, asset): ignored_assets = self.db.get_ignored_assets() if asset in ignored_assets: return False, '%s already in ignored assets' % asset self.db.add_to_ignored_assets(asset) return True, '' def remove_ignored_asset(self, asset): ignored_assets = self.db.get_ignored_assets() if asset not in ignored_assets: return False, '%s not in ignored assets' % asset self.db.remove_from_ignored_assets(asset) return True, '' def set_premium_credentials(self, api_key, api_secret): self.db.set_rotkehlchen_premium(api_key, api_secret) def set_main_currency(self, currency, accountant): accountant.set_main_currency(currency) self.db.set_main_currency(currency) def set_settings(self, settings, accountant): given_items = list(settings.keys()) msg = '' # ignore invalid settings invalid = [] all_okay = True for x in given_items: if x not in VALID_SETTINGS: invalid.append(x) del settings[x] all_okay = False if not all_okay: msg = 'provided settings: {} are invalid'.format(','.join(invalid)) if 'main_currency' in settings: accountant.set_main_currency(settings['main_currency']) self.db.set_settings(settings) return True, msg def get_eth_accounts(self): blockchain_accounts = self.db.get_blockchain_accounts() return blockchain_accounts[ 'ETH'] if 'ETH' in blockchain_accounts else [] def set_fiat_balance(self, currency, balance): if currency not in FIAT_CURRENCIES: return False, 'Provided currency {} is unknown' if balance == 0 or balance == '': self.db.remove_fiat_balance(currency) else: try: balance = FVal(balance) except ValueError: return False, 'Provided amount is not a number' self.db.add_fiat_balance(currency, str(balance)) return True, '' def get_fiat_balances(self): return self.db.get_fiat_balances() def get_external_trades(self): return self.db.get_external_trades() def add_external_trade(self, data): timestamp, message = check_otctrade_data_valid(data) if not timestamp: return False, message self.db.add_external_trade( time=timestamp, location='external', pair=data['otc_pair'], trade_type=data['otc_type'], amount=data['otc_amount'], rate=data['otc_rate'], fee=data['otc_fee'], fee_currency=data['otc_fee_currency'], link=data['otc_link'], notes=data['otc_notes'], ) return True, '' def edit_external_trade(self, data): timestamp, message = check_otctrade_data_valid(data) if not timestamp: return False, message result, message = self.db.edit_external_trade( trade_id=data['otc_id'], time=timestamp, location='external', pair=data['otc_pair'], trade_type=data['otc_type'], amount=data['otc_amount'], rate=data['otc_rate'], fee=data['otc_fee'], fee_currency=data['otc_fee_currency'], link=data['otc_link'], notes=data['otc_notes'], ) return result, message def delete_external_trade(self, trade_id): return self.db.delete_external_trade(trade_id) def compress_and_encrypt_db(self, password): """Decrypt the DB, dump in temporary plaintextdb, compress it, and then re-encrypt it Returns a b64 encoded binary blob""" with tempfile.TemporaryDirectory() as tmpdirname: tempdb = os.path.join(tmpdirname, 'temp.db') self.db.export_unencrypted(tempdb) with open(tempdb, 'rb') as f: data_blob = f.read() original_data_hash = base64.b64encode( hashlib.sha256(data_blob).digest()).decode() compressed_data = zlib.compress(data_blob, level=9) encrypted_data = encrypt(password.encode(), compressed_data) return encrypted_data.encode(), original_data_hash def decompress_and_decrypt_db(self, password, encrypted_data): """Decrypt and decompress the encrypted data we receive from the server If successful then replace our local Database""" decrypted_data = decrypt(password.encode(), encrypted_data) decompressed_data = zlib.decompress(decrypted_data) self.db.import_unencrypted(decompressed_data, password)