rotkehlchen.tests.utils.mock.MockResponse

Here are the examples of the python api rotkehlchen.tests.utils.mock.MockResponse taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

94 Examples 7

3 Source : test_bitfinex.py
with GNU Affero General Public License v3.0
from rotki

def test_validate_api_key_invalid_key(mock_bitfinex):
    """Test the error code related with an invalid API key/secret returns the
    tuple (False,   <  invalid api key error message>).
    """
    def mock_api_query_response(endpoint):  # pylint: disable=unused-argument
        return MockResponse(
            HTTPStatus.INTERNAL_SERVER_ERROR,
            f'["error", {API_KEY_ERROR_CODE}, "apikey: invalid"]',
        )

    with patch.object(mock_bitfinex, '_api_query', side_effect=mock_api_query_response):
        result, msg = mock_bitfinex.validate_api_key()

        assert result is False
        assert msg == API_KEY_ERROR_MESSAGE


@pytest.mark.parametrize('should_mock_current_price_queries', [True])

3 Source : test_bitstamp.py
with GNU Affero General Public License v3.0
from rotki

def test_validate_api_key_invalid_json(mock_bitstamp):
    """Test when status code is not 200, an invalid JSON response is handled."""
    def mock_api_query_response(endpoint, method='', options=None):  # pylint: disable=unused-argument  # noqa: E501
        return MockResponse(HTTPStatus.FORBIDDEN, '{"key"}')

    with patch.object(mock_bitstamp, '_api_query', side_effect=mock_api_query_response):
        result, msg = mock_bitstamp.validate_api_key()
        assert result is False
        assert msg == 'Bitstamp returned invalid JSON response: {"key"}.'


def test_validate_api_key_err_auth_nonce(mock_bitstamp):

3 Source : test_bitstamp.py
with GNU Affero General Public License v3.0
from rotki

def test_validate_api_key_success(mock_bitstamp):
    """Test when status code is 200 the response is a tuple with True (result)
    and an empty message.
    """
    def mock_api_query_response(endpoint):  # pylint: disable=unused-argument
        return MockResponse(HTTPStatus.OK, '')

    with patch.object(mock_bitstamp, '_api_query', side_effect=mock_api_query_response):
        result, msg = mock_bitstamp.validate_api_key()

    assert result is True
    assert msg == ''


def test_query_balances_invalid_json(mock_bitstamp):

3 Source : test_bitstamp.py
with GNU Affero General Public License v3.0
from rotki

def test_query_balances_invalid_json(mock_bitstamp):
    """Test an invalid JSON response raises RemoteError.
    """
    def mock_api_query_response(endpoint):  # pylint: disable=unused-argument
        return MockResponse(HTTPStatus.OK, '{"key"}')

    with patch.object(mock_bitstamp, '_api_query', side_effect=mock_api_query_response):
        with pytest.raises(RemoteError):
            mock_bitstamp.query_balances()


@pytest.mark.parametrize('response, has_reason', (

3 Source : test_bitstamp.py
with GNU Affero General Public License v3.0
from rotki

def test_query_balances_skips_not_balance_entry(mock_bitstamp):
    """Test an entry that doesn't end with `_balance` is skipped
    """
    def mock_api_query_response(endpoint):  # pylint: disable=unused-argument
        return MockResponse(HTTPStatus.OK, '{"link_available": "1.00000000"}')

    with patch.object(mock_bitstamp, '_api_query', side_effect=mock_api_query_response):
        assert mock_bitstamp.query_balances() == ({}, '')


def test_query_balances_skipped_not_asset_entry(mock_bitstamp):

3 Source : test_bitstamp.py
with GNU Affero General Public License v3.0
from rotki

def test_query_balances_skipped_not_asset_entry(mock_bitstamp):
    """Test an entry that can't instantiate Asset is skipped
    """
    def mock_api_query_response(endpoint):  # pylint: disable=unused-argument
        return MockResponse(HTTPStatus.OK, '{"bbbrrrlink_balance": "1.00000000"}')

    with patch.object(mock_bitstamp, '_api_query', side_effect=mock_api_query_response):
        assert mock_bitstamp.query_balances() == ({}, '')


def test_query_balances_skips_inquirer_error(mock_bitstamp):

3 Source : test_bitstamp.py
with GNU Affero General Public License v3.0
from rotki

def test_query_balances_skips_inquirer_error(mock_bitstamp):
    """Test an entry that can't get its USD price because of a remote error is
    skipped
    """
    inquirer = MagicMock()
    inquirer.find_usd_price.side_effect = RemoteError('test')

    def mock_api_query_response(endpoint):  # pylint: disable=unused-argument
        return MockResponse(HTTPStatus.OK, '{"link_balance": "1.00000000"}')

    with patch('rotkehlchen.exchanges.bitstamp.Inquirer', return_value=inquirer):
        with patch.object(mock_bitstamp, '_api_query', side_effect=mock_api_query_response):
            assert mock_bitstamp.query_balances() == ({}, '')


@pytest.mark.parametrize('should_mock_current_price_queries', [True])

3 Source : test_coinbase.py
with GNU Affero General Public License v3.0
from rotki

def mock_normal_coinbase_query(url, **kwargs):  # pylint: disable=unused-argument
    if 'buys' in url:
        return MockResponse(200, BUYS_RESPONSE)
    if 'sells' in url:
        return MockResponse(200, SELLS_RESPONSE)
    if 'deposits' in url:
        return MockResponse(200, DEPOSITS_RESPONSE)
    if 'withdrawals' in url:
        return MockResponse(200, WITHDRAWALS_RESPONSE)
    if 'transactions' in url:
        return MockResponse(200, TRANSACTIONS_RESPONSE)
    if 'accounts' in url:
        # keep it simple just return a single ID and ignore the rest of the fields
        return MockResponse(200, '{"data": [{"id": "5fs23"}]}')
    # else
    raise AssertionError(f'Unexpected url {url} for test')


def test_coinbase_query_trade_history(function_scope_coinbase):

3 Source : test_ftx.py
with GNU Affero General Public License v3.0
from rotki

def mock_normal_ftx_query(url: str, **kwargs):  # pylint: disable=unused-argument
    if 'fills' in url:
        return MockResponse(200, FILLS_RESPONSE)
    if 'deposits' in url:
        return MockResponse(200, DEPOSITS_RESPONSE)
    if 'withdrawals' in url:
        return MockResponse(200, WITHDRAWALS_RESPONSE)
    if 'balances' in url:
        return MockResponse(200, BALANCES_RESPONSE)
    # else
    raise AssertionError(f'Unexpected url {url} for test')


def query_ftx_and_test(

3 Source : test_gemini.py
with GNU Affero General Public License v3.0
from rotki

def mock_gemini_transfers(gemini, original_requests_request):
    def mock_requests_requests(method, url, *args, **kwargs):
        if 'transfers' not in url:
            return original_requests_request(method, url, *args, **kwargs)

        return MockResponse(200, TRANSFERS_RESPONSE)

    return patch.object(gemini.session, 'request', wraps=mock_requests_requests)


def test_gemini_query_deposits_withdrawals(sandbox_gemini):

3 Source : test_kraken.py
with GNU Affero General Public License v3.0
from rotki

def test_emptry_kraken_balance_response():
    """Balance api query returns a response without a result

    Regression test for: https://github.com/rotki/rotki/issues/2443
    """
    kraken = Kraken('kraken1', 'a', b'YW55IGNhcm5hbCBwbGVhc3VyZS4=', object(), object())

    def mock_post(url, data, **kwargs):  # pylint: disable=unused-argument
        return MockResponse(200, '{"error":[]}')

    with patch.object(kraken.session, 'post', wraps=mock_post):
        result, msg = kraken.query_balances()
        assert msg == ''
        assert result == {}


def test_timestamp_deserialization():

3 Source : test_inquirer.py
with GNU Affero General Public License v3.0
from rotki

def test_switching_to_backup_api(inquirer):
    count = 0
    original_get = requests.get

    def mock_xratescom_fail(url, timeout):  # pylint: disable=unused-argument
        nonlocal count
        count += 1
        if 'www.x-rates.com' in url:
            return MockResponse(501, '{"msg": "some error")')
        return original_get(url)

    with patch('requests.get', side_effect=mock_xratescom_fail):
        result = inquirer._query_fiat_pair(A_USD, A_EUR)
        assert result and isinstance(result, FVal)
        assert count > 1, 'requests.get should have been called more than once'


@pytest.mark.parametrize('should_mock_current_price_queries', [False])

3 Source : test_loopring.py
with GNU Affero General Public License v3.0
from rotki

def patch_loopring(loopring):
    def mock_requests_get(_url, **kwargs):  # pylint: disable=unused-argument
        response = (
            '[{"tokenId":0,"total":"8427006149700000000","locked":"0",'
            '"pending":{"withdraw":"0","deposit":"0"}},'
            '{"tokenId": 1, "total": "435974889000000000000", "locked": "0",'
            '"pending": {"withdraw": "0", "deposit": "0"}},'
            '{"tokenId":5,"total":"0","locked":"0","pending":{"withdraw":"0","deposit":"0"}},'
            '{"tokenId":70,"total":"2829249920000000000","locked":"0",'
            '"pending":{"withdraw":"0","deposit":"0"}}]'
        )
        return MockResponse(200, response)

    return patch.object(loopring.session, 'get', wraps=mock_requests_get)


def test_loopring_accountid_mapping(database):

3 Source : exchanges.py
with GNU Affero General Public License v3.0
from rotki

def mock_binance_balance_response(url, **kwargs):  # pylint: disable=unused-argument
    if 'futures' in url:
        return MockResponse(200, BINANCE_FUTURES_WALLET_RESPONSE)
    if 'lending' in url:
        return MockResponse(200, BINANCE_LENDING_WALLET_RESPONSE)
    if 'https://fapi' in url:
        return MockResponse(200, BINANCE_USDT_FUTURES_BALANCES_RESPONSE)
    if 'https://dapi' in url:
        return MockResponse(200, BINANCE_COIN_FUTURES_BALANCES_RESPONSE)
    if 'bswap/liquidity' in url:
        return MockResponse(200, BINANCE_POOL_BALANCES_RESPONSE)

    # else
    return MockResponse(200, BINANCE_BALANCES_RESPONSE)


def patch_binance_balances_query(binance: 'Binance'):

3 Source : exchanges.py
with GNU Affero General Public License v3.0
from rotki

def patch_poloniex_balances_query(poloniex: 'Poloniex'):
    def mock_poloniex_asset_return(url, *args, **kwargs):  # pylint: disable=unused-argument
        return MockResponse(200, POLONIEX_BALANCES_RESPONSE)

    poloniex_patch = patch.object(poloniex.session, 'post', side_effect=mock_poloniex_asset_return)
    return poloniex_patch

# # -- Test Exchange Objects creation --


def create_test_coinbase(

3 Source : premium.py
with GNU Affero General Public License v3.0
from rotki

def mock_query_last_metadata(last_modify_ts, data_hash, data_size):
    def do_mock_query_last_metadata(url, data, timeout):  # pylint: disable=unused-argument
        assert len(data) == 1
        assert 'nonce' in data
        assert timeout == ROTKEHLCHEN_SERVER_TIMEOUT
        payload = (
            f'{{"upload_ts": 1337, '
            f'"last_modify_ts": {last_modify_ts}, '
            f'"data_hash": "{data_hash}",'
            f'"data_size": {data_size}}}'
        )
        return MockResponse(200, payload)

    return do_mock_query_last_metadata


def mock_get_saved_data(saved_data):

3 Source : premium.py
with GNU Affero General Public License v3.0
from rotki

def mock_get_saved_data(saved_data):
    def do_mock_get_saved_data(url, data, timeout):  # pylint: disable=unused-argument
        assert len(data) == 1
        assert 'nonce' in data
        assert timeout == ROTKEHLCHEN_SERVER_TIMEOUT
        decoded_data = None if saved_data is None else saved_data.decode()
        payload = f'{{"data": {json.dumps(decoded_data)}}}'
        return MockResponse(200, payload)

    return do_mock_get_saved_data


def create_patched_requests_get_for_premium(

0 Source : test_assets_updates.py
with GNU Affero General Public License v3.0
from rotki

def mock_asset_updates(original_requests_get, latest: int, updates: Dict[str, Any], sql_actions: Dict[str, str]):  # noqa: E501

    def mock_requests_get(url, *args, **kwargs):  # pylint: disable=unused-argument
        if 'github' not in url:
            return original_requests_get(url, *args, **kwargs)

        if 'updates/info.json' in url:
            response = f'{{"latest": {latest}, "updates": {json.dumps(updates)}}}'
        elif 'updates.sql' in url:
            match = re.search(r'.*/(\d+)/updates.sql', url)
            assert match, f'Couldnt extract version from {url}'
            version = match.group(1)
            action = sql_actions.get(version)
            assert action is not None, f'Could not find SQL action for version {version}'
            response = action
        else:
            raise AssertionError(f'Unrecognized argument url for assets update mock in tests: {url}')  # noqa: E501

        return MockResponse(200, response)

    return patch('requests.get', side_effect=mock_requests_get)


@pytest.mark.parametrize('use_clean_caching_directory', [True])

0 Source : test_ethereum_transactions.py
with GNU Affero General Public License v3.0
from rotki

def test_query_transactions(rotkehlchen_api_server):
    """Test that querying the ethereum transactions endpoint works as expected.
    Also tests that requesting for transaction decoding works.

    This test uses real data.
    """
    async_query = random.choice([False, True])
    rotki = rotkehlchen_api_server.rest_api.rotkehlchen
    # Check that we get all transactions
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            'ethereumtransactionsresource',
        ), json={'async_query': async_query},
    )
    if async_query:
        task_id = assert_ok_async_response(response)
        outcome = wait_for_async_task(rotkehlchen_api_server, task_id)
        assert outcome['message'] == ''
        result = outcome['result']
    else:
        result = assert_proper_response_with_result(response)
    expected_result = EXPECTED_AFB7_TXS + EXPECTED_4193_TXS
    expected_result.sort(key=lambda x: x['timestamp'])
    expected_result.reverse()

    # Make sure that all of the transactions we expect are there and in order
    # There can be more transactions (since the address can make more)
    # but this check ignores them
    previous_index = 0
    result_entries = [x['entry'] for x in result['entries']]
    assert all(x['ignored_in_accounting'] is False for x in result['entries']), 'by default nothing should be ignored'  # noqa: E501
    for entry in expected_result:
        assert entry in result_entries
        entry_idx = result_entries.index(entry)
        if previous_index != 0:
            assert entry_idx == previous_index + 1
        previous_index = entry_idx

    assert result['entries_found'] >= len(expected_result)
    assert result['entries_limit'] == FREE_ETH_TX_LIMIT

    # now let's ignore two transactions
    ignored_ids = [
        EXPECTED_AFB7_TXS[2]['tx_hash'] + EXPECTED_AFB7_TXS[2]['from_address'] + str(EXPECTED_AFB7_TXS[2]['nonce']),  # noqa: E501
        EXPECTED_AFB7_TXS[3]['tx_hash'] + EXPECTED_AFB7_TXS[3]['from_address'] + str(EXPECTED_AFB7_TXS[3]['nonce']),  # noqa: E501
    ]
    response = requests.put(
        api_url_for(
            rotkehlchen_api_server,
            "ignoredactionsresource",
        ), json={'action_type': 'ethereum transaction', 'action_ids': ignored_ids},
    )
    result = assert_proper_response_with_result(response)
    assert result == {'ethereum transaction': ignored_ids}

    # Check that transactions per address and in a specific time range can be
    # queried and that this is from the DB and not etherscan
    def mock_etherscan_get(url, *args, **kwargs):  # pylint: disable=unused-argument
        return MockResponse(200, "{}")
    etherscan_patch = patch.object(rotki.etherscan.session, 'get', wraps=mock_etherscan_get)
    with etherscan_patch as mock_call:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server,
                'per_address_ethereum_transactions_resource',
                address='0xaFB7ed3beBE50E0b62Fa862FAba93e7A46e59cA7',
            ), json={
                'async_query': async_query,
                'from_timestamp': 1461399856,
                'to_timestamp': 1494458860,
            },
        )
        if async_query:
            task_id = assert_ok_async_response(response)
            outcome = wait_for_async_task(rotkehlchen_api_server, task_id)
            assert outcome['message'] == ''
            result = outcome['result']
        else:
            result = assert_proper_response_with_result(response)

        assert mock_call.call_count == 0

    result_entries = [x['entry'] for x in result['entries']]
    assert result_entries == EXPECTED_AFB7_TXS[2:4][::-1]
    msg = 'the transactions we ignored have not been ignored for accounting'
    assert all(x['ignored_in_accounting'] is True for x in result['entries']), msg

    # Also check that requesting decoding of tx_hashes gets receipts and decodes events
    hashes = [EXPECTED_AFB7_TXS[0]['tx_hash'], EXPECTED_4193_TXS[0]['tx_hash']]
    response = requests.post(
        api_url_for(
            rotkehlchen_api_server,
            'ethereumtransactionsresource',
        ), json={
            'async_query': async_query,
            'tx_hashes': hashes,
        },
    )
    if async_query:
        task_id = assert_ok_async_response(response)
        outcome = wait_for_async_task(rotkehlchen_api_server, task_id)
        assert outcome['message'] == ''
        result = outcome['result']
    else:
        result = assert_proper_response_with_result(response)
    assert result is True

    dbethtx = DBEthTx(rotki.data.db)
    dbevents = DBHistoryEvents(rotki.data.db)
    event_ids = set()
    for tx_hash_hex in hashes:
        receipt = dbethtx.get_receipt(hexstring_to_bytes(tx_hash_hex))
        assert isinstance(receipt, EthereumTxReceipt) and receipt.tx_hash == hexstring_to_bytes(tx_hash_hex)  # noqa: E501
        events = dbevents.get_history_events(
            filter_query=HistoryEventFilterQuery.make(
                event_identifier=tx_hash_hex,
            ),
            has_premium=True,  # for this function we don't limit. We only limit txs.
        )
        event_ids.add(events[0].identifier)
        assert len(events) == 1

    # see that if same transaction hash is requested for decoding events are not re-decoded
    response = requests.post(
        api_url_for(
            rotkehlchen_api_server,
            'ethereumtransactionsresource',
        ), json={
            'async_query': False,
            'tx_hashes': hashes,
        },
    )
    result = assert_proper_response_with_result(response)
    for tx_hash_hex in hashes:
        receipt = dbethtx.get_receipt(hexstring_to_bytes(tx_hash_hex))
        assert isinstance(receipt, EthereumTxReceipt) and receipt.tx_hash == hexstring_to_bytes(tx_hash_hex)  # noqa: E501
        events = dbevents.get_history_events(
            filter_query=HistoryEventFilterQuery.make(
                event_identifier=tx_hash_hex,
            ),
            has_premium=True,  # for this function we don't limit. We only limit txs.
        )
        assert len(events) == 1
        assert events[0].identifier in event_ids

    # Check that force re-requesting the events works
    response = requests.post(
        api_url_for(
            rotkehlchen_api_server,
            'ethereumtransactionsresource',
        ), json={
            'async_query': False,
            'ignore_cache': True,
            'tx_hashes': hashes,
        },
    )
    result = assert_proper_response_with_result(response)
    for tx_hash_hex in hashes:
        receipt = dbethtx.get_receipt(hexstring_to_bytes(tx_hash_hex))
        assert isinstance(receipt, EthereumTxReceipt) and receipt.tx_hash == hexstring_to_bytes(tx_hash_hex)  # noqa: E501
        events = dbevents.get_history_events(
            filter_query=HistoryEventFilterQuery.make(
                event_identifier=tx_hash_hex,
            ),
            has_premium=True,  # for this function we don't limit. We only limit txs.
        )
        assert len(events) == 1
        assert events[0].identifier not in event_ids


def test_request_transaction_decoding_errors(rotkehlchen_api_server):

0 Source : test_ethereum_transactions.py
with GNU Affero General Public License v3.0
from rotki

def test_query_over_10k_transactions(rotkehlchen_api_server):
    """Test that querying for an address with over 10k transactions works

    This test uses real etherscan queries and an address that we found that has > 10k transactions.

    Etherscan has a limit for 1k transactions per query and we need to make
    sure that we properly pull all data by using pagination
    """
    rotki = rotkehlchen_api_server.rest_api.rotkehlchen
    original_get = requests.get

    def mock_some_etherscan_queries(etherscan: Etherscan):
        """Just hit etherscan for the actual transations and mock all else.
        This test just needs to see that pagination works on the tx endpoint
        """
        def mocked_request_dict(url, *_args, **_kwargs):
            if '=txlistinternal&' in url:
                # don't return any internal transactions
                payload = '{"status":"1","message":"OK","result":[]}'
            elif '=tokentx&' in url:
                # don't return any token transactions
                payload = '{"status":"1","message":"OK","result":[]}'
            elif '=getblocknobytime&' in url:
                # we don't really care about this in this test so return whatever
                # payload = '{"status":"1","message":"OK","result": "1"}'
                return original_get(url)
            elif '=txlist&' in url:
                return original_get(url)
            else:
                raise AssertionError(f'Unexpected etherscan query {url} at test mock')
            return MockResponse(200, payload)

        return patch.object(etherscan.session, 'get', wraps=mocked_request_dict)

    expected_at_least = 16097  # 30/08/2020
    with mock_some_etherscan_queries(rotki.etherscan):
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server,
                'ethereumtransactionsresource',
            ),
        )

    result = assert_proper_response_with_result(response)
    assert len(result['entries']) >= expected_at_least
    assert result['entries_found'] >= expected_at_least
    assert result['entries_limit'] == -1

    # Also check some entries in the list that we know of to see that they exist
    rresult = [x['entry'] for x in result['entries'][::-1]]

    assert rresult[1]['tx_hash'] == '0xec72748b8b784380ff6fcca9b897d649a0992eaa63b6c025ecbec885f64d2ac9'  # noqa: E501
    assert rresult[1]['nonce'] == 0
    assert rresult[11201]['tx_hash'] == '0x118edf91d6d47fcc6bc9c7ceefe2ee2344e0ff3b5a1805a804fa9c9448efb746'  # noqa: E501
    assert rresult[11201]['nonce'] == 11198
    assert rresult[16172]['tx_hash'] == '0x92baec6dbf3351a1aea2371453bfcb5af898ffc8172fcf9577ca2e5335df4c71'  # noqa: E501
    assert rresult[16172]['nonce'] == 16169


def test_query_transactions_errors(rotkehlchen_api_server):

0 Source : test_ethereum_transactions.py
with GNU Affero General Public License v3.0
from rotki

def test_transaction_same_hash_same_nonce_two_tracked_accounts(
        rotkehlchen_api_server,
        ethereum_accounts,
):
    """Make sure that if we track two addresses and they send one transaction
    to each other it's not counted as duplicate in the DB but is returned
    every time by both addresses"""
    rotki = rotkehlchen_api_server.rest_api.rotkehlchen

    def mock_etherscan_transaction_response(etherscan: Etherscan, eth_accounts):
        def mocked_request_dict(url, *_args, **_kwargs):

            addr1_tx = f"""{{"blockNumber":"1","timeStamp":"1","hash":"0x9c81f44c29ff0226f835cd0a8a2f2a7eca6db52a711f8211b566fd15d3e0e8d4","nonce":"0","blockHash":"0xd3cabad6adab0b52ea632c386ea19403680571e682c62cb589b5abcd76de2159","transactionIndex":"0","from":"{eth_accounts[0]}","to":"{eth_accounts[1]}","value":"1","gas":"2000000","gasPrice":"10000000000000","isError":"0","txreceipt_status":"","input":"0x","contractAddress":"","cumulativeGasUsed":"1436963","gasUsed":"1436963","confirmations":"1"}}"""  # noqa: E501
            addr2_txs = f"""{addr1_tx}, {{"blockNumber":"2","timeStamp":"2","hash":"0x1c81f54c29ff0226f835cd0a2a2f2a7eca6db52a711f8211b566fd15d3e0e8d4","nonce":"1","blockHash":"0xd1cabad2adab0b56ea632c386ea19403680571e682c62cb589b5abcd76de2159","transactionIndex":"0","from":"{eth_accounts[1]}","to":"{make_ethereum_address()}","value":"1","gas":"2000000","gasPrice":"10000000000000","isError":"0","txreceipt_status":"","input":"0x","contractAddress":"","cumulativeGasUsed":"1436963","gasUsed":"1436963","confirmations":"1"}}"""  # noqa: E501
            if '=txlistinternal&' in url:
                # don't return any internal transactions
                payload = '{"status":"1","message":"OK","result":[]}'
            elif 'action=tokentx&' in url:
                # don't return any token transactions
                payload = '{"status":"1","message":"OK","result":[]}'
            elif '=txlist&' in url:
                if eth_accounts[0] in url:
                    tx_str = addr1_tx
                elif eth_accounts[1] in url:
                    tx_str = addr2_txs
                else:
                    raise AssertionError(
                        'Requested etherscan transactions for unknown address in tests',
                    )
                payload = f'{{"status":"1","message":"OK","result":[{tx_str}]}}'
            elif '=getblocknobytime&' in url:
                # we don't really care about this so just return whatever
                payload = '{"status":"1","message":"OK","result": "1"}'
            else:
                raise AssertionError('Got in unexpected section during test')

            return MockResponse(200, payload)

        return patch.object(etherscan.session, 'get', wraps=mocked_request_dict)

    with mock_etherscan_transaction_response(rotki.etherscan, ethereum_accounts):
        # Check that we get transaction both when we query all accounts and each one individually
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server,
                'ethereumtransactionsresource',
            ),
        )
        result = assert_proper_response_with_result(response)
        assert len(result['entries']) == 2
        assert result['entries_found'] == 2
        assert result['entries_total'] == 2

        response = requests.get(
            api_url_for(
                rotkehlchen_api_server,
                'per_address_ethereum_transactions_resource',
                address=ethereum_accounts[0],
            ),
        )
        result = assert_proper_response_with_result(response)
        assert len(result['entries']) == 1
        assert result['entries_found'] == 1
        assert result['entries_total'] == 2
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server,
                'per_address_ethereum_transactions_resource',
                address=ethereum_accounts[1],
            ),
        )
        result = assert_proper_response_with_result(response)
        assert len(result['entries']) == 2
        assert result['entries_found'] == 2
        assert result['entries_total'] == 2


@pytest.mark.parametrize('ethereum_accounts', [['0x6e15887E2CEC81434C16D587709f64603b39b545']])

0 Source : test_exchanges.py
with GNU Affero General Public License v3.0
from rotki

def test_kraken_malformed_response(rotkehlchen_api_server_with_exchanges):
    """Test that if rotki gets a malformed response from Kraken it's handled properly

    Regression test for the first part of https://github.com/rotki/rotki/issues/943
    and for https://github.com/rotki/rotki/issues/946
    """
    rotki = rotkehlchen_api_server_with_exchanges.rest_api.rotkehlchen
    kraken = try_get_first_exchange(rotki.exchange_manager, Location.KRAKEN)
    kraken.cache_ttl_secs = 0
    kraken.use_original_kraken = True
    response_data = '{"'

    def mock_kraken_return(url, *args, **kwargs):  # pylint: disable=unused-argument
        return MockResponse(200, response_data)
    kraken_patch = patch.object(kraken.session, 'post', side_effect=mock_kraken_return)

    # Test that invalid json is handled
    with kraken_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server_with_exchanges,
                "exchangebalancesresource",
                location='kraken',
            ),
        )
    assert_error_response(
        response=response,
        status_code=HTTPStatus.CONFLICT,
        contained_in_msg='Could not reach kraken due to Invalid JSON in Kraken response',
    )

    # Test that the response missing result key seen in #946 is handled properly
    response_data = '{"error": []}'
    with kraken_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server_with_exchanges,
                'exchangebalancesresource',
                location='kraken',
            ),
        )
    result = assert_proper_response_with_result(response=response)
    assert result == {}


@pytest.mark.parametrize('number_of_eth_accounts', [0])

0 Source : test_makerdao_dsr.py
with GNU Affero General Public License v3.0
from rotki

def mock_etherscan_for_dsr(
        etherscan: Etherscan,
        account1: ChecksumEthAddress,
        account2: ChecksumEthAddress,
        account3: ChecksumEthAddress,
        original_requests_get,
        params: DSRMockParameters,
) -> _patch:

    proxy1 = make_ethereum_address()
    proxy2 = make_ethereum_address()
    targets = [address_to_32byteshexstr(proxy1), address_to_32byteshexstr(proxy2), '0x0000000000000000000000000000000000000000000000000000000000000000']  # noqa: E501

    sorted_accounts = sorted(zip([account1, account2, account3], targets), key=lambda x: x[0])
    proxies = [y[1] for y in sorted_accounts]

    account1_join1_event = f"""{{"address": "{MAKERDAO_POT.address}", "topics": ["0x049878f300000000000000000000000000000000000000000000000000000000", "{address_to_32byteshexstr(proxy1)}", "{int_to_32byteshexstr(params.account1_join1_normalized_balance)}", "0x0000000000000000000000000000000000000000000000000000000000000000"], "data": "0x1", "blockNumber": "{hex(params.account1_join1_blocknumber)}", "timeStamp": "{hex(blocknumber_to_timestamp(params.account1_join1_blocknumber))}", "gasPrice": "0x1", "gasUsed": "0x1", "logIndex": "0x6c", "transactionHash": "0xf00", "transactionIndex": "0x79"}}"""  # noqa: E501

    account1_join1_deposit = params.account1_join1_normalized_balance * params.account1_join1_chi
    account1_join1_move_event = f"""{{"address": "{MAKERDAO_VAT.address}", "topics": ["0xbb35783b00000000000000000000000000000000000000000000000000000000", "{address_to_32byteshexstr(proxy1)}", "{MAKERDAO_POT.address}", "{int_to_32byteshexstr(account1_join1_deposit // 10 ** 27)}"], "data": "0x1", "blockNumber": "{hex(params.account1_join1_blocknumber)}", "timeStamp": "{hex(blocknumber_to_timestamp(params.account1_join1_blocknumber))}", "gasPrice": "0x1", "gasUsed": "0x1", "logIndex": "0x6c", "transactionHash": "0xf00", "transactionIndex": "0x79"}}"""  # noqa: E501
    account1_join2_event = f"""{{"address": "{MAKERDAO_POT.address}", "topics": ["0x049878f300000000000000000000000000000000000000000000000000000000", "{address_to_32byteshexstr(proxy1)}", "{int_to_32byteshexstr(params.account1_join2_normalized_balance)}", "0x0000000000000000000000000000000000000000000000000000000000000000"], "data": "0x1", "blockNumber": "{hex(params.account1_join2_blocknumber)}", "timeStamp": "{hex(blocknumber_to_timestamp(params.account1_join2_blocknumber))}", "gasPrice": "0x1", "gasUsed": "0x1", "logIndex": "0x6c", "transactionHash": "0xf00", "transactionIndex": "0x79"}}"""  # noqa: E501
    account1_join2_deposit = params.account1_join2_normalized_balance * params.account1_join2_chi
    account1_join2_move_event = f"""{{"address": "{MAKERDAO_VAT.address}", "topics": ["0xbb35783b00000000000000000000000000000000000000000000000000000000", "{address_to_32byteshexstr(proxy1)}", "{MAKERDAO_POT.address}", "{int_to_32byteshexstr(account1_join2_deposit // 10 ** 27)}"], "data": "0x1", "blockNumber": "{hex(params.account1_join1_blocknumber)}", "timeStamp": "{hex(blocknumber_to_timestamp(params.account1_join2_blocknumber))}", "gasPrice": "0x1", "gasUsed": "0x1", "logIndex": "0x6c", "transactionHash": "0xf00", "transactionIndex": "0x79"}}"""  # noqa: E501

    account1_exit1_event = f"""{{"address": "{MAKERDAO_POT.address}", "topics": ["0x7f8661a100000000000000000000000000000000000000000000000000000000", "{address_to_32byteshexstr(proxy1)}", "{int_to_32byteshexstr(params.account1_exit1_normalized_balance)}", "0x0000000000000000000000000000000000000000000000000000000000000000"], "data": "0x1", "blockNumber": "{hex(params.account1_exit1_blocknumber)}", "timeStamp": "{hex(blocknumber_to_timestamp(params.account1_exit1_blocknumber))}", "gasPrice": "0x1", "gasUsed": "0x1", "logIndex": "0x6c", "transactionHash": "0xf00", "transactionIndex": "0x79"}}"""  # noqa: E501
    account1_exit1_withdrawal = (
        params.account1_exit1_normalized_balance * params.account1_exit1_chi
    )
    account1_exit1_move_event = f"""{{"address": "{MAKERDAO_VAT.address}", "topics": ["0xbb35783b00000000000000000000000000000000000000000000000000000000", "{MAKERDAO_POT.address}", "{address_to_32byteshexstr(proxy1)}", "{int_to_32byteshexstr(account1_exit1_withdrawal // 10 ** 27)}"], "data": "0x1", "blockNumber": "{hex(params.account1_exit1_blocknumber)}", "timeStamp": "{hex(blocknumber_to_timestamp(params.account1_exit1_blocknumber))}", "gasPrice": "0x1", "gasUsed": "0x1", "logIndex": "0x6c", "transactionHash": "0xf00", "transactionIndex": "0x79"}}"""  # noqa: E501
    account2_join1_event = f"""{{"address": "{MAKERDAO_POT.address}", "topics": ["0x049878f300000000000000000000000000000000000000000000000000000000", "{address_to_32byteshexstr(proxy2)}", "{int_to_32byteshexstr(params.account2_join1_normalized_balance)}", "0x0000000000000000000000000000000000000000000000000000000000000000"], "data": "0x1", "blockNumber": "{hex(params.account2_join1_blocknumber)}", "timeStamp": "{hex(blocknumber_to_timestamp(params.account2_join1_blocknumber))}", "gasPrice": "0x1", "gasUsed": "0x1", "logIndex": "0x6c", "transactionHash": "0xf00", "transactionIndex": "0x79"}}"""  # noqa: E501

    account2_join1_deposit = params.account2_join1_normalized_balance * params.account2_join1_chi
    account2_join1_move_event = f"""{{"address": "{MAKERDAO_VAT.address}", "topics": ["0xbb35783b00000000000000000000000000000000000000000000000000000000", "{address_to_32byteshexstr(proxy2)}", "{MAKERDAO_POT.address}", "{int_to_32byteshexstr(account2_join1_deposit // 10 ** 27)}"], "data": "0x1", "blockNumber": "{hex(params.account2_join1_blocknumber)}", "timeStamp": "{hex(blocknumber_to_timestamp(params.account2_join1_blocknumber))}", "gasPrice": "0x1", "gasUsed": "0x1", "logIndex": "0x6c", "transactionHash": "0fx00", "transactionIndex": "0x79"}}"""  # noqa: E501

    # Not sure how to convince pylint that this ChecksumEthAddress IS a subscriptable object
    proxy1_contents = proxy1[2:].lower()  # pylint: disable=unsubscriptable-object
    proxy2_contents = proxy2[2:].lower()  # pylint: disable=unsubscriptable-object

    def mock_requests_get(url, *args, **kwargs):
        if 'etherscan.io/api?module=proxy&action=eth_blockNumber' in url:
            response = f'{{"status":"1","message":"OK","result":"{TEST_LATEST_BLOCKNUMBER_HEX}"}}'
        elif 'etherscan.io/api?module=proxy&action=eth_call' in url:
            to_address = url.split(
                'https://api.etherscan.io/api?module=proxy&action=eth_call&to=',
            )[1][:42]
            input_data = url.split('data=')[1].split('&apikey')[0]
            if to_address == DS_PROXY_REGISTRY.address:
                if not input_data.startswith('0xc4552791'):
                    raise AssertionError(
                        'Call to unexpected method of DSR ProxyRegistry during tests',
                    )

                # It's a call to proxy registry. Return the mapping
                if account1[2:].lower() in input_data:
                    proxy_account = address_to_32byteshexstr(proxy1)
                elif account2[2:].lower() in input_data:
                    proxy_account = address_to_32byteshexstr(proxy2)
                else:
                    proxy_account = '0x' + '0' * 64
                response = f'{{"status":"1","message":"OK","result":"{proxy_account}"}}'
            elif to_address == ETH_MULTICALL.address:
                web3 = Web3()
                contract = web3.eth.contract(address=ETH_MULTICALL.address, abi=ETH_MULTICALL.abi)
                data = url.split('data=')[1]
                if '&apikey' in data:
                    data = data.split('&apikey')[0]

                fn_abi = contract.functions.abi[1]
                output_types = get_abi_output_types(fn_abi)
                args = [1, proxies]
                result = '0x' + web3.codec.encode_abi(output_types, args).hex()
                response = f'{{"status":"1","message":"OK","result":"{result}"}}'
            elif to_address == MAKERDAO_POT.address:
                if input_data.startswith('0x0bebac86'):  # pie
                    if proxy1_contents in input_data:
                        result = int_to_32byteshexstr(params.account1_current_normalized_balance)
                    elif proxy2_contents in input_data:
                        result = int_to_32byteshexstr(params.account2_current_normalized_balance)
                    else:
                        # result = int_to_32byteshexstr(0)
                        raise AssertionError('Pie call for unexpected account during tests')
                elif input_data.startswith('0xc92aecc4'):  # chi
                    result = int_to_32byteshexstr(params.current_chi)
                elif input_data.startswith('0x487bf082'):  # dsr
                    result = int_to_32byteshexstr(params.current_dsr)
                else:
                    raise AssertionError(
                        'Call to unexpected method of MakerDao pot during tests',
                    )

                response = f'{{"status":"1","message":"OK","result":"{result}"}}'

            else:
                raise AssertionError(
                    f'Etherscan call to unknown contract {to_address} during tests',
                )
        elif 'etherscan.io/api?module=logs&action=getLogs' in url:
            contract_address = url.split('&address=')[1].split('&topic0')[0]
            topic0 = url.split('&topic0=')[1].split('&topic0_1')[0]
            topic1 = url.split('&topic1=')[1].split('&topic1_2')[0]
            topic2 = None
            if '&topic2=' in url:
                topic2 = url.split('&topic2=')[1].split('&')[0]
            from_block = int(url.split('&fromBlock=')[1].split('&')[0])
            to_block = int(url.split('&toBlock=')[1].split('&')[0])

            if contract_address == MAKERDAO_POT.address:
                if topic0.startswith('0x049878f3'):  # join

                    events = []
                    if proxy1_contents in topic1:
                        if from_block   <  = params.account1_join1_blocknumber  < = to_block:
                            events.append(account1_join1_event)
                        if from_block  < = params.account1_join2_blocknumber  < = to_block:
                            events.append(account1_join2_event)
                    elif proxy2_contents in topic1:
                        if from_block  < = params.account2_join1_blocknumber  < = to_block:
                            events.append(account2_join1_event)
                    else:
                        raise AssertionError(
                            f'Etherscan log query to makerdao POT contract for '
                            f'join for unknown account {topic1}',
                        )
                    response = f'{{"status":"1","message":"OK","result":[{",".join(events)}]}}'

                elif topic0.startswith('0x7f8661a1'):  # exit
                    events = []
                    if proxy1_contents in topic1:
                        if from_block  < = params.account1_exit1_blocknumber  < = to_block:
                            events.append(account1_exit1_event)

                    response = f'{{"status":"1","message":"OK","result":[{",".join(events)}]}}'
                else:
                    raise AssertionError('Etherscan unknown log query to makerdao POT contract')

            elif contract_address == MAKERDAO_VAT.address:
                if topic0.startswith('0xbb35783b'):  # move
                    events = []
                    if proxy1_contents in topic1:  # deposit from acc1
                        if from_block  < = params.account1_join1_blocknumber  < = to_block:
                            events.append(account1_join1_move_event)
                        if from_block  < = params.account1_join2_blocknumber  < = to_block:
                            events.append(account1_join2_move_event)
                    elif proxy2_contents in topic1:  # deposit from acc2
                        if from_block  < = params.account2_join1_blocknumber  < = to_block:
                            events.append(account2_join1_move_event)
                    elif proxy1_contents in topic2:  # withdrawal from acc1

                        if from_block  < = params.account1_exit1_blocknumber  < = to_block:
                            events.append(account1_exit1_move_event)

                    response = f'{{"status":"1","message":"OK","result":[{",".join(events)}]}}'
                else:
                    raise AssertionError('Etherscan unknown log query to makerdao VAT contract')
            elif contract_address == MAKERDAO_DAI_JOIN.address:
                events = []
                if topic0.startswith('0x3b4da69f'):  # join
                    if proxy1_contents in topic1:  # deposit from acc1
                        if from_block  < = params.account1_join1_blocknumber  < = to_block:
                            events.append(account1_join1_move_event)
                        if from_block  < = params.account1_join2_blocknumber  < = to_block:
                            events.append(account1_join2_move_event)
                    elif proxy2_contents in topic1:  # deposit from acc2
                        if from_block  < = params.account2_join1_blocknumber  < = to_block:
                            events.append(account2_join1_move_event)
                elif topic0.startswith('0xef693bed'):  # exit
                    if from_block  < = params.account1_exit1_blocknumber  < = to_block:
                        events.append(account1_exit1_move_event)
                else:
                    raise AssertionError('Etherscan unknown call to makerdao DAIJOIN contract')
                response = f'{{"status":"1","message":"OK","result":[{",".join(events)}]}}'

            else:
                raise AssertionError(
                    f'Etherscan getLogs call to unknown contract {contract_address} during tests',
                )
        else:
            return original_requests_get(url, *args, **kwargs)

        return MockResponse(200, response)

    return patch.object(etherscan.session, 'get', wraps=mock_requests_get)


def setup_tests_for_dsr(

0 Source : test_statistics.py
with GNU Affero General Public License v3.0
from rotki

def test_query_statistics_renderer(rotkehlchen_api_server, start_with_valid_premium):
    """Test that the statistics renderer endpoint works when properly queried"""
    rotki = rotkehlchen_api_server.rest_api.rotkehlchen

    if start_with_valid_premium:
        def mock_premium_get(url, *_args, **_kwargs):
            if 'last_data_metadata' in url:
                response = (
                    '{"upload_ts": 0, "last_modify_ts": 0, "data_hash": "0x0", "data_size": 0}'
                )
            else:
                response = '{"data": "codegoeshere"}'
            return MockResponse(200, response)
        premium_patch = patch.object(rotki.premium.session, 'get', mock_premium_get)
    else:
        premium_patch = contextlib.nullcontext()

    with premium_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server,
                "statisticsrendererresource",
            ),
        )
    if start_with_valid_premium:
        result = assert_proper_response_with_result(response)
        assert result == 'codegoeshere'
    else:
        assert_error_response(
            response=response,
            contained_in_msg='logged in user testuser does not have a premium subscription',
            status_code=HTTPStatus.CONFLICT,
        )

0 Source : test_binance.py
with GNU Affero General Public License v3.0
from rotki

def test_binance_query_trade_history(function_scope_binance):
    """Test that turning a binance trade as returned by the server to our format works"""
    binance = function_scope_binance

    def mock_my_trades(url, **kwargs):  # pylint: disable=unused-argument
        if 'myTrades' in url:
            if 'symbol=BNBBTC' in url:
                text = BINANCE_MYTRADES_RESPONSE
            else:
                text = '[]'
        elif 'fiat/payments' in url:
            match = TIMESTAMPS_RE.search(url)
            assert match
            groups = match.groups()
            assert len(groups) == 2
            from_ts, to_ts = [int(x) for x in groups]
            if 'transactionType=0' in url:
                if from_ts   <   1624529919000  <  to_ts:
                    text = BINANCE_FIATBUY_RESPONSE
                else:
                    text = '[]'
            elif 'transactionType=1' in url:
                if from_ts  <  1628529919000  <  to_ts:
                    text = BINANCE_FIATSELL_RESPONSE
                else:
                    text = '[]'
            else:
                raise AssertionError('Unexpected binance request in test')
        else:
            raise AssertionError('Unexpected binance request in test')

        return MockResponse(200, text)

    with patch.object(binance.session, 'get', side_effect=mock_my_trades):
        trades = binance.query_trade_history(start_ts=0, end_ts=1638529919, only_cache=False)

    expected_trades = [Trade(
        timestamp=1499865549,
        location=Location.BINANCE,
        base_asset=A_BNB,
        quote_asset=A_BTC,
        trade_type=TradeType.BUY,
        amount=FVal('12'),
        rate=FVal('4.00000100'),
        fee=FVal('10.10000000'),
        fee_currency=A_BNB,
        link='28457',
    ), Trade(
        timestamp=1624529919,
        location=Location.BINANCE,
        base_asset=A_LUNA,
        quote_asset=A_EUR,
        trade_type=TradeType.BUY,
        amount=FVal('4.462'),
        rate=FVal('4.437472'),
        fee=FVal('0.2'),
        fee_currency=A_EUR,
        link='353fca443f06466db0c4dc89f94f027a',
    ), Trade(
        timestamp=1628529919,
        location=Location.BINANCE,
        base_asset=A_ETH,
        quote_asset=A_EUR,
        trade_type=TradeType.SELL,
        amount=FVal('4.462'),
        rate=FVal('4.437472'),
        fee=FVal('0.2'),
        fee_currency=A_EUR,
        link='463fca443f06466db0c4dc89f94f027a',
    )]

    assert trades == expected_trades


def test_binance_query_trade_history_unexpected_data(function_scope_binance):

0 Source : test_binance.py
with GNU Affero General Public License v3.0
from rotki

def test_binance_query_trade_history_unexpected_data(function_scope_binance):
    """Test that turning a binance trade that contains unexpected data is handled gracefully"""
    binance = function_scope_binance
    binance.cache_ttl_secs = 0

    def mock_my_trades(url, **kwargs):  # pylint: disable=unused-argument
        if 'symbol=BNBBTC' in url or 'symbol=doesnotexist' in url:
            text = BINANCE_MYTRADES_RESPONSE
        else:
            text = '[]'

        return MockResponse(200, text)

    def query_binance_and_test(
            input_trade_str,
            expected_warnings_num,
            expected_errors_num,
            warning_str_test=None,
            error_str_test=None,
            query_specific_markets=None,
    ):
        patch_get = patch.object(binance.session, 'get', side_effect=mock_my_trades)
        patch_response = patch(
            'rotkehlchen.tests.exchanges.test_binance.BINANCE_MYTRADES_RESPONSE',
            new=input_trade_str,
        )
        binance.selected_pairs = query_specific_markets
        with patch_get, patch_response:
            trades, _ = binance.query_online_trade_history(
                start_ts=0,
                end_ts=1564301134,
            )

        assert len(trades) == 0
        errors = binance.msg_aggregator.consume_errors()
        warnings = binance.msg_aggregator.consume_warnings()
        assert len(errors) == expected_errors_num
        assert len(warnings) == expected_warnings_num
        if warning_str_test:
            assert warning_str_test in warnings[0]
        if error_str_test:
            assert error_str_test in errors[0]

    input_str = BINANCE_MYTRADES_RESPONSE.replace(
        '"qty": "12.00000000"',
        '"qty": "dsadsad"',
    )
    query_binance_and_test(input_str, expected_warnings_num=0, expected_errors_num=1)

    input_str = BINANCE_MYTRADES_RESPONSE.replace(
        '"price": "4.00000100"',
        '"price": null',
    )
    query_binance_and_test(input_str, expected_warnings_num=0, expected_errors_num=1)

    input_str = BINANCE_MYTRADES_RESPONSE.replace(
        '"symbol": "BNBBTC"',
        '"symbol": "nonexistingmarket"',
    )
    query_binance_and_test(
        input_str,
        expected_warnings_num=0,
        expected_errors_num=0,
        query_specific_markets=['doesnotexist'],
    )

    input_str = BINANCE_MYTRADES_RESPONSE.replace(
        '"time": 1499865549590',
        '"time": "sadsad"',
    )
    query_binance_and_test(input_str, expected_warnings_num=0, expected_errors_num=1)

    # Delete an entry
    input_str = BINANCE_MYTRADES_RESPONSE.replace('"isBuyer": true,', '')
    query_binance_and_test(input_str, expected_warnings_num=0, expected_errors_num=1)

    input_str = BINANCE_MYTRADES_RESPONSE.replace(
        '"commission": "10.10000000"',
        '"commission": "fdfdfdsf"',
    )
    query_binance_and_test(input_str, expected_warnings_num=0, expected_errors_num=1)

    # unsupported fee currency
    input_str = BINANCE_MYTRADES_RESPONSE.replace(
        '"commissionAsset": "BNB"',
        '"commissionAsset": "BTCB"',
    )
    query_binance_and_test(
        input_str,
        expected_warnings_num=1,
        expected_errors_num=0,
        warning_str_test='Found binance trade with unsupported asset BTCB',
    )

    # unknown fee currency
    input_str = BINANCE_MYTRADES_RESPONSE.replace(
        '"commissionAsset": "BNB"',
        '"commissionAsset": "DSDSDS"',
    )
    query_binance_and_test(
        input_str,
        expected_warnings_num=1,
        expected_errors_num=0,
        warning_str_test='Found binance trade with unknown asset DSDSDS',
    )


def test_binance_query_deposits_withdrawals(function_scope_binance):

0 Source : test_binance.py
with GNU Affero General Public License v3.0
from rotki

def test_binance_query_deposits_withdrawals(function_scope_binance):
    """Test the happy case of binance deposit withdrawal query

    NB: set `start_ts` and `end_ts` with a difference less than 90 days to
    prevent requesting with a time delta.
    """
    start_ts = 1508022000  # 2017-10-15
    # end_ts = 1508540400  # 2017-10-21 (less than 90 days since `start_ts`)
    end_ts = 1636400907
    binance = function_scope_binance

    def mock_get_deposit_withdrawal(url, **kwargs):  # pylint: disable=unused-argument
        match = TIMESTAMPS_RE.search(url)
        assert match
        groups = match.groups()
        assert len(groups) == 2
        from_ts, to_ts = [int(x) for x in groups]
        if 'capital/deposit' in url:
            if from_ts >= 1508022000000 and to_ts   <  = 1515797999999:
                response_str = BINANCE_DEPOSITS_HISTORY_RESPONSE
            else:
                response_str = '[]'
        elif 'capital/withdraw' in url:
            if from_ts  < = 1508198532000  < = to_ts:
                response_str = BINANCE_WITHDRAWALS_HISTORY_RESPONSE
            else:
                response_str = '[]'
        elif 'fiat/orders' in url:
            from_ts, to_ts = [int(x) for x in groups]
            if 'transactionType=0' in url:
                if from_ts  <  1626144956000  <  to_ts:
                    response_str = BINANCE_FIATDEPOSITS_RESPONSE
                else:
                    response_str = '[]'
            elif 'transactionType=1' in url:
                if from_ts  <  1636144956000  <  to_ts:
                    response_str = BINANCE_FIATWITHDRAWS_RESPONSE
                else:
                    response_str = '[]'
            else:
                raise AssertionError('Unexpected binance request in test')
        else:
            raise AssertionError('Unexpected binance request in test')

        return MockResponse(200, response_str)

    with patch.object(binance.session, 'get', side_effect=mock_get_deposit_withdrawal):
        movements = binance.query_online_deposits_withdrawals(
            start_ts=Timestamp(start_ts),
            end_ts=Timestamp(end_ts),
        )

    errors = binance.msg_aggregator.consume_errors()
    warnings = binance.msg_aggregator.consume_warnings()
    assert len(errors) == 0
    assert len(warnings) == 0
    assert_binance_asset_movements_result(
        movements=movements,
        location=Location.BINANCE,
        got_fiat=True,
    )


def test_binance_query_deposits_withdrawals_unexpected_data(function_scope_binance):

0 Source : test_binance.py
with GNU Affero General Public License v3.0
from rotki

def test_binance_query_deposits_withdrawals_unexpected_data(function_scope_binance):
    """Test that we handle unexpected deposit withdrawal query data gracefully

    NB: set `start_ts` and `end_ts` with a difference less than 90 days to
    prevent requesting with a time delta.
    """
    start_ts = 1508022000  # 2017-10-15
    end_ts = 1508540400  # 2017-10-21 (less than 90 days since `start_ts`)
    binance = function_scope_binance

    def mock_binance_and_query(deposits, withdrawals, expected_warnings_num, expected_errors_num):

        def mock_get_deposit_withdrawal(url, **kwargs):  # pylint: disable=unused-argument
            if 'deposit' in url:
                response_str = deposits
            else:
                response_str = withdrawals

            return MockResponse(200, response_str)

        with patch.object(binance.session, 'get', side_effect=mock_get_deposit_withdrawal):
            movements = binance.query_online_deposits_withdrawals(
                start_ts=Timestamp(start_ts),
                end_ts=Timestamp(end_ts),
            )

        if expected_errors_num == 0 and expected_warnings_num == 0:
            assert len(movements) == 1
        else:
            assert len(movements) == 0
            warnings = binance.msg_aggregator.consume_warnings()
            assert len(warnings) == expected_warnings_num
            errors = binance.msg_aggregator.consume_errors()
            assert len(errors) == expected_errors_num

    def check_permutations_of_input_invalid_data(deposits, withdrawals):
        # First make sure it works with normal data
        mock_binance_and_query(
            deposits,
            withdrawals,
            expected_warnings_num=0,
            expected_errors_num=0,
        )
        testing_deposits = "amount" in deposits

        # From here and on test unexpected data
        # invalid timestamp
        if testing_deposits:
            new_deposits = deposits.replace('1508198532000', '"dasdd"')
            new_withdrawals = withdrawals
        else:
            new_deposits = deposits
            new_withdrawals = withdrawals.replace('"2017-10-17 00:02:12"', '"dasdd"')
        mock_binance_and_query(
            new_deposits,
            new_withdrawals,
            expected_warnings_num=0,
            expected_errors_num=1,
        )

        # invalid asset
        if testing_deposits:
            new_deposits = deposits.replace('"ETH"', '[]')
            new_withdrawals = withdrawals
        else:
            new_deposits = deposits
            new_withdrawals = withdrawals.replace('"ETH"', '[]')
        mock_binance_and_query(
            new_deposits,
            new_withdrawals,
            expected_warnings_num=0,
            expected_errors_num=1,
        )

        # Unknown asset
        if testing_deposits:
            new_deposits = deposits.replace('"ETH"', '"dasdsDSDSAD"')
            new_withdrawals = withdrawals
        else:
            new_deposits = deposits
            new_withdrawals = withdrawals.replace('"ETH"', '"dasdsDSDSAD"')
        mock_binance_and_query(
            new_deposits,
            new_withdrawals,
            expected_warnings_num=1,
            expected_errors_num=0,
        )

        # Unsupported Asset
        if testing_deposits:
            new_deposits = deposits.replace('"ETH"', '"BTCB"')
            new_withdrawals = withdrawals
        else:
            new_deposits = deposits
            new_withdrawals = withdrawals.replace('"ETH"', '"BTCB"')
        mock_binance_and_query(
            new_deposits,
            new_withdrawals,
            expected_warnings_num=1,
            expected_errors_num=0,
        )

        # Invalid amount
        if testing_deposits:
            new_deposits = deposits.replace('0.04670582', 'null')
            new_withdrawals = withdrawals
        else:
            new_deposits = deposits
            new_withdrawals = withdrawals.replace('0.04670582', 'null')
        mock_binance_and_query(
            new_deposits,
            new_withdrawals,
            expected_warnings_num=0,
            expected_errors_num=1,
        )

        # Missing Key Error
        if testing_deposits:
            new_deposits = deposits.replace('"amount": 0.04670582,', '')
            new_withdrawals = withdrawals
        else:
            new_deposits = deposits
            new_withdrawals = withdrawals.replace('"amount": 0.04670582,', '')
        mock_binance_and_query(
            new_deposits,
            new_withdrawals,
            expected_warnings_num=0,
            expected_errors_num=1,
        )

    # To make the test easy to write the values for deposit/withdrawal attributes
    # are the same in the two examples below
    empty_deposits = '[]'
    empty_withdrawals = '[]'
    input_withdrawals = """[{
        "id":"7213fea8e94b4a5593d507237e5a555b",
        "amount": 0.04670582,
        "transactionFee": 0.01,
        "address": "0x6915f16f8791d0a1cc2bf47c13a6b2a92000504b",
        "coin": "ETH",
        "txId": "0xdf33b22bdb2b28b1f75ccd201a4a4m6e7g83jy5fc5d5a9d1340961598cfcb0a1",
        "applyTime": "2017-10-17 00:02:12",
        "status": 4
        }]"""
    check_permutations_of_input_invalid_data(
        deposits=empty_deposits,
        withdrawals=input_withdrawals,
    )

    input_deposits = """[{
        "insertTime": 1508198532000,
        "amount": 0.04670582,
        "coin": "ETH",
        "address": "0x6915f16f8791d0a1cc2bf47c13a6b2a92000504b",
        "txId": "0xdf33b22bdb2b28b1f75ccd201a4a4m6e7g83jy5fc5d5a9d1340961598cfcb0a1",
        "status": 1
        }]"""
    check_permutations_of_input_invalid_data(
        deposits=input_deposits,
        withdrawals=empty_withdrawals,
    )


def test_binance_query_deposits_withdrawals_gte_90_days(function_scope_binance):

0 Source : test_binance.py
with GNU Affero General Public License v3.0
from rotki

def test_binance_query_deposits_withdrawals_gte_90_days(function_scope_binance):
    """Test the not so happy case of binance deposit withdrawal query

    From `start_ts` to `end_ts` there is a difference gte 90 days, which forces
    to request using a time delta (from API_TIME_INTERVAL_CONSTRAINT_TS). As
    the `mock_get_deposit_withdrawal()` results are the same as in
    `test_binance_query_deposits_withdrawals`, we only assert the number of
    movements.

    NB: this test implementation must mock 4 requests instead of 2.
    """
    start_ts = 0  # Defaults to BINANCE_LAUNCH_TS
    end_ts = BINANCE_LAUNCH_TS + API_TIME_INTERVAL_CONSTRAINT_TS  # eq 90 days after
    binance = function_scope_binance

    def get_time_delta_deposit_result():
        results = [
            BINANCE_DEPOSITS_HISTORY_RESPONSE,
            '[]',
        ]
        for result in results:
            yield result

    def get_time_delta_withdraw_result():
        results = [
            '[]',
            BINANCE_WITHDRAWALS_HISTORY_RESPONSE,
        ]
        for result in results:
            yield result

    def get_fiat_deposit_result():
        results = ['[]']
        for result in results:
            yield result

    def get_fiat_withdraw_result():
        results = ['[]']
        for result in results:
            yield result

    def mock_get_deposit_withdrawal(url, **kwargs):  # pylint: disable=unused-argument
        if 'capital/deposit' in url:
            response_str = next(get_deposit_result)
        elif 'capital/withdraw' in url:
            response_str = next(get_withdraw_result)
        elif 'fiat/orders' in url:
            if 'transactionType=0' in url:
                response_str = next(get_fiat_deposit_result())
            elif 'transactionType=1' in url:
                response_str = next(get_fiat_withdraw_result())
            else:
                raise AssertionError('Unexpected binance request in test')

        else:
            raise AssertionError('Unexpected binance request in test')

        return MockResponse(200, response_str)

    get_deposit_result = get_time_delta_deposit_result()
    get_withdraw_result = get_time_delta_withdraw_result()

    with patch.object(binance.session, 'get', side_effect=mock_get_deposit_withdrawal):
        movements = binance.query_online_deposits_withdrawals(
            start_ts=Timestamp(start_ts),
            end_ts=Timestamp(end_ts),
        )

    errors = binance.msg_aggregator.consume_errors()
    warnings = binance.msg_aggregator.consume_warnings()
    assert len(errors) == 0
    assert len(warnings) == 0

    assert len(movements) == 4


@pytest.mark.freeze_time(datetime(2020, 11, 24, 3, 14, 15))

0 Source : test_binance.py
with GNU Affero General Public License v3.0
from rotki

def test_api_query_list_calls_with_time_delta(function_scope_binance):
    """Test the `api_query_list()` arguments when deposit/withdraw history
    requests involve a time delta.

    From `start_ts` to `end_ts` there is a difference gte 90 days, which forces
    to request using a time delta (from API_TIME_INTERVAL_CONSTRAINT_TS).
    """
    now_ts_ms = int(datetime.utcnow().timestamp()) * 1000
    start_ts = 0  # Defaults to BINANCE_LAUNCH_TS
    end_ts = BINANCE_LAUNCH_TS + API_TIME_INTERVAL_CONSTRAINT_TS  # eq 90 days after
    expected_calls = [
        call(
            'sapi',
            'capital/deposit/hisrec',
            options={
                'timestamp': now_ts_ms,
                'startTime': 1500001200000,
                'endTime': 1507777199999,
            },
        ),
        call(
            'sapi',
            'capital/deposit/hisrec',
            options={
                'timestamp': now_ts_ms,
                'startTime': 1507777200000,
                'endTime': 1507777200000,
            },
        ),
        call(
            'sapi',
            'capital/withdraw/history',
            options={
                'timestamp': now_ts_ms,
                'startTime': 1500001200000,
                'endTime': 1507777199999,
            },
        ),
        call(
            'sapi',
            'capital/withdraw/history',
            options={
                'timestamp': now_ts_ms,
                'startTime': 1507777200000,
                'endTime': 1507777200000,
            },
        ),
    ]
    binance = function_scope_binance

    def get_time_delta_deposit_result():
        results = [
            BINANCE_DEPOSITS_HISTORY_RESPONSE,
            '[]',
        ]
        for result in results:
            yield result

    def get_time_delta_withdraw_result():
        results = [
            '[]',
            BINANCE_WITHDRAWALS_HISTORY_RESPONSE,
        ]
        for result in results:
            yield result

    def mock_get_deposit_withdrawal(url, **kwargs):  # pylint: disable=unused-argument
        if 'deposit' in url:
            response_str = next(get_deposit_result)
        else:
            response_str = next(get_withdraw_result)

        return MockResponse(200, response_str)

    get_deposit_result = get_time_delta_deposit_result()
    get_withdraw_result = get_time_delta_withdraw_result()

    with patch.object(binance.session, 'get', side_effect=mock_get_deposit_withdrawal):
        with patch.object(binance, 'api_query_list') as mock_api_query_list:
            binance.query_online_deposits_withdrawals(
                start_ts=Timestamp(start_ts),
                end_ts=Timestamp(end_ts),
            )
            # TODO: Fix this test to deal with fiat deposits too
            assert mock_api_query_list.call_args_list[:4] == expected_calls


@pytest.mark.freeze_time(datetime(2020, 11, 24, 3, 14, 15))

0 Source : test_binance.py
with GNU Affero General Public License v3.0
from rotki

def test_api_query_retry_on_status_code_429(function_scope_binance):
    """Test when Binance API returns 429 and the request is retried, the
    signature is not polluted by any attribute from the previous call.

    It also tests getting the `retry-after` seconds to backoff from the
    response header.

    NB: basically remove `call_options['signature']`.
    """
    binance = function_scope_binance
    offset_ms = 1000
    call_options = {
        'fromId': 0,
        'limit': 1000,
        'symbol': 'BUSDUSDT',
        'recvWindow': 10000,
        'timestamp': str(ts_now_in_ms() + offset_ms),
    }
    signature = hmac.new(
        binance.secret,
        urlencode(call_options).encode('utf-8'),
        hashlib.sha256,
    ).hexdigest()
    call_options['signature'] = signature
    base_url = 'https://api.binance.com/api/v3/myTrades?'
    exp_request_url = base_url + urlencode(call_options)

    # NB: all calls must have the same signature (time frozen)
    expected_calls = [
        call(exp_request_url, timeout=DEFAULT_TIMEOUT_TUPLE),
        call(exp_request_url, timeout=DEFAULT_TIMEOUT_TUPLE),
        call(exp_request_url, timeout=DEFAULT_TIMEOUT_TUPLE),
    ]

    def get_mocked_response():
        responses = [
            MockResponse(429, '[]', headers={'retry-after': '1'}),
            MockResponse(418, '[]', headers={'retry-after': '5'}),
            MockResponse(418, '[]', headers={'retry-after': str(RETRY_AFTER_LIMIT + 1)}),
        ]
        for response in responses:
            yield response

    def mock_response(url, timeout):  # pylint: disable=unused-argument
        return next(get_response)

    get_response = get_mocked_response()
    offset_ms_patch = patch.object(binance, 'offset_ms', new=1000)
    binance_patch = patch.object(binance.session, 'get', side_effect=mock_response)

    with ExitStack() as stack:
        stack.enter_context(offset_ms_patch)
        binance_mock_get = stack.enter_context(binance_patch)
        with pytest.raises(RemoteError) as e:
            binance.api_query(
                api_type='api',
                method='myTrades',
                options={
                    'fromId': 0,
                    'limit': 1000,
                    'symbol': 'BUSDUSDT',
                },
            )
    assert 'myTrades failed with HTTP status code: 418' in str(e.value)
    assert binance_mock_get.call_args_list == expected_calls


def test_binance_query_trade_history_custom_markets(function_scope_binance, user_data_dir):

0 Source : test_binance.py
with GNU Affero General Public License v3.0
from rotki

def test_binance_query_trade_history_custom_markets(function_scope_binance, user_data_dir):
    """Test that custom pairs are queried correctly"""
    msg_aggregator = MessagesAggregator()
    db = DBHandler(user_data_dir, '123', msg_aggregator, None)

    binance_api_key = ApiKey('binance_api_key')
    binance_api_secret = ApiSecret(b'binance_api_secret')
    db.add_exchange('binance', Location.BINANCE, binance_api_key, binance_api_secret)

    binance = function_scope_binance

    markets = ['ETHBTC', 'BNBBTC', 'BTCUSDC']
    binance.edit_exchange(name=None, api_key=None, api_secret=None, PAIRS=markets)
    count = 0
    p = re.compile(r'symbol=[A-Z]*')
    seen = set()

    def mock_my_trades(url, timeout):  # pylint: disable=unused-argument
        nonlocal count
        if '/fiat/payments' not in url:
            count += 1
            market = p.search(url).group()[7:]
            assert market in markets and market not in seen
            seen.add(market)
        text = '[]'
        return MockResponse(200, text)

    with patch.object(binance.session, 'get', side_effect=mock_my_trades):
        binance.query_trade_history(start_ts=0, end_ts=1564301134, only_cache=False)

    assert count == len(markets)

0 Source : test_binance_us.py
with GNU Affero General Public License v3.0
from rotki

def test_binanceus_trades_location(function_scope_binance):
    """Test that trades from binance US have the right location.

    Regression test for https://github.com/rotki/rotki/issues/2837
    """
    binance = function_scope_binance

    def mock_my_trades(url, **kwargs):  # pylint: disable=unused-argument
        if 'symbol=BNBBTC' in url:
            text = BINANCE_MYTRADES_RESPONSE
        else:
            text = '[]'

        return MockResponse(200, text)

    with patch.object(binance.session, 'get', side_effect=mock_my_trades):
        trades = binance.query_trade_history(start_ts=0, end_ts=1564301134, only_cache=False)

    expected_trade = Trade(
        timestamp=1499865549,
        location=Location.BINANCEUS,
        base_asset=A_BNB,
        quote_asset=A_BTC,
        trade_type=TradeType.BUY,
        amount=FVal('12'),
        rate=FVal('4.00000100'),
        fee=FVal('10.10000000'),
        fee_currency=A_BNB,
        link='28457',
    )

    assert len(trades) == 1
    assert trades[0] == expected_trade


@pytest.mark.parametrize('binance_location', [Location.BINANCEUS])

0 Source : test_binance_us.py
with GNU Affero General Public License v3.0
from rotki

def test_binanceus_deposits_withdrawals_location(function_scope_binance):
    """Test deposits/withdrawls of binance US have the right location.

    Regression test for https://github.com/rotki/rotki/issues/2837
    """
    start_ts = 1508022000  # 2017-10-15
    end_ts = 1508540400  # 2017-10-21 (less than 90 days since `start_ts`)
    binance = function_scope_binance

    def mock_get_deposit_withdrawal(url, **kwargs):  # pylint: disable=unused-argument
        if 'deposit' in url:
            response_str = BINANCE_DEPOSITS_HISTORY_RESPONSE
        else:
            response_str = BINANCE_WITHDRAWALS_HISTORY_RESPONSE

        return MockResponse(200, response_str)

    with patch.object(binance.session, 'get', side_effect=mock_get_deposit_withdrawal):
        movements = binance.query_online_deposits_withdrawals(
            start_ts=Timestamp(start_ts),
            end_ts=Timestamp(end_ts),
        )

    errors = binance.msg_aggregator.consume_errors()
    warnings = binance.msg_aggregator.consume_warnings()
    assert len(errors) == 0
    assert len(warnings) == 0

    assert len(movements) == 4
    assert_binance_asset_movements_result(
        movements=movements,
        location=Location.BINANCEUS,
        got_fiat=False,
    )

0 Source : test_bitcoinde.py
with GNU Affero General Public License v3.0
from rotki

def test_bitcoinde_query_balances_unknown_asset(function_scope_bitcoinde):
    """Test that if a bitcoinde balance query returns unknown asset no exception
    is raised and a warning is generated. Same for unsupported assets"""
    bitcoinde = function_scope_bitcoinde

    def mock_unknown_asset_return(url, **kwargs):  # pylint: disable=unused-argument
        return MockResponse(200, BITCOINDE_BALANCES_RESPONSE)

    with patch.object(bitcoinde.session, 'get', side_effect=mock_unknown_asset_return):
        # Test that after querying the assets only ETH and BTC are there
        balances, msg = bitcoinde.query_balances()

    assert msg == ''
    assert len(balances) == 6
    assert balances[A_ETH].amount == FVal('32.0')
    assert balances[A_BTC].amount == FVal('0.5')

    warnings = bitcoinde.msg_aggregator.consume_warnings()
    assert len(warnings) == 0


def test_query_trade_history(function_scope_bitcoinde):

0 Source : test_bitcoinde.py
with GNU Affero General Public License v3.0
from rotki

def test_query_trade_history(function_scope_bitcoinde):
    """Happy path test for bitcoinde trade history querying"""
    bitcoinde = function_scope_bitcoinde

    def mock_api_return(url, **kwargs):  # pylint: disable=unused-argument
        return MockResponse(200, BITCOINDE_TRADES_RESPONSE)

    with patch.object(bitcoinde.session, 'get', side_effect=mock_api_return):
        trades = bitcoinde.query_trade_history(
            start_ts=0,
            end_ts=1565732120,
            only_cache=False,
        )

    assert len(trades) == 2
    assert trades[0].timestamp == 1512531092
    assert trades[0].location == Location.BITCOINDE
    assert trades[0].base_asset == A_BTC
    assert trades[0].quote_asset == A_EUR
    assert trades[0].trade_type == TradeType.BUY
    assert trades[0].amount == FVal('10')
    assert trades[0].rate.is_close(FVal('234.121'))
    assert trades[0].fee.is_close(FVal('1.5214'))
    assert isinstance(trades[0].fee_currency, Asset)
    assert trades[0].fee_currency == A_EUR

    assert trades[1].timestamp == 1502439199
    assert trades[1].location == Location.BITCOINDE
    assert trades[1].base_asset == A_BTC
    assert trades[1].quote_asset == A_EUR
    assert trades[1].trade_type == TradeType.BUY
    assert trades[1].amount == FVal('241.214')
    assert trades[1].rate.is_close(FVal('17.09736582453754757186564627'))
    assert trades[1].fee.is_close(FVal('0.93452135'))
    assert isinstance(trades[1].fee_currency, Asset)
    assert trades[1].fee_currency == A_EUR


def test_bitcoinde_trading_pairs():

0 Source : test_bitfinex.py
with GNU Affero General Public License v3.0
from rotki

def test_api_key_err_auth_nonce(mock_bitfinex):
    """Test the error code related with the nonce authentication is properly handled"""
    def mock_api_query_response(endpoint, options=None):  # pylint: disable=unused-argument
        return MockResponse(
            HTTPStatus.INTERNAL_SERVER_ERROR,
            f'["error", {API_ERR_AUTH_NONCE_CODE}, "nonce: small"]',
        )

    mock_bitfinex.first_connection_made = True
    with patch.object(mock_bitfinex, '_api_query', side_effect=mock_api_query_response):
        result, msg = mock_bitfinex.query_balances()
        assert result is False
        assert msg == API_ERR_AUTH_NONCE_MESSAGE

        result, msg = mock_bitfinex.validate_api_key()
        assert result is False
        assert msg == API_ERR_AUTH_NONCE_MESSAGE

        movements = mock_bitfinex.query_online_deposits_withdrawals(0, 1)
        assert movements == []
        errors = mock_bitfinex.msg_aggregator.consume_errors()
        assert len(errors) == 1
        assert API_ERR_AUTH_NONCE_MESSAGE in errors[0]

        trades, _ = mock_bitfinex.query_online_trade_history(0, 1)
        assert trades == []
        errors = mock_bitfinex.msg_aggregator.consume_errors()
        assert len(errors) == 1
        assert API_ERR_AUTH_NONCE_MESSAGE in errors[0]


def test_validate_api_key_invalid_key(mock_bitfinex):

0 Source : test_bitfinex.py
with GNU Affero General Public License v3.0
from rotki

def test_query_balances_asset_balance(mock_bitfinex, inquirer):  # pylint: disable=unused-argument
    """Test the balances of the assets are returned as expected.

    Also test the following logic:
      - An asset balance is the result of aggregating its balances per wallet
      type (i.e. exchange, margin and funding).
      - The balance of an asset in UNSUPPORTED_BITFINEX_ASSETS is skipped.
      - The asset ticker is standardized (e.g. WBT to WBTC, UST to USDT).
    """
    mock_bitfinex.first_connection = MagicMock()
    mock_bitfinex.currency_map = {
        'UST': 'USDt',
        'GNT': 'GLM',
        'WBT': 'WBTC',
    }
    balances_data = (
        """
        [
            ["exchange"],
            ["exchange", "UST"],
            ["exchange", "", 12345],
            ["exchange", "WBT", 0.0000000],
            ["exchange", "", 19788.6529257],
            ["exchange", "UST", 19788.6529257],
            ["margin", "UST", 0.50000000],
            ["funding", "UST", 1],
            ["exchange", "LINK", 777.777777],
            ["exchange", "GNT", 0.0000001],
            ["exchange", "EUR", 99.9999999],
            ["margin", "WBT", 1.00000000],
            ["funding", "NEO", 1.00000000],
            ["exchange", "B21X", 1.00000000]
        ]
        """
    )

    def mock_api_query_response(endpoint):  # pylint: disable=unused-argument
        return MockResponse(HTTPStatus.OK, balances_data)

    with patch.object(
        target=mock_bitfinex,
        attribute='_api_query',
        side_effect=mock_api_query_response,
    ):
        asset_balance, msg = mock_bitfinex.query_balances()

        assert asset_balance == {
            A_EUR: Balance(
                amount=FVal('99.9999999'),
                usd_value=FVal('149.99999985'),
            ),
            A_GLM: Balance(
                amount=FVal('0.0000001'),
                usd_value=FVal('0.00000015'),
            ),
            A_LINK: Balance(
                amount=FVal('777.777777'),
                usd_value=FVal('1166.6666655'),
            ),
            A_NEO: Balance(
                amount=FVal('1'),
                usd_value=FVal('1.5'),
            ),
            A_USDT: Balance(
                amount=FVal('19790.1529257'),
                usd_value=FVal('29685.22938855'),
            ),
            A_WBTC: Balance(
                amount=FVal('1'),
                usd_value=FVal('1.5'),
            ),
        }
        assert msg == ''


def test_api_query_paginated_stops_requesting(mock_bitfinex):

0 Source : test_bitfinex.py
with GNU Affero General Public License v3.0
from rotki

def test_api_query_paginated_stops_requesting(mock_bitfinex):
    """Test requests are stopped after retry limit is reached.
    """
    mock_bitfinex.currency_map = {}

    def mock_api_query_response(endpoint, options):  # pylint: disable=unused-argument
        return MockResponse(
            HTTPStatus.INTERNAL_SERVER_ERROR,
            f'{{"error":"{API_RATE_LIMITS_ERROR_MESSAGE}"}}',
        )

    api_request_retry_times_patch = patch(
        target='rotkehlchen.exchanges.bitfinex.API_REQUEST_RETRY_TIMES',
        new=0,
    )
    # Just in case the test fails, we don't want to wait 60s
    api_request_retry_after_seconds_patch = patch(
        target='rotkehlchen.exchanges.bitfinex.API_REQUEST_RETRY_AFTER_SECONDS',
        new=0,
    )
    api_query_patch = patch.object(
        target=mock_bitfinex,
        attribute='_api_query',
        side_effect=mock_api_query_response,
    )
    with ExitStack() as stack:
        stack.enter_context(api_request_retry_times_patch)
        stack.enter_context(api_request_retry_after_seconds_patch)
        stack.enter_context(api_query_patch)
        result = mock_bitfinex._api_query_paginated(
            options={'limit': 2},
            case='trades',
        )
        assert result == []


def test_api_query_paginated_retries_request(mock_bitfinex):

0 Source : test_bitfinex.py
with GNU Affero General Public License v3.0
from rotki

def test_api_query_paginated_retries_request(mock_bitfinex):
    """Test retry logic works as expected.

    It also tests that that trying to decode first the unsuccessful response
    JSON as a dict and later as a list (via `_process_unsuccessful_response()`)
    works as expected.
    """
    mock_bitfinex.currency_map = {}

    def get_paginated_response():
        results = [
            f'{{"error":"{API_RATE_LIMITS_ERROR_MESSAGE}"}}',
            '["error", 10000, "unknown error"]',
        ]
        for result_ in results:
            yield result_

    def mock_api_query_response(endpoint, options):  # pylint: disable=unused-argument
        return MockResponse(HTTPStatus.INTERNAL_SERVER_ERROR, next(get_response))

    get_response = get_paginated_response()
    api_request_retry_times_patch = patch(
        target='rotkehlchen.exchanges.bitfinex.API_REQUEST_RETRY_TIMES',
        new=1,
    )
    api_request_retry_after_seconds_patch = patch(
        target='rotkehlchen.exchanges.bitfinex.API_REQUEST_RETRY_AFTER_SECONDS',
        new=0,
    )
    api_query_patch = patch.object(
        target=mock_bitfinex,
        attribute='_api_query',
        side_effect=mock_api_query_response,
    )
    with ExitStack() as stack:
        stack.enter_context(api_request_retry_times_patch)
        stack.enter_context(api_request_retry_after_seconds_patch)
        stack.enter_context(api_query_patch)
        result = mock_bitfinex._api_query_paginated(
            options={'limit': 2},
            case='trades',
        )
        assert result == []


def test_deserialize_trade_buy(mock_bitfinex):

0 Source : test_bitfinex.py
with GNU Affero General Public License v3.0
from rotki

def test_query_online_trade_history_case_1(mock_bitfinex):
    """Test pagination logic for trades works as expected when each request
    does not return a result already processed.

    Other things tested:
      - Stop requesting (break the loop) when result timestamp is greater than
      'end_ts'.
      - '_api_query' call arguments.

    First request: 2 results
    Second request: 2 results
    Third request: 1 result, out of time range (its timestamp is gt 'end_ts')

    Trades with id 1 to 4 are expected to be returned.
    """
    api_limit = 2
    mock_bitfinex.first_connection = MagicMock()
    mock_bitfinex.currency_map = {
        'UST': 'USDt',
        'WBT': 'WBTC',
    }
    mock_bitfinex.pair_bfx_symbols_map = {
        'ETHUST': ('ETH', 'UST'),
        'WBTUSD': ('WBT', 'USD'),
        'ETHEUR': ('ETH', 'EUR'),
    }
    # Buy ETH with USDT
    trade_1 = """
    [
        1,
        "tETH:UST",
        1606899600000,
        10,
        0.26334268,
        187.37,
        "LIMIT",
        null,
        -1,
        -0.09868591,
        "USD"
    ]
    """
    # Sell ETH for USDT
    trade_2 = """
    [
        2,
        "tETH:UST",
        1606901400000,
        20,
        -0.26334268,
        187.37,
        "LIMIT",
        null,
        -1,
        -0.09868591,
        "ETH"
    ]
    """
    # Buy WBTC for USD
    trade_3 = """
    [
        3,
        "tWBTUSD",
        1606932000000,
        30,
        10000.00000000,
        0.00005000,
        "LIMIT",
        null,
        -1,
        -20.00000000,
        "USD"
    ]
    """
    # Sell WBTC for USD
    trade_4 = """
    [
        4,
        "tWBTUSD",
        1606986000000,
        40,
        -10000.00000000,
        0.00005000,
        "LIMIT",
        null,
        -1,
        -20.00000000,
        "BTC"
    ]
    """
    # Sell ETH for EUR, outside time range (gt 'end_ts')
    trade_5 = """
    [
        5,
        "tETH:EUR",
        1606996801000,
        50,
        -0.26334268,
        163.29,
        "LIMIT",
        null,
        -1,
        -0.09868591,
        "ETH"
    ]
    """
    expected_calls = [
        call(
            endpoint='trades',
            options={
                'start': 0,
                'end': 1606996800000,
                'limit': 2,
                'sort': 1,
            },
        ),
        call(
            endpoint='trades',
            options={
                'start': 1606901400000,
                'end': 1606996800000,
                'limit': 2,
                'sort': 1,
            },
        ),
        call(
            endpoint='trades',
            options={
                'start': 1606986000000,
                'end': 1606996800000,
                'limit': 2,
                'sort': 1,
            },
        ),
    ]

    def get_paginated_response():
        results = [
            f'[{trade_1},{trade_2}]',
            f'[{trade_3},{trade_4}]',
            f'[{trade_5}]',
        ]
        for result_ in results:
            yield result_

    def mock_api_query_response(endpoint, options):  # pylint: disable=unused-argument
        return MockResponse(HTTPStatus.OK, next(get_response))

    get_response = get_paginated_response()
    api_limit_patch = patch(
        target='rotkehlchen.exchanges.bitfinex.API_TRADES_MAX_LIMIT',
        new=api_limit,
    )
    api_query_patch = patch.object(
        target=mock_bitfinex,
        attribute='_api_query',
        side_effect=mock_api_query_response,
    )
    with ExitStack() as stack:
        stack.enter_context(api_limit_patch)
        api_query_mock = stack.enter_context(api_query_patch)
        trades, _ = mock_bitfinex.query_online_trade_history(
            start_ts=Timestamp(0),
            end_ts=Timestamp(int(datetime.now().timestamp())),
        )
        assert api_query_mock.call_args_list == expected_calls
        expected_trades = [
            Trade(
                timestamp=Timestamp(1606899600),
                location=Location.BITFINEX,
                base_asset=A_ETH,
                quote_asset=A_USDT,
                trade_type=TradeType.BUY,
                amount=AssetAmount(FVal('0.26334268')),
                rate=Price(FVal('187.37')),
                fee=Fee(FVal('0.09868591')),
                fee_currency=A_USD,
                link='1',
                notes='',
            ),
            Trade(
                timestamp=Timestamp(1606901400),
                location=Location.BITFINEX,
                base_asset=A_ETH,
                quote_asset=A_USDT,
                trade_type=TradeType.SELL,
                amount=AssetAmount(FVal('0.26334268')),
                rate=Price(FVal('187.37')),
                fee=Fee(FVal('0.09868591')),
                fee_currency=A_ETH,
                link='2',
                notes='',
            ),
            Trade(
                timestamp=Timestamp(1606932000),
                location=Location.BITFINEX,
                base_asset=A_WBTC,
                quote_asset=A_USD,
                trade_type=TradeType.BUY,
                amount=AssetAmount(FVal('10000.0')),
                rate=Price(FVal('0.00005')),
                fee=Fee(FVal('20.0')),
                fee_currency=A_USD,
                link='3',
                notes='',
            ),
            Trade(
                timestamp=Timestamp(1606986000),
                location=Location.BITFINEX,
                base_asset=A_WBTC,
                quote_asset=A_USD,
                trade_type=TradeType.SELL,
                amount=AssetAmount(FVal('10000.0')),
                rate=Price(FVal('0.00005')),
                fee=Fee(FVal('20.0')),
                fee_currency=A_BTC,
                link='4',
                notes='',
            ),
        ]
        assert trades == expected_trades


@pytest.mark.freeze_time(datetime(2020, 12, 3, 12, 0, 0))

0 Source : test_bitfinex.py
with GNU Affero General Public License v3.0
from rotki

def test_query_online_trade_history_case_2(mock_bitfinex):
    """Test pagination logic for trades works as expected when a request
    returns a result already processed in the previous request.

    Other things tested:
      - Stop requesting when number of entries is less than limit.

    First request: 2 results
    Second request: 2 results, both trades are repeated from the 1st request.
    Third request: 2 results, first trade is repeated from the 2nd request.
    Fourth request: 1 result

    Trades with id 1 to 4 are expected to be returned.
    """
    api_limit = 2
    mock_bitfinex.first_connection = MagicMock()
    mock_bitfinex.currency_map = {
        'UST': 'USDt',
        'WBT': 'WBTC',
    }
    mock_bitfinex.pair_bfx_symbols_map = {
        'ETHUST': ('ETH', 'UST'),
        'WBTUSD': ('WBT', 'USD'),
        'ETHEUR': ('ETH', 'EUR'),
    }
    # Buy ETH with USDT
    trade_1 = """
    [
        1,
        "tETH:UST",
        1606899600000,
        10,
        0.26334268,
        187.37,
        "LIMIT",
        null,
        -1,
        -0.09868591,
        "UST"
    ]
    """
    # Sell ETH for USDT
    trade_2 = """
    [
        2,
        "tETH:UST",
        1606901400000,
        20,
        -0.26334268,
        187.37,
        "LIMIT",
        null,
        -1,
        -0.09868591,
        "ETH"
    ]
    """
    # Buy WBTC for USD
    trade_3 = """
    [
        3,
        "tWBTUSD",
        1606932000000,
        30,
        10000.00000000,
        0.00005000,
        "LIMIT",
        null,
        -1,
        -20.00000000,
        "USD"
    ]
    """
    # Sell WBTC for USD
    trade_4 = """
    [
        4,
        "tWBTUSD",
        1606986000000,
        40,
        -10000.00000000,
        0.00005000,
        "LIMIT",
        null,
        -1,
        -20.00000000,
        "WBT"
    ]
    """

    def get_paginated_response():
        results = [
            f'[{trade_1},{trade_2}]',
            f'[{trade_1},{trade_2}]',  # repeated line
            f'[{trade_2},{trade_3}]',  # contains repeated
            f'[{trade_4}]',
        ]
        for result_ in results:
            yield result_

    def mock_api_query_response(endpoint, options):  # pylint: disable=unused-argument
        return MockResponse(HTTPStatus.OK, next(get_response))

    get_response = get_paginated_response()
    api_limit_patch = patch(
        target='rotkehlchen.exchanges.bitfinex.API_TRADES_MAX_LIMIT',
        new=api_limit,
    )
    api_query_patch = patch.object(
        target=mock_bitfinex,
        attribute='_api_query',
        side_effect=mock_api_query_response,
    )
    with ExitStack() as stack:
        stack.enter_context(api_limit_patch)
        stack.enter_context(api_query_patch)
        trades, _ = mock_bitfinex.query_online_trade_history(
            start_ts=Timestamp(0),
            end_ts=Timestamp(int(datetime.now().timestamp())),
        )
        expected_trades = [
            Trade(
                timestamp=Timestamp(1606899600),
                location=Location.BITFINEX,
                base_asset=A_ETH,
                quote_asset=A_USDT,
                trade_type=TradeType.BUY,
                amount=AssetAmount(FVal('0.26334268')),
                rate=Price(FVal('187.37')),
                fee=Fee(FVal('0.09868591')),
                fee_currency=A_USDT,
                link='1',
                notes='',
            ),
            Trade(
                timestamp=Timestamp(1606901400),
                location=Location.BITFINEX,
                base_asset=A_ETH,
                quote_asset=A_USDT,
                trade_type=TradeType.SELL,
                amount=AssetAmount(FVal('0.26334268')),
                rate=Price(FVal('187.37')),
                fee=Fee(FVal('0.09868591')),
                fee_currency=A_ETH,
                link='2',
                notes='',
            ),
            Trade(
                timestamp=Timestamp(1606932000),
                location=Location.BITFINEX,
                base_asset=A_WBTC,
                quote_asset=A_USD,
                trade_type=TradeType.BUY,
                amount=AssetAmount(FVal('10000.0')),
                rate=Price(FVal('0.00005')),
                fee=Fee(FVal('20.0')),
                fee_currency=A_USD,
                link='3',
                notes='',
            ),
            Trade(
                timestamp=Timestamp(1606986000),
                location=Location.BITFINEX,
                base_asset=A_WBTC,
                quote_asset=A_USD,
                trade_type=TradeType.SELL,
                amount=AssetAmount(FVal('10000.0')),
                rate=Price(FVal('0.00005')),
                fee=Fee(FVal('20.0')),
                fee_currency=A_WBTC,
                link='4',
                notes='',
            ),
        ]
        assert trades == expected_trades


def test_deserialize_asset_movement_deposit(mock_bitfinex):

0 Source : test_bitfinex.py
with GNU Affero General Public License v3.0
from rotki

def test_query_online_deposits_withdrawals_case_1(mock_bitfinex):
    """Test pagination logic for asset movements works as expected when each
    request does not return a result already processed.

    Other things tested:
      - Results are sorted by id in ascending mode.
      - Skip result when status is not 'COMPLETED'.
      - Stop requesting (break the loop) when result timestamp is greater than
      'end_ts'.
      - '_api_query' call arguments.

    First request: 2 results
    Second request: 2 results, 1 not completed.
    Third request: 1 result, out of time range (its timestamp is gt 'end_ts')

    Movements with id 1, 2 and 4 are expected to be returned.
    """
    api_limit = 2
    mock_bitfinex.first_connection = MagicMock()
    mock_bitfinex.currency_map = {'WBT': 'WBTC'}
    # Deposit WBTC
    movement_1 = """
    [
        1,
        "WBT",
        "Wrapped Bitcoin",
        null,
        null,
        1606899600000,
        1606899700000,
        null,
        null,
        "COMPLETED",
        null,
        null,
        0.26300954,
        -0.00135,
        null,
        null,
        "DESTINATION_ADDRESS",
        null,
        null,
        null,
        "TRANSACTION_ID",
        null
    ]
    """
    # Withdraw WBTC
    movement_2 = """
    [
        2,
        "WBT",
        "Wrapped Bitcoin",
        null,
        null,
        1606901400000,
        1606901500000,
        null,
        null,
        "COMPLETED",
        null,
        null,
        -0.26300954,
        -0.00135,
        null,
        null,
        "DESTINATION_ADDRESS",
        null,
        null,
        null,
        "TRANSACTION_ID",
        null
    ]
    """
    # Deposit WBTC, not completed
    movement_3 = """
    [
        3,
        "WBT",
        "Wrapped Bitcoin",
        null,
        null,
        1606932000000,
        1606932100000,
        null,
        null,
        "WHATEVER",
        null,
        null,
        0.26300954,
        -0.00135,
        null,
        null,
        "DESTINATION_ADDRESS",
        null,
        null,
        null,
        "TRANSACTION_ID",
        null
    ]
    """
    # Withdraw EUR
    movement_4 = """
    [
        4,
        "EUR",
        "Euro",
        null,
        null,
        1606986000000,
        1606986100000,
        null,
        null,
        "COMPLETED",
        null,
        null,
        -0.26300954,
        -0.00135,
        null,
        null,
        "",
        null,
        null,
        null,
        "",
        null
    ]
    """
    # Deposit WBTC, outside time range (gt 'end_ts')
    movement_5 = """
    [
        5,
        "WBT",
        "Wrapped Bitcoin",
        null,
        null,
        1606996801000,
        1606996901000,
        null,
        null,
        "COMPLETED",
        null,
        null,
        0.26300954,
        -0.00135,
        null,
        null,
        "DESTINATION_ADDRESS",
        null,
        null,
        null,
        "TRANSACTION_ID",
        null
    ]
    """
    expected_calls = [
        call(
            endpoint='movements',
            options={
                'start': 0,
                'end': 1606996800000,
                'limit': 2,
            },
        ),
        call(
            endpoint='movements',
            options={
                'start': 1606901400000,
                'end': 1606996800000,
                'limit': 2,
            },
        ),
        call(
            endpoint='movements',
            options={
                'start': 1606986000000,
                'end': 1606996800000,
                'limit': 2,
            },
        ),
    ]

    def get_paginated_response():
        results = [
            f'[{movement_2},{movement_1}]',
            f'[{movement_4},{movement_3}]',
            f'[{movement_5}]',
        ]
        for result_ in results:
            yield result_

    def mock_api_query_response(endpoint, options):  # pylint: disable=unused-argument
        return MockResponse(HTTPStatus.OK, next(get_response))

    get_response = get_paginated_response()
    api_limit_patch = patch(
        target='rotkehlchen.exchanges.bitfinex.API_MOVEMENTS_MAX_LIMIT',
        new=api_limit,
    )
    api_query_patch = patch.object(
        target=mock_bitfinex,
        attribute='_api_query',
        side_effect=mock_api_query_response,
    )
    with ExitStack() as stack:
        stack.enter_context(api_limit_patch)
        api_query_mock = stack.enter_context(api_query_patch)
        asset_movements = mock_bitfinex.query_online_deposits_withdrawals(
            start_ts=Timestamp(0),
            end_ts=Timestamp(int(datetime.now().timestamp())),
        )
        assert api_query_mock.call_args_list == expected_calls

        wbtc_fee_asset = A_WBTC
        eur_fee_asset = A_EUR
        expected_asset_movements = [
            AssetMovement(
                timestamp=Timestamp(1606899600),
                location=Location.BITFINEX,
                category=AssetMovementCategory.DEPOSIT,
                address='DESTINATION_ADDRESS',
                transaction_id='TRANSACTION_ID',
                asset=wbtc_fee_asset,
                amount=FVal('0.26300954'),
                fee_asset=wbtc_fee_asset,
                fee=Fee(FVal('0.00135')),
                link=str(1),
            ),
            AssetMovement(
                timestamp=Timestamp(1606901400),
                location=Location.BITFINEX,
                category=AssetMovementCategory.WITHDRAWAL,
                address='DESTINATION_ADDRESS',
                transaction_id='TRANSACTION_ID',
                asset=wbtc_fee_asset,
                amount=FVal('0.26300954'),
                fee_asset=wbtc_fee_asset,
                fee=Fee(FVal('0.00135')),
                link=str(2),
            ),
            AssetMovement(
                timestamp=Timestamp(1606986000),
                location=Location.BITFINEX,
                category=AssetMovementCategory.WITHDRAWAL,
                address=None,
                transaction_id=None,
                asset=eur_fee_asset,
                amount=FVal('0.26300954'),
                fee_asset=eur_fee_asset,
                fee=Fee(FVal('0.00135')),
                link=str(4),
            ),
        ]
        assert asset_movements == expected_asset_movements


@pytest.mark.freeze_time(datetime(2020, 12, 3, 12, 0, 0))

0 Source : test_bitfinex.py
with GNU Affero General Public License v3.0
from rotki

def test_query_online_deposits_withdrawals_case_2(mock_bitfinex):
    """Test pagination logic for asset movements works as expected when a
    request returns a result already processed in the previous request.

    Other things tested:
      - Stop requesting when number of entries is less than limit.

    First request: 2 results
    Second request: 2 results, both movements are repeated from the 1st request.
    Third request: 2 results, first movement is repeated from the 2nd request.
    Fourth request: 1 result

    Trades with id 1 to 4 are expected to be returned.
    """
    api_limit = 2
    mock_bitfinex.first_connection = MagicMock()
    mock_bitfinex.currency_map = {'WBT': 'WBTC'}
    # Deposit WBTC
    movement_1 = """
    [
        1,
        "WBT",
        "Wrapped Bitcoin",
        null,
        null,
        1606899600000,
        1606899700000,
        null,
        null,
        "COMPLETED",
        null,
        null,
        0.26300954,
        -0.00135,
        null,
        null,
        "DESTINATION_ADDRESS",
        null,
        null,
        null,
        "TRANSACTION_ID",
        null
    ]
    """
    # Withdraw WBTC
    movement_2 = """
    [
        2,
        "WBT",
        "Wrapped Bitcoin",
        null,
        null,
        1606901400000,
        1606901500000,
        null,
        null,
        "COMPLETED",
        null,
        null,
        -0.26300954,
        -0.00135,
        null,
        null,
        "DESTINATION_ADDRESS",
        null,
        null,
        null,
        "TRANSACTION_ID",
        null
    ]
    """
    # Withdraw EUR
    movement_3 = """
    [
        3,
        "EUR",
        "Euro",
        null,
        null,
        1606986000000,
        1606986100000,
        null,
        null,
        "COMPLETED",
        null,
        null,
        -0.26300954,
        -0.00135,
        null,
        null,
        "",
        null,
        null,
        null,
        "",
        null
    ]
    """
    # Deposit WBTC
    movement_4 = """
    [
        4,
        "WBT",
        "Wrapped Bitcoin",
        null,
        null,
        1606996800000,
        1606996900000,
        null,
        null,
        "COMPLETED",
        null,
        null,
        0.26300954,
        -0.00135,
        null,
        null,
        "DESTINATION_ADDRESS",
        null,
        null,
        null,
        "TRANSACTION_ID",
        null
    ]
    """

    def get_paginated_response():
        results = [
            f'[{movement_2},{movement_1}]',
            f'[{movement_2},{movement_1}]',
            f'[{movement_3},{movement_2}]',
            f'[{movement_4}]',
        ]
        for result_ in results:
            yield result_

    def mock_api_query_response(endpoint, options):  # pylint: disable=unused-argument
        return MockResponse(HTTPStatus.OK, next(get_response))

    get_response = get_paginated_response()
    api_limit_patch = patch(
        target='rotkehlchen.exchanges.bitfinex.API_MOVEMENTS_MAX_LIMIT',
        new=api_limit,
    )
    api_query_patch = patch.object(
        target=mock_bitfinex,
        attribute='_api_query',
        side_effect=mock_api_query_response,
    )
    with ExitStack() as stack:
        stack.enter_context(api_limit_patch)
        stack.enter_context(api_query_patch)
        asset_movements = mock_bitfinex.query_online_deposits_withdrawals(
            start_ts=Timestamp(0),
            end_ts=Timestamp(int(datetime.now().timestamp())),
        )
        wbtc_fee_asset = A_WBTC
        eur_fee_asset = A_EUR
        expected_asset_movements = [
            AssetMovement(
                timestamp=Timestamp(1606899600),
                location=Location.BITFINEX,
                category=AssetMovementCategory.DEPOSIT,
                address='DESTINATION_ADDRESS',
                transaction_id='TRANSACTION_ID',
                asset=wbtc_fee_asset,
                amount=FVal('0.26300954'),
                fee_asset=wbtc_fee_asset,
                fee=Fee(FVal('0.00135')),
                link=str(1),
            ),
            AssetMovement(
                timestamp=Timestamp(1606901400),
                location=Location.BITFINEX,
                category=AssetMovementCategory.WITHDRAWAL,
                address='DESTINATION_ADDRESS',
                transaction_id='TRANSACTION_ID',
                asset=wbtc_fee_asset,
                amount=FVal('0.26300954'),
                fee_asset=wbtc_fee_asset,
                fee=Fee(FVal('0.00135')),
                link=str(2),
            ),
            AssetMovement(
                timestamp=Timestamp(1606986000),
                location=Location.BITFINEX,
                category=AssetMovementCategory.WITHDRAWAL,
                address=None,
                transaction_id=None,
                asset=eur_fee_asset,
                amount=FVal('0.26300954'),
                fee_asset=eur_fee_asset,
                fee=Fee(FVal('0.00135')),
                link=str(3),
            ),
            AssetMovement(
                timestamp=Timestamp(1606996800),
                location=Location.BITFINEX,
                category=AssetMovementCategory.DEPOSIT,
                address='DESTINATION_ADDRESS',
                transaction_id='TRANSACTION_ID',
                asset=wbtc_fee_asset,
                amount=FVal('0.26300954'),
                fee_asset=wbtc_fee_asset,
                fee=Fee(FVal('0.00135')),
                link=str(4),
            ),
        ]
        assert asset_movements == expected_asset_movements

0 Source : test_bitmex.py
with GNU Affero General Public License v3.0
from rotki

def test_bitmex_api_withdrawals_deposit_unexpected_data(sandbox_bitmex):
    """Test getting unexpected data in bitmex withdrawals deposit query is handled gracefully"""

    original_input = """[{
"transactID": "b6c6fd2c-4d0c-b101-a41c-fa5aa1ce7ef1", "account": 126541, "currency": "XBt",
 "transactType": "Withdrawal", "amount": 16960386, "fee": 800, "transactStatus": "Completed",
 "address": "", "tx": "", "text": "", "transactTime": "2018-09-15T12:30:56.475Z",
 "walletBalance": 103394923, "marginBalance": null,
 "timestamp": "2018-09-15T12:30:56.475Z"}]"""
    now = ts_now()

    def query_bitmex_and_test(input_str, expected_warnings_num, expected_errors_num):
        def mock_get_deposit_withdrawal(url, data, **kwargs):  # pylint: disable=unused-argument
            return MockResponse(200, input_str)
        with patch.object(sandbox_bitmex.session, 'get', side_effect=mock_get_deposit_withdrawal):
            movements = sandbox_bitmex.query_online_deposits_withdrawals(
                start_ts=0,
                end_ts=now,
            )

        if expected_warnings_num == 0 and expected_errors_num == 0:
            assert len(movements) == 1
        else:
            assert len(movements) == 0
            errors = sandbox_bitmex.msg_aggregator.consume_errors()
            warnings = sandbox_bitmex.msg_aggregator.consume_warnings()
            assert len(errors) == expected_errors_num
            assert len(warnings) == expected_warnings_num

    # First try with correct data to make sure everything works
    query_bitmex_and_test(original_input, expected_warnings_num=0, expected_errors_num=0)

    # From here and on present unexpected data
    # invalid timestamp
    given_input = original_input.replace('"2018-09-15T12:30:56.475Z"', '"dasd"')
    query_bitmex_and_test(given_input, expected_warnings_num=0, expected_errors_num=1)

    # invalid asset
    given_input = original_input.replace('"XBt"', '[]')
    query_bitmex_and_test(given_input, expected_warnings_num=0, expected_errors_num=1)

    # unknown asset
    given_input = original_input.replace('"XBt"', '"dadsdsa"')
    query_bitmex_and_test(given_input, expected_warnings_num=1, expected_errors_num=0)

    # invalid amount
    given_input = original_input.replace('16960386', 'null')
    query_bitmex_and_test(given_input, expected_warnings_num=0, expected_errors_num=1)

    # make sure that fee null/none works
    given_input = original_input.replace('800', 'null')
    query_bitmex_and_test(given_input, expected_warnings_num=0, expected_errors_num=0)

    # invalid fee
    given_input = original_input.replace('800', '"dadsdsa"')
    query_bitmex_and_test(given_input, expected_warnings_num=0, expected_errors_num=1)

    # missing key error
    given_input = original_input.replace('"amount": 16960386,', '')
    query_bitmex_and_test(given_input, expected_warnings_num=0, expected_errors_num=1)

    # check that if 'transactType` key is missing things still work
    given_input = original_input.replace('"transactType": "Withdrawal",', '')
    query_bitmex_and_test(given_input, expected_warnings_num=0, expected_errors_num=1)


def test_bitmex_margin_history(sandbox_bitmex):

0 Source : test_bitpanda.py
with GNU Affero General Public License v3.0
from rotki

def test_balances(mock_bitpanda):
    """Test that balances are correctly queried"""

    def mock_bitpanda_query(url: str, **kwargs):  # pylint: disable=unused-argument
        if '/wallets' in url:
            return MockResponse(status_code=HTTPStatus.OK, text=WALLETS_RESPONSE)
        if '/fiatwallets' in url:
            return MockResponse(status_code=HTTPStatus.OK, text=FIAT_WALLETS_RESPONSE)
        # else
        raise AssertionError(f'Unexpected url {url} in bitpanda test')

    with patch.object(mock_bitpanda.session, 'get', side_effect=mock_bitpanda_query):
        balances, msg = mock_bitpanda.query_balances()

    warnings = mock_bitpanda.msg_aggregator.consume_warnings()
    errors = mock_bitpanda.msg_aggregator.consume_errors()
    assert len(warnings) == 0
    assert len(errors) == 0

    assert msg == ''
    assert len(balances) == 5
    assert balances[A_ETH].amount == FVal('100.55')
    assert balances[A_ETH].usd_value == FVal('301650')
    assert balances[A_BEST].amount == FVal('210')
    assert balances[A_BEST].usd_value == FVal('4200')
    assert balances[A_AXS].amount == FVal('15.5')
    assert balances[A_AXS].usd_value == FVal('620')
    assert balances[A_EUR].amount == FVal('1500.51')
    assert balances[A_EUR].usd_value == FVal('1275.4335')
    assert balances[A_TRY].amount == FVal('155.22')
    assert balances[A_TRY].usd_value == FVal('15.98766')


TRADES_RESPONSE = """{"data":[

0 Source : test_bitpanda.py
with GNU Affero General Public License v3.0
from rotki

def test_trades(mock_bitpanda):
    """Test that trades are correctly queried"""

    def mock_bitpanda_query(url: str, **kwargs):  # pylint: disable=unused-argument
        if '/wallets' in url:
            return MockResponse(status_code=HTTPStatus.OK, text=WALLETS_RESPONSE)
        if '/fiatwallets' in url:
            return MockResponse(status_code=HTTPStatus.OK, text=FIAT_WALLETS_RESPONSE)
        if '/trades' in url:
            return MockResponse(status_code=HTTPStatus.OK, text=TRADES_RESPONSE)

        # else
        raise AssertionError(f'Unexpected url {url} in bitpanda test')

    with patch.object(mock_bitpanda.session, 'get', side_effect=mock_bitpanda_query):
        trades = mock_bitpanda.query_trade_history(start_ts=0, end_ts=ts_now(), only_cache=False)

    warnings = mock_bitpanda.msg_aggregator.consume_warnings()
    errors = mock_bitpanda.msg_aggregator.consume_errors()
    assert len(warnings) == 0
    assert len(errors) == 0

    expected_trades = [Trade(
        timestamp=1634963958,
        location=Location.BITPANDA,
        base_asset=A_LTC,
        quote_asset=A_EUR,
        trade_type=TradeType.BUY,
        amount=FVal('0.00917887'),
        rate=FVal('180.85'),
        fee=FVal('1.71800028'),
        fee_currency=A_BEST,
        link='tradeid1',
    ), Trade(
        timestamp=1629440767,
        location=Location.BITPANDA,
        base_asset=A_ADA,
        quote_asset=A_EUR,
        trade_type=TradeType.SELL,
        amount=FVal('5.37267451'),
        rate=FVal('2.4079'),
        fee=ZERO,
        fee_currency=A_BEST,
        link='tradeid2',
    )]
    assert expected_trades == trades


FIATWALLETS_TX_RESPONSE = """{"data":[

0 Source : test_bitpanda.py
with GNU Affero General Public License v3.0
from rotki

def test_asset_movements(mock_bitpanda):
    """Test that deposits/withdrawals are correctly queried"""

    def mock_bitpanda_query(url: str, **kwargs):  # pylint: disable=unused-argument
        if '/wallets/transactions' in url:
            return MockResponse(status_code=HTTPStatus.OK, text=WALLET_TX_RESPONSE)
        if '/wallets' in url:
            return MockResponse(status_code=HTTPStatus.OK, text=WALLETS_RESPONSE)
        if '/fiatwallets/transactions' in url:
            return MockResponse(status_code=HTTPStatus.OK, text=FIATWALLETS_TX_RESPONSE)
        if '/fiatwallets' in url:
            return MockResponse(status_code=HTTPStatus.OK, text=FIAT_WALLETS_RESPONSE)

        # else
        raise AssertionError(f'Unexpected url {url} in bitpanda test')

    with patch.object(mock_bitpanda.session, 'get', side_effect=mock_bitpanda_query):
        movements = mock_bitpanda.query_deposits_withdrawals(
            start_ts=0,
            end_ts=ts_now(),
            only_cache=False,
        )

    warnings = mock_bitpanda.msg_aggregator.consume_warnings()
    errors = mock_bitpanda.msg_aggregator.consume_errors()
    assert len(warnings) == 0
    assert len(errors) == 0

    expected_movements = [AssetMovement(
        location=Location.BITPANDA,
        category=AssetMovementCategory.DEPOSIT,
        address=None,
        transaction_id=None,
        timestamp=1631088548,
        asset=A_EUR,
        amount=FVal('25'),
        fee_asset=A_EUR,
        fee=ZERO,
        link='movementid1',
    ), AssetMovement(
        location=Location.BITPANDA,
        category=AssetMovementCategory.WITHDRAWAL,
        address=None,
        transaction_id=None,
        timestamp=1631888548,
        asset=A_EUR,
        amount=FVal('50'),
        fee_asset=A_EUR,
        fee=FVal('0.01'),
        link='movementid2',
    ), AssetMovement(
        location=Location.BITPANDA,
        category=AssetMovementCategory.DEPOSIT,
        address='0x54dca71a34f498e3053cba240895e51da5f89d24',
        transaction_id='0x28cb2ba8ac14bdedb0ad021662b631952ce2514f1e3ff7870882ebe8a8c1b03f',
        timestamp=1633849272,
        asset=A_USDT,
        amount=FVal('6608.34105600'),
        fee_asset=A_USDT,
        fee=ZERO,
        link='XXX',
    ), AssetMovement(
        location=Location.BITPANDA,
        category=AssetMovementCategory.WITHDRAWAL,
        address='0x54dca71a34f498e3053cba240895e51da5f89d24',
        transaction_id='0xe45c1befc0968d2dab0374bc8d1aa3e193136dc769596d42e4d3274475bc7c60',
        timestamp=1597072246,
        asset=A_ETH,
        amount=FVal('1.55165264'),
        fee_asset=A_ETH,
        fee=FVal('0.00762000'),
        link='XXX',
    )]
    assert expected_movements == movements

0 Source : test_bitstamp.py
with GNU Affero General Public License v3.0
from rotki

def test_validate_api_key_err_auth_nonce(mock_bitstamp):
    """Test the error code related with the nonce authentication is properly handled"""
    def mock_api_query_response(endpoint, method='', options=None):  # pylint: disable=unused-argument  # noqa: E501
        return MockResponse(
            HTTPStatus.FORBIDDEN,
            f'{{"code": "{API_ERR_AUTH_NONCE_CODE}", "reason": "whatever"}}',
        )

    with patch.object(mock_bitstamp, '_api_query', side_effect=mock_api_query_response):
        result, msg = mock_bitstamp.query_balances()
        assert result is False
        assert msg == API_ERR_AUTH_NONCE_MESSAGE

        result, msg = mock_bitstamp.validate_api_key()
        assert result is False
        assert msg == API_ERR_AUTH_NONCE_MESSAGE

        movements = mock_bitstamp.query_online_deposits_withdrawals(0, 1)
        assert movements == []
        errors = mock_bitstamp.msg_aggregator.consume_errors()
        assert len(errors) == 1
        assert API_ERR_AUTH_NONCE_MESSAGE in errors[0]

        trades, _ = mock_bitstamp.query_online_trade_history(0, 1)
        assert trades == []
        errors = mock_bitstamp.msg_aggregator.consume_errors()
        assert len(errors) == 1
        assert API_ERR_AUTH_NONCE_MESSAGE in errors[0]


@pytest.mark.parametrize('code', API_KEY_ERROR_CODE_ACTION.keys())

0 Source : test_bitstamp.py
with GNU Affero General Public License v3.0
from rotki

def test_validate_api_key_api_key_error_code(
        mock_bitstamp,
        code,
):
    """Test an error code related with the API key ones returns a tuple with
    False (result) and a user friendly message (reason,
    from API_KEY_ERROR_CODE_ACTION values).
    """
    def mock_api_query_response(endpoint):  # pylint: disable=unused-argument
        return MockResponse(
            HTTPStatus.FORBIDDEN,
            f'{{"code": "{code}", "reason": "whatever"}}',
        )

    with patch.object(mock_bitstamp, '_api_query', side_effect=mock_api_query_response):
        result, msg = mock_bitstamp.validate_api_key()

    assert result is False
    assert msg == API_KEY_ERROR_CODE_ACTION[code]


def test_validate_api_key_success(mock_bitstamp):

See More Examples