示例#1
0
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()
示例#2
0
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
示例#3
0
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
示例#4
0
文件: database.py 项目: step21/rotki
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)
示例#5
0
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)