Beispiel #1
0
def test_query_all_balances_with_manually_tracked_balances(
    rotkehlchen_api_server_with_exchanges,
    ethereum_accounts,
    btc_accounts,
    manually_tracked_balances,
):
    """Test that using the query all balances endpoint also includes manually tracked balances"""
    # Disable caching of query results
    rotki = rotkehlchen_api_server_with_exchanges.rest_api.rotkehlchen
    rotki.chain_manager.cache_ttl_secs = 0
    setup = setup_balances(
        rotki=rotki,
        ethereum_accounts=ethereum_accounts,
        btc_accounts=btc_accounts,
        manually_tracked_balances=manually_tracked_balances,
    )
    # now do the same but save the data in the DB and test it works
    # `save_data` is False by default but data will save since this is a fresh account
    with ExitStack() as stack:
        setup.enter_all_patches(stack)
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server_with_exchanges,
                "allbalancesresource",
            ), )
    assert_proper_response(response)
    json_data = response.json()
    assert_all_balances(
        data=json_data,
        db=rotki.data.db,
        expected_data_in_db=True,
        setup=setup,
    )
Beispiel #2
0
def test_qerying_settings(rotkehlchen_api_server, username):
    """Make sure that querying settings works for logged in user"""
    response = requests.get(
        api_url_for(rotkehlchen_api_server, "settingsresource"))
    assert_proper_response(response)
    json_data = response.json()

    result = json_data['result']
    assert json_data['message'] == ''
    assert result['version'] == ROTKEHLCHEN_DB_VERSION
    for setting in DBSettings._fields:
        assert setting in result

    # Logout of the active user
    data = {'action': 'logout'}
    response = requests.patch(
        api_url_for(rotkehlchen_api_server,
                    "usersbynameresource",
                    name=username),
        json=data,
    )
    assert_simple_ok_response(response)

    # and now with no logged in user it should fail
    response = requests.get(
        api_url_for(rotkehlchen_api_server, "settingsresource"))
    assert_error_response(
        response=response,
        contained_in_msg='No user is currently logged in',
        status_code=HTTPStatus.CONFLICT,
    )
Beispiel #3
0
def test_user_creation(rotkehlchen_api_server, data_dir):
    """Test that PUT at user endpoint can create a new user"""
    # Create a user without any premium credentials
    username = '******'
    data = {
        'name': username,
        'password': '******',
    }
    response = requests.put(api_url_for(rotkehlchen_api_server,
                                        "usersresource"),
                            json=data)
    assert_proper_response(response)
    check_proper_unlock_result(response.json(),
                               {'submit_usage_analytics': True})

    # Query users and make sure the new user is logged in
    response = requests.get(
        api_url_for(rotkehlchen_api_server, "usersresource"))
    assert_proper_response(response)
    json = response.json()
    assert json['result'][username] == 'loggedin'
    assert len(json['result']) == 1

    # Check that the directory was created
    assert Path(data_dir / username / 'rotkehlchen.db').exists()
Beispiel #4
0
def test_query_version_when_update_required(rotkehlchen_api_server):
    """Test that endpoint to query version works when a new version is available"""
    def patched_get_latest_release(_klass):
        new_latest = 'v99.99.99'
        return new_latest, f'https://github.com/rotki/rotki/releases/tag/{new_latest}'
    release_patch = patch(
        'rotkehlchen.externalapis.github.Github.get_latest_release',
        patched_get_latest_release,
    )
    with release_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server,
                "versionresource",
            ),
        )

    assert_proper_response(response)
    our_version = get_system_spec()['rotkehlchen']
    data = response.json()
    assert data['message'] == ''
    assert len(data['result']) == 3
    assert data['result']['our_version'] == our_version
    assert data['result']['latest_version'] == 'v99.99.99'
    assert 'v99.99.99' in data['result']['download_url']
Beispiel #5
0
def test_setup_exchange_does_not_stay_in_mapping_after_500_error(
        rotkehlchen_api_server):
    """Test that if 500 error is returned during setup of an exchange and it's stuck
    in the exchange mapping Rotki doesn't still think the exchange is registered.

    Regression test for the second part of https://github.com/rotki/rotki/issues/943
    """
    data = {'name': 'kraken', 'api_key': 'ddddd', 'api_secret': 'fffffff'}
    with API_KEYPAIR_KRAKEN_VALIDATION_FAIL_PATCH:
        response = requests.put(
            api_url_for(rotkehlchen_api_server, "exchangesresource"),
            json=data,
        )
    assert_error_response(
        response=response,
        status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
    )

    # Now try to register the exchange again
    data = {'name': 'kraken', 'api_key': 'ddddd', 'api_secret': 'fffffff'}
    with API_KEYPAIR_VALIDATION_PATCH:
        response = requests.put(
            api_url_for(rotkehlchen_api_server, "exchangesresource"),
            json=data,
        )
    assert_simple_ok_response(response)

    # and check that kraken is now registered
    response = requests.get(
        api_url_for(rotkehlchen_api_server, "exchangesresource"))
    assert_proper_response(response)
    json_data = response.json()
    assert json_data['message'] == ''
    assert json_data['result'] == ['kraken']
Beispiel #6
0
def test_query_periodic(rotkehlchen_api_server_with_exchanges):
    rotki = rotkehlchen_api_server_with_exchanges.rest_api.rotkehlchen
    rotki.chain_manager.cache_ttl_secs = 0
    setup = setup_balances(rotki, ethereum_accounts=[], btc_accounts=[])
    start_ts = ts_now()

    # Query trades of an exchange to get them saved in the DB
    with setup.binance_patch, setup.poloniex_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server_with_exchanges,
                "allbalancesresource",
            ),
            json={'save_data': True},
        )
    assert_proper_response(response)

    response = requests.get(
        api_url_for(rotkehlchen_api_server_with_exchanges,
                    "periodicdataresource"), )
    assert_proper_response(response)
    data = response.json()
    assert data['message'] == ''
    assert len(data['result']) == 3
    assert data['result']['last_balance_save'] >= start_ts
    assert data['result']['eth_node_connection'] is False
    # Non -1 value tests for these exist in test_history.py::test_query_history_timerange
    assert data['result']['last_data_upload_ts'] == 0
Beispiel #7
0
def test_query_version_when_up_to_date(rotkehlchen_api_server):
    """Test that endpoint to query the rotki version works if no new version is available"""
    expected_version = 'v1.1.0'

    def patched_get_system_spec() -> Dict[str, Any]:
        return {'rotkehlchen': expected_version}

    def patched_get_latest_release(_klass):
        return expected_version, f'https://github.com/rotki/rotki/releases/tag/{expected_version}'
    release_patch = patch(
        'rotkehlchen.externalapis.github.Github.get_latest_release',
        patched_get_latest_release,
    )
    version_patch = patch(
        'rotkehlchen.utils.version_check.get_system_spec',
        patched_get_system_spec,
    )

    with version_patch, release_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server,
                "versionresource",
            ),
        )

    assert_proper_response(response)
    data = response.json()
    assert data['message'] == ''
    assert len(data['result']) == 3
    assert data['result']['our_version'] == expected_version
    assert data['result']['latest_version'] == expected_version
    assert data['result']['download_url'] is None
Beispiel #8
0
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:
        assert_proper_response(response)
        data = response.json()
        assert data['message'] == ''
        assert data['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,
        )
Beispiel #9
0
def test_set_rpc_endpoint_fail_not_set_others(rotkehlchen_api_server):
    """Test that setting a non-existing eth rpc along with other settings does not modify them"""
    eth_rpc_endpoint = 'http://working.nodes.com:8545'
    main_currency = A_JPY
    data = {
        'settings': {
            'eth_rpc_endpoint': eth_rpc_endpoint,
            'main_currency': main_currency.identifier,
        }
    }

    response = requests.put(api_url_for(rotkehlchen_api_server,
                                        "settingsresource"),
                            json=data)
    assert_error_response(
        response=response,
        contained_in_msg=
        (f'Failed to connect to ethereum node own node at endpoint {eth_rpc_endpoint}'
         ),
        status_code=HTTPStatus.CONFLICT,
    )

    # Get settings and make sure they have not been modified
    response = requests.get(
        api_url_for(rotkehlchen_api_server, "settingsresource"))
    assert_proper_response(response)
    json_data = response.json()
    result = json_data['result']
    assert json_data['message'] == ''
    assert result['main_currency'] != 'JPY'
    assert result['eth_rpc_endpoint'] != 'http://working.nodes.com:8545'
Beispiel #10
0
def test_removing_ethereum_tokens(
    rotkehlchen_api_server,
    ethereum_accounts,
):
    """Test that the rest api endpoint to add new ethereum tokens works properly"""
    rotki = rotkehlchen_api_server.rest_api.rotkehlchen
    setup = setup_balances(
        rotki,
        ethereum_accounts=ethereum_accounts,
        token_balances={
            A_RDN: ['0', '0'],
            A_DAI: ['50000000', '0'],
            A_GNO: ['0', '0'],
        },
        btc_accounts=[],
    )

    # Remove GNO and RDN as tracked tokens and make sure that the dai balance checks out
    with setup.etherscan_patch, setup.alethio_patch:
        response = requests.delete(api_url_for(
            rotkehlchen_api_server,
            "ethereumtokensresource",
        ),
                                   json={'eth_tokens': ['GNO', 'RDN']})

    assert_proper_response(response)
    json_data = response.json()
    assert json_data['message'] == ''
    assert_modifying_ethereum_tokens(
        rotkehlchen_api_server,
        json_data,
        ethereum_accounts,
        setup,
        ['DAI'],
    )
Beispiel #11
0
def test_unset_rpc_endpoint(rotkehlchen_api_server):
    """Test the rpc endpoint can be unset"""
    response = requests.get(
        api_url_for(rotkehlchen_api_server, "settingsresource"))
    assert_proper_response(response)
    json_data = response.json()
    assert json_data['message'] == ''
    result = json_data['result']
    assert result['eth_rpc_endpoint'] != ''

    data = {
        'settings': {
            'eth_rpc_endpoint': ''
        },
    }

    response = requests.put(api_url_for(rotkehlchen_api_server,
                                        "settingsresource"),
                            json=data)
    assert_proper_response(response)

    json_data = response.json()
    result = json_data['result']
    assert json_data['message'] == ''
    assert result['eth_rpc_endpoint'] == ''
Beispiel #12
0
def test_query_owned_assets(
        rotkehlchen_api_server_with_exchanges,
        ethereum_accounts,
        btc_accounts,
        number_of_eth_accounts,
):
    """Test that using the query all owned assets endpoint works"""
    # Disable caching of query results
    rotki = rotkehlchen_api_server_with_exchanges.rest_api.rotkehlchen
    rotki.chain_manager.cache_ttl_secs = 0
    setup = setup_balances(rotki, ethereum_accounts, btc_accounts)

    # Get all our mocked balances and save them in the DB
    with setup.poloniex_patch, setup.binance_patch, setup.etherscan_patch, setup.bitcoin_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server_with_exchanges,
                "allbalancesresource",
            ), json={'save_data': True},
        )
    assert_proper_response(response)

    # And now check that the query owned assets endpoint works
    with setup.poloniex_patch, setup.binance_patch, setup.etherscan_patch, setup.bitcoin_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server_with_exchanges,
                "ownedassetsresource",
            ),
        )
    assert_proper_response(response)
    data = response.json()
    assert data['message'] == ''
    assert set(data['result']) == {'ETH', 'BTC', 'EUR', 'RDN'}
Beispiel #13
0
def test_disable_taxfree_after_period(rotkehlchen_api_server):
    """Test that providing -1 for the taxfree_after_period setting disables it """
    data = {
        'taxfree_after_period': -1,
    }
    response = requests.put(api_url_for(rotkehlchen_api_server, "settingsresource"), json=data)
    assert_proper_response(response)
    json_data = response.json()
    assert json_data['result']['taxfree_after_period'] is None

    # Test that any other negative value is refused
    data = {
        'taxfree_after_period': -5,
    }
    response = requests.put(api_url_for(rotkehlchen_api_server, "settingsresource"), json=data)
    assert_error_response(
        response=response,
        contained_in_msg='The taxfree_after_period value can not be negative',
        status_code=HTTPStatus.BAD_REQUEST,
    )
    # Test that zero value is refused
    data = {
        'taxfree_after_period': 0,
    }
    response = requests.put(api_url_for(rotkehlchen_api_server, "settingsresource"), json=data)
    assert_error_response(
        response=response,
        contained_in_msg='The taxfree_after_period value can not be set to zero',
        status_code=HTTPStatus.BAD_REQUEST,
    )
Beispiel #14
0
def test_remove_exchange(rotkehlchen_api_server):
    """Test that removing a setup exchange via the api works"""
    rotki = rotkehlchen_api_server.rest_api.rotkehlchen
    db = rotki.data.db
    # Setup coinbase exchange
    data = {'name': 'coinbase', 'api_key': 'ddddd', 'api_secret': 'fffffff'}
    with API_KEYPAIR_COINBASE_VALIDATION_PATCH:
        response = requests.put(
            api_url_for(rotkehlchen_api_server, "exchangesresource"),
            json=data,
        )
    assert_simple_ok_response(response)

    # Add query ranges to see that they also get deleted when removing the exchange
    cursor = db.conn.cursor()
    cursor.executemany(
        'INSERT OR REPLACE INTO used_query_ranges(name, start_ts, end_ts) VALUES (?, ?, ?)',
        [('coinbasepro_trades', 0, 1579564096),
         ('coinbasepro_margins', 0, 1579564096),
         ('coinbasepro_asset_movements', 0, 1579564096),
         ('coinbase_trades', 0, 1579564096),
         ('coinbase_margins', 0, 1579564096),
         ('coinbase_asset_movements', 0, 1579564096),
         ('binance_trades', 0, 1579564096), ('binance_margins', 0, 1579564096),
         ('binance_asset_movements', 0, 1579564096)],
    )

    # Now remove the registered coinbase exchange
    data = {'name': 'coinbase'}
    response = requests.delete(api_url_for(rotkehlchen_api_server,
                                           "exchangesresource"),
                               json=data)
    assert_simple_ok_response(response)
    # and check that it's not registered anymore
    response = requests.get(
        api_url_for(rotkehlchen_api_server, "exchangesresource"))
    assert_proper_response(response)
    json_data = response.json()
    assert json_data['message'] == ''
    assert json_data['result'] == []
    # Also check that the coinbase query ranges have been deleted but not the other ones
    cursor = db.conn.cursor()
    result = cursor.execute('SELECT name from used_query_ranges')
    count = 0
    for entry in result:
        count += 1
        msg = 'only binance or coinbasepro query ranges should remain'
        assert 'binance' in entry[0] or 'coinbasepro' in entry[0], msg
    assert count == 6, 'only 6 query ranges should remain in the DB'

    # now try to remove a non-registered exchange
    data = {'name': 'binance'}
    response = requests.delete(api_url_for(rotkehlchen_api_server,
                                           "exchangesresource"),
                               json=data)
    assert_error_response(
        response=response,
        contained_in_msg='Exchange binance is not registered',
        status_code=HTTPStatus.CONFLICT,
    )
Beispiel #15
0
def test_query_historical_dsr(
    rotkehlchen_api_server,
    ethereum_accounts,
):
    rotki = rotkehlchen_api_server.rest_api.rotkehlchen
    account1 = ethereum_accounts[0]
    account2 = ethereum_accounts[2]
    setup = setup_tests_for_dsr(
        etherscan=rotki.etherscan,
        account1=account1,
        account2=account2,
        original_requests_get=requests.get,
    )
    with setup.etherscan_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server,
                "makerdaodsrhistoryresource",
            ))

    assert_proper_response(response)
    json_data = response.json()
    assert json_data['message'] == ''
    result = json_data['result']
    assert_dsr_history_result_is_correct(result, setup)
Beispiel #16
0
def test_query_statistics_netvalue(
    rotkehlchen_api_server_with_exchanges,
    ethereum_accounts,
    btc_accounts,
):
    """Test that using the statistics netvalue over time endpoint works"""
    # Disable caching of query results
    rotki = rotkehlchen_api_server_with_exchanges.rest_api.rotkehlchen
    rotki.chain_manager.cache_ttl_secs = 0
    setup = setup_balances(rotki, ethereum_accounts, btc_accounts)

    # query balances and save data in DB to have data to test the statistics endpoint
    with ExitStack() as stack:
        setup.enter_all_patches(stack)
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server_with_exchanges,
                "allbalancesresource",
            ),
            json={'save_data': True},
        )
    assert_proper_response(response)

    # and now test that statistics work fine
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server_with_exchanges,
            "statisticsnetvalueresource",
        ), )

    result = assert_proper_response_with_result(response)
    assert len(result) == 2
    assert len(result['times']) == 1
    assert len(result['data']) == 1
Beispiel #17
0
def check_user_status(api_server) -> Dict[str, str]:
    # Check users status
    response = requests.get(api_url_for(api_server, "usersresource"), )
    assert_proper_response(response)
    data = response.json()
    assert data['message'] == ''
    return response.json()['result']
Beispiel #18
0
def test_query_historical_dsr(
        rotkehlchen_api_server,
        ethereum_accounts,
        inquirer,  # pylint: disable=unused-argument
):
    """Test DSR history is correctly queried

    This (and the async version) is a very hard to maintain test due to mocking
    everything.

    TODO: Perhaps change it to querying etherscan/chain until a given block for a
    given DSR account and check that until then all data match.
    """
    rotki = rotkehlchen_api_server.rest_api.rotkehlchen
    account1 = ethereum_accounts[0]
    account2 = ethereum_accounts[2]
    setup = setup_tests_for_dsr(
        etherscan=rotki.etherscan,
        account1=account1,
        account2=account2,
        original_requests_get=requests.get,
    )
    with setup.etherscan_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server,
                "makerdaodsrhistoryresource",
            ))

    assert_proper_response(response)
    json_data = response.json()
    assert json_data['message'] == ''
    result = json_data['result']
    assert_dsr_history_result_is_correct(result, setup)
Beispiel #19
0
def test_query_history_timerange(rotkehlchen_api_server_with_exchanges):
    """Same as test_query_history but on a limited timerange"""
    rotki = rotkehlchen_api_server_with_exchanges.rest_api.rotkehlchen
    start_ts = 1539713237
    end_ts = 1539713238
    setup = prepare_rotki_for_history_processing_test(
        rotki,
        should_mock_history_processing=False,
        history_start_ts=start_ts,
        history_end_ts=end_ts,
    )

    # Query history processing to start the history processing
    with ExitStack() as stack:
        for manager in setup:
            if manager is None:
                continue
            stack.enter_context(manager)
        response = requests.get(
            api_url_for(rotkehlchen_api_server_with_exchanges,
                        "historyprocessingresource"),
            json={
                'from_timestamp': start_ts,
                'to_timestamp': end_ts
            },
        )

    # Simply check that the results got returned here. The actual correctness of
    # accounting results is checked in other tests such as test_simple_accounting
    assert_proper_response(response)
    data = response.json()
    assert data['message'] == ''
    assert len(data['result']) == 2
    overview = data['result']['overview']
    assert len(overview) == 11
    assert overview["loan_profit"] is not None
    assert overview["margin_positions_profit_loss"] is not None
    assert overview["settlement_losses"] is not None
    assert overview["ethereum_transaction_gas_costs"] is not None
    assert overview["asset_movement_fees"] is not None
    assert overview["general_trade_profit_loss"] is not None
    assert overview["taxable_trade_profit_loss"] is not None
    assert overview["total_taxable_profit_loss"] is not None
    assert overview["total_profit_loss"] is not None
    assert overview["defi_profit_loss"] is not None
    assert overview["ledger_actions_profit_loss"] is not None
    all_events = data['result']['all_events']
    assert isinstance(all_events, list)
    assert len(all_events) == 4

    response = requests.get(
        api_url_for(rotkehlchen_api_server_with_exchanges,
                    "periodicdataresource"), )
    assert_proper_response(response)
    data = response.json()
    assert data['result']['last_balance_save'] == 0
    assert data['result']['eth_node_connection'] is False
    assert data['result']['history_process_start_ts'] == 1428994442
    assert data['result']['history_process_current_ts'] == end_ts
Beispiel #20
0
 def assert_okay(response):
     """Helper function to run next query and its assertion twice"""
     assert_proper_response(response)
     data = response.json()
     assert data['message'] == ''
     assert len(data['result']) == 2  # only 2 binance trades
     assert_binance_trades_result(
         [t for t in data['result'] if t['location'] == 'binance'])
Beispiel #21
0
def test_history_export_csv_errors(
        rotkehlchen_api_server_with_exchanges,
        tmpdir_factory,
):
    """Test that errors on the csv export REST API endpoint are handled correctly"""
    rotki = rotkehlchen_api_server_with_exchanges.rest_api.rotkehlchen
    setup = prepare_rotki_for_history_processing_test(
        rotki,
        should_mock_history_processing=False,
    )
    csv_dir = str(tmpdir_factory.mktemp('test_csv_dir'))

    # Query the export endpoint without first having queried the history
    response = requests.get(
        api_url_for(rotkehlchen_api_server_with_exchanges, "historyexportingresource"),
        json={'directory_path': csv_dir},
    )
    assert_error_response(
        response=response,
        contained_in_msg='No history processed in order to perform an export',
        status_code=HTTPStatus.CONFLICT,
    )

    # Now, query history processing to have data for exporting
    with ExitStack() as stack:
        for manager in setup:
            if manager is None:
                continue
            stack.enter_context(manager)
        response = requests.get(
            api_url_for(rotkehlchen_api_server_with_exchanges, "historyprocessingresource"),
        )
    assert_proper_response(response)

    # And now provide non-existing path for directory
    response = requests.get(
        api_url_for(rotkehlchen_api_server_with_exchanges, "historyexportingresource"),
        json={'directory_path': '/idont/exist/for/sure/'},
    )
    assert_error_response(
        response=response,
        contained_in_msg='"directory_path": ["Given path /idont/exist/for/sure/ does not exist',
        status_code=HTTPStatus.BAD_REQUEST,
    )

    # And now provide valid path but not directory
    tempfile = Path(Path(csv_dir) / 'f.txt')
    tempfile.touch()
    response = requests.get(
        api_url_for(rotkehlchen_api_server_with_exchanges, "historyexportingresource"),
        json={'directory_path': str(tempfile)},
    )
    assert_error_response(
        response=response,
        contained_in_msg='is not a directory',
        status_code=HTTPStatus.BAD_REQUEST,
    )
Beispiel #22
0
def test_query_async_task_that_died(rotkehlchen_api_server_with_exchanges):
    """If an async task dies with an exception check that it's properly handled"""

    # async query balances of one specific exchange
    server = rotkehlchen_api_server_with_exchanges
    binance = server.rest_api.rotkehlchen.exchange_manager.connected_exchanges[
        'binance']

    def mock_binance_asset_return(url):  # pylint: disable=unused-argument
        raise ValueError('BOOM!')

    binance_patch = patch.object(binance.session,
                                 'get',
                                 side_effect=mock_binance_asset_return)

    # Create an async task
    with binance_patch:
        response = requests.get(api_url_for(
            server,
            "named_exchanges_balances_resource",
            name='binance',
        ),
                                json={'async_query': True})
    task_id = assert_ok_async_response(response)

    # now check that there is a task
    response = requests.get(api_url_for(server, "asynctasksresource"))
    assert_proper_response(response)
    json_data = response.json()
    assert json_data['message'] == ''
    assert json_data['result'] == [task_id]

    while True:
        # and now query for the task result and assert on it
        response = requests.get(
            api_url_for(server,
                        "specific_async_tasks_resource",
                        task_id=task_id), )
        assert_proper_response(response)
        json_data = response.json()
        if json_data['result']['status'] == 'pending':
            # context switch so that the greenlet to query balances can operate
            gevent.sleep(1)
        elif json_data['result']['status'] == 'completed':
            break
        else:
            raise AssertionError(
                f"Unexpected status: {json_data['result']['status']}")

    assert json_data['message'] == ''
    assert json_data['result']['status'] == 'completed'
    # assert that the backend task query died and we detect it
    assert json_data['result']['outcome'] is not None
    assert json_data['result']['outcome']['result'] is None
    msg = 'The backend query task died unexpectedly: BOOM!'
    assert json_data['result']['outcome']['message'] == msg
Beispiel #23
0
 def assert_okay(response):
     """Helper function for DRY checking below assertions"""
     assert_proper_response(response)
     json_data = response.json()
     assert json_data['message'] == ''
     assert len(json_data['result']
                ) == 2, 'only two exchanges should be registered'
     assert_binance_trades_result(json_data['result']['binance'])
     assert_poloniex_trades_result(json_data['result']['poloniex'],
                                   trades_to_check=(0, ))
Beispiel #24
0
 def assert_okay(response):
     """Helper function for DRY checking below assertions"""
     assert_proper_response(response)
     json_data = response.json()
     assert json_data['message'] == ''
     result = json_data['result']
     assert len(result) == 3
     assert FVal(result['EUR']) > 0
     assert FVal(result['USD']) > 0
     assert FVal(result['KRW']) > 0
Beispiel #25
0
def test_loggedin_user_querying(rotkehlchen_api_server, username, data_dir):
    """Start with a logged in user and make sure we can query all users"""
    Path(data_dir / 'another_user').mkdir()
    Path(data_dir / 'another_user' / 'rotkehlchen.db').touch()
    response = requests.get(api_url_for(rotkehlchen_api_server, "usersresource"))
    assert_proper_response(response)
    json = response.json()
    assert json['result'][username] == 'loggedin'
    assert json['result']['another_user'] == 'loggedout'
    assert len(json['result']) == 2
Beispiel #26
0
def test_query_all_assets(rotkehlchen_api_server):
    """Test that using the query all owned assets endpoint works

    Compare with the contents of all_assets.json. Essentially tests that priming the DB works.

    That's why there is quite a few extra checks for things that changed
    when moving to global DB
    """
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            "allassetsresource",
        ),
    )
    assert_proper_response(response)
    data = response.json()
    assert data['message'] == ''

    dir_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
    with open(os.path.join(dir_path, 'data', 'all_assets.json'), 'r') as f:
        expected_assets = json.loads(f.read())

    returned_ids = set(data['result'].keys())
    expected_ids = set(expected_assets.keys())
    expected_missing_ids = {'XD'}
    assert expected_ids - returned_ids == expected_missing_ids, f'Missing ids: {expected_ids - returned_ids - expected_missing_ids}'  # noqa: E501

    for asset_id, entry_data in data['result'].items():
        for key, val in entry_data.items():
            if key in ('active', 'ended'):
                continue  # we ignore these keys after DB insertion

            other_key = key
            if key == 'asset_type':
                other_key = 'type'
            elif key == 'decimals':
                other_key = 'ethereum_token_decimals'

            if val is not None:
                is_ethereum_token_and_more = (
                    key == 'asset_type' and
                    val == 'ethereum token' and
                    expected_assets[asset_id][other_key] == 'ethereum token and more'
                )
                if is_ethereum_token_and_more:
                    continue  # we ignore this distinction in the DB

                expected_val = expected_assets[asset_id][other_key]
                if key == 'asset_type':
                    expected_val = expected_val.lower()
                    if expected_val == 'ethereum token and own chain':
                        expected_val = 'own chain'
                assert val == expected_val, f'mismatch of {other_key} for {asset_id}'  # noqa: E501
            else:
                assert other_key not in expected_assets[asset_id]
Beispiel #27
0
def test_query_ping(rotkehlchen_api_server):
    """Test that the ping endpoint works"""
    expected_result = True
    expected_message = ''

    response = requests.get(api_url_for(rotkehlchen_api_server,
                                        "pingresource"))
    assert_proper_response(response)
    response_json = response.json()
    assert len(response_json) == 2
    assert response_json['result'] == expected_result
    assert response_json['message'] == expected_message
Beispiel #28
0
def test_edit_trades(rotkehlchen_api_server_with_exchanges):
    """Test that editing a trade via the trades endpoint works as expected"""
    rotki = rotkehlchen_api_server_with_exchanges.rest_api.rotkehlchen
    setup = mock_history_processing_and_exchanges(rotki)

    # Simply get all trades without any filtering
    with setup.binance_patch, setup.polo_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server_with_exchanges,
                "tradesresource",
            ), )
    assert_proper_response(response)
    trades = response.json()['result']['entries']

    # get the binance trades
    original_binance_trades = [
        t['entry'] for t in trades if t['entry']['location'] == 'binance'
    ]

    for trade in original_binance_trades:
        # edit two fields of each binance trade
        trade['amount'] = '1337.5'
        trade['notes'] = 'edited trade'
        response = requests.patch(
            api_url_for(
                rotkehlchen_api_server_with_exchanges,
                "tradesresource",
            ),
            json=trade,
        )
        assert_proper_response(response)
        data = response.json()
        assert data['message'] == ''
        # check that the returned trade is edited
        _check_trade_is_edited(original_trade=trade,
                               result_trade=data['result'])

    # Finally also query binance trades to see they are edited
    with setup.binance_patch, setup.polo_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server_with_exchanges,
                "tradesresource",
            ),
            json={'location': 'binance'},
        )
    trades = assert_proper_response_with_result(response)['entries']
    assert len(trades) == 2  # only 2 binance trades
    for idx, trade in enumerate(trades):
        _check_trade_is_edited(original_trade=original_binance_trades[idx],
                               result_trade=trade['entry'])  # noqa: E501
Beispiel #29
0
def test_query_all_balances(
        rotkehlchen_api_server_with_exchanges,
        ethereum_accounts,
        btc_accounts,
        number_of_eth_accounts,
):
    """Test that using the query all balances endpoint works

    Test that balances from various sources are returned. Such as exchanges,
    blockchain and FIAT"""
    # Disable caching of query results
    rotki = rotkehlchen_api_server_with_exchanges.rest_api.rotkehlchen
    rotki.chain_manager.cache_ttl_secs = 0
    setup = setup_balances(rotki, ethereum_accounts, btc_accounts)
    # Test all balances request by requesting to not save the data
    with ExitStack() as stack:
        setup.enter_all_patches(stack)
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server_with_exchanges,
                "allbalancesresource",
            ), json={'save_data': False},
        )

    assert_proper_response(response)
    json_data = response.json()
    assert_all_balances(
        data=json_data,
        db=rotki.data.db,
        expected_data_in_db=False,
        setup=setup,
    )

    # now do the same but save the data in the DB and test it works
    # Omit the argument to test that default value of save_data is True
    with ExitStack() as stack:
        setup.enter_all_patches(stack)
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server_with_exchanges,
                "allbalancesresource",
            ),
        )
    assert_proper_response(response)
    json_data = response.json()
    assert_all_balances(
        data=json_data,
        db=rotki.data.db,
        expected_data_in_db=True,
        setup=setup,
    )
Beispiel #30
0
def test_exchange_query_trades(rotkehlchen_api_server_with_exchanges):
    """Test that using the exchange trades query endpoint works fine"""
    server = rotkehlchen_api_server_with_exchanges
    setup = mock_history_processing_and_exchanges(server.rest_api.rotkehlchen)
    # query trades of one specific exchange
    with setup.binance_patch:
        response = requests.get(
            api_url_for(
                server,
                "named_exchanges_trades_resource",
                name='binance',
            ))
    assert_proper_response(response)
    json_data = response.json()
    assert json_data['message'] == ''
    assert_binance_trades_result(json_data['result'])

    # query trades of all exchanges
    with setup.binance_patch, setup.polo_patch:
        response = requests.get(api_url_for(server, "exchangetradesresource"))
    assert_proper_response(response)
    json_data = response.json()
    assert json_data['message'] == ''
    assert len(
        json_data['result']) == 2, 'only two exchanges should be registered'
    assert_binance_trades_result(json_data['result']['binance'])
    assert_poloniex_trades_result(json_data['result']['poloniex'])

    def assert_okay(response):
        """Helper function for DRY checking below assertions"""
        assert_proper_response(response)
        json_data = response.json()
        assert json_data['message'] == ''
        assert len(json_data['result']
                   ) == 2, 'only two exchanges should be registered'
        assert_binance_trades_result(json_data['result']['binance'])
        assert_poloniex_trades_result(json_data['result']['poloniex'],
                                      trades_to_check=(0, ))

    # and now query them in a specific time range excluding two of poloniex's trades
    data = {'from_timestamp': 1499865548, 'to_timestamp': 1539713118}
    with setup.binance_patch, setup.polo_patch:
        response = requests.get(api_url_for(server, "exchangetradesresource"),
                                json=data)
    assert_okay(response)
    # do the same but with query args. This serves as test of from/to timestamp with query args
    with setup.binance_patch, setup.polo_patch:
        response = requests.get(
            api_url_for(server, "exchangetradesresource") + '?' +
            urlencode(data))
    assert_okay(response)