Beispiel #1
0
def test_query_aave_balances_module_not_activated(
    rotkehlchen_api_server,
    ethereum_accounts,
):
    async_query = random.choice([False, True])
    rotki = rotkehlchen_api_server.rest_api.rotkehlchen
    setup = setup_balances(rotki,
                           ethereum_accounts=ethereum_accounts,
                           btc_accounts=None)

    with ExitStack() as stack:
        # patch ethereum/etherscan to not autodetect tokens
        setup.enter_ethereum_patches(stack)
        response = requests.get(api_url_for(
            rotkehlchen_api_server,
            "aavebalancesresource",
        ),
                                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['result'] is None
            assert outcome['message'] == 'aave module is not activated'
        else:
            assert_error_response(
                response=response,
                contained_in_msg='aave module is not activated',
                status_code=HTTPStatus.CONFLICT,
            )
def test_custom_tokens_delete_guard(rotkehlchen_api_server):
    """Test that deleting an owned ethereum token is guarded against"""
    user_db = rotkehlchen_api_server.rest_api.rotkehlchen.data.db
    token0_id = ETHEREUM_DIRECTIVE + INITIAL_TOKENS[0].ethereum_address
    user_db.add_manually_tracked_balances([
        ManuallyTrackedBalance(
            id=-1,
            asset=Asset(token0_id),
            label='manual1',
            amount=FVal(1),
            location=Location.EXTERNAL,
            tags=None,
            balance_type=BalanceType.ASSET,
        )
    ])

    # Try to delete the token and see it fails because a user owns it
    response = requests.delete(
        api_url_for(
            rotkehlchen_api_server,
            'ethereumassetsresource',
        ),
        json={'address': INITIAL_TOKENS[0].ethereum_address},
    )
    expected_msg = 'Failed to delete asset with id'
    assert_error_response(
        response=response,
        contained_in_msg=expected_msg,
        status_code=HTTPStatus.CONFLICT,
    )
Beispiel #3
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 #4
0
def test_delete_tag_errors(rotkehlchen_api_server, ):
    """Test that errors in input data while deleting a tag are handled correctly"""
    # Name missing
    data = {}
    response = requests.delete(
        api_url_for(
            rotkehlchen_api_server,
            "tagsresource",
        ),
        json=data,
    )
    assert_error_response(
        response=response,
        contained_in_msg='name": ["Missing data for required field',
        status_code=HTTPStatus.BAD_REQUEST,
    )
    # Invalid type for name
    data = {'name': 55.52}
    response = requests.delete(
        api_url_for(
            rotkehlchen_api_server,
            "tagsresource",
        ),
        json=data,
    )
    assert_error_response(
        response=response,
        contained_in_msg='name": ["Not a valid string',
        status_code=HTTPStatus.BAD_REQUEST,
    )
Beispiel #5
0
def test_query_all_balances_errors(rotkehlchen_api_server):
    """Test that errors are handled correctly by the all balances endpoint"""
    # invoke the endpoint with non boolean save_data
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            "allbalancesresource",
        ),
        json={'save_data': 14545},
    )
    assert_error_response(
        response=response,
        contained_in_msg='Not a valid boolean',
        status_code=HTTPStatus.BAD_REQUEST,
    )
    # invoke the endpoint with non boolean async_query
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            "allbalancesresource",
        ),
        json={'async_query': 14545},
    )
    assert_error_response(
        response=response,
        contained_in_msg='Not a valid boolean',
        status_code=HTTPStatus.BAD_REQUEST,
    )
Beispiel #6
0
def test_query_statistics_value_distribution_errors(rotkehlchen_api_server):
    """Test that the statistics value distribution endpoint handles errors properly"""
    # Test omitting the distribution_by argument
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            "statisticsvaluedistributionresource",
        ), )
    assert_error_response(
        response=response,
        contained_in_msg='Missing data for required field',
        status_code=HTTPStatus.BAD_REQUEST,
    )

    # Test invalid value for distribution_by
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            "statisticsvaluedistributionresource",
        ),
        json={'distribution_by': 'haircolor'},
    )
    assert_error_response(
        response=response,
        contained_in_msg='Must be one of: location, asset',
        status_code=HTTPStatus.BAD_REQUEST,
    )
Beispiel #7
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 #8
0
def test_exchange_query_balances_errors(rotkehlchen_api_server_with_exchanges):
    """Test errors and edge cases of the exchange balances query endpoint"""
    server = rotkehlchen_api_server_with_exchanges
    # Invalid exchange
    response = requests.get(
        api_url_for(
            server,
            "named_exchanges_balances_resource",
            name='dasdsad',
        ))
    assert_error_response(
        response=response,
        contained_in_msg='Exchange dasdsad is not supported',
        status_code=HTTPStatus.BAD_REQUEST,
    )

    # not registered exchange
    response = requests.get(
        api_url_for(
            server,
            "named_exchanges_balances_resource",
            name='kraken',
        ))
    assert_error_response(
        response=response,
        contained_in_msg=
        'Could not query balances for kraken since it is not registered',
        status_code=HTTPStatus.CONFLICT,
    )
Beispiel #9
0
def test_upload_custom_icon_errors(rotkehlchen_api_server, file_upload):
    """Test that common error handling for uploading custom icons"""
    root_path = Path(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))  # noqa: E501
    filepath = root_path / 'frontend' / 'app' / 'src' / 'assets' / 'images' / 'kraken.png'

    # Let's also try to upload a file without the csv prefix
    with TemporaryDirectory() as temp_directory:
        bad_filepath = Path(temp_directory) / 'somefile.bad'
        shutil.copyfile(filepath, bad_filepath)
        if file_upload:
            files = {'file': open(bad_filepath, 'rb')}
            response = requests.post(
                api_url_for(
                    rotkehlchen_api_server,
                    'asseticonsresource',
                    asset='GNO',
                ),
                files=files,
            )
        else:
            json_data = {'file': str(bad_filepath)}
            response = requests.put(
                api_url_for(
                    rotkehlchen_api_server,
                    'asseticonsresource',
                    asset='GNO',
                ), json=json_data,
            )

    assert_error_response(
        response=response,
        contained_in_msg='does not end in any of .png,.svg,jpeg,jpg',
        status_code=HTTPStatus.BAD_REQUEST,
    )
Beispiel #10
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 #11
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='Failed to connect to ethereum node at 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 #12
0
def test_add_edit_ledger_actions_with_timestamp(rotkehlchen_api_server):
    """Test that the user can't pass future dates when creating/editing ledger actions"""
    error_msg = 'Given date cannot be in the future'
    action = {
        'timestamp': Timestamp(ts_now() - 5),
        'action_type': 'dividends income',
        'location': 'external',
        'amount': '75',
        'asset': 'EUR',
        'rate': '1.23',
        'rate_asset': None,
        'link': 'APPL_dividens_income_id',
        'notes': None,
    }

    response = requests.put(
        api_url_for(rotkehlchen_api_server, 'ledgeractionsresource'),
        json=action,
    )
    result = assert_proper_response_with_result(response)
    assert 'identifier' in result
    action['identifier'] = int(result['identifier'])

    # Now add an action with a date after the valid ts_now
    action['timestamp'] = Timestamp(ts_now() + 45)
    response = requests.put(
        api_url_for(rotkehlchen_api_server, 'ledgeractionsresource'),
        json=action,
    )
    assert_error_response(
        response,
        contained_in_msg=error_msg,
        status_code=HTTPStatus.BAD_REQUEST,
    )

    # Try to edit the first action and check that a invalid date fails
    response = requests.patch(
        api_url_for(
            rotkehlchen_api_server,
            'ledgeractionsresource',
        ),
        json=action,
    )
    assert_error_response(
        response,
        contained_in_msg=error_msg,
        status_code=HTTPStatus.BAD_REQUEST,
    )

    # And finally try to edit with the right date
    action['timestamp'] = Timestamp(ts_now())
    response = requests.patch(
        api_url_for(
            rotkehlchen_api_server,
            'ledgeractionsresource',
        ),
        json=action,
    )
    result = assert_proper_response_with_result(response)
def test_editing_custom_tokens(rotkehlchen_api_server):
    """Test that the endpoint for editing a custom ethereum token works"""
    new_token1 = INITIAL_TOKENS[0].serialize_all_info()
    del new_token1['identifier']
    new_name = 'Edited token'
    new_symbol = 'ESMBL'
    new_protocol = 'curve'
    new_swapped_for = A_BAT.identifier
    new_token1['name'] = new_name
    new_token1['symbol'] = new_symbol
    new_token1['swapped_for'] = new_swapped_for
    new_token1['protocol'] = new_protocol
    response = requests.patch(
        api_url_for(
            rotkehlchen_api_server,
            'ethereumassetsresource',
        ),
        json={'token': new_token1},
    )
    result = assert_proper_response_with_result(response)
    token0_id = ETHEREUM_DIRECTIVE + INITIAL_TOKENS[0].ethereum_address
    assert result == {'identifier': token0_id}

    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            'ethereumassetsresource',
        ),
    )
    result = assert_proper_response_with_result(response)
    expected_tokens = deepcopy(INITIAL_EXPECTED_TOKENS)
    object.__setattr__(expected_tokens[0], 'name', new_name)
    object.__setattr__(expected_tokens[0], 'symbol', new_symbol)
    object.__setattr__(expected_tokens[0], 'protocol', new_protocol)
    object.__setattr__(expected_tokens[0], 'swapped_for', A_BAT)
    expected_result = [x.serialize_all_info() for x in expected_tokens]
    assert_token_entry_exists_in_result(result, expected_result)

    # test that editing an non existing address is handled properly
    non_existing_token = INITIAL_TOKENS[0].serialize_all_info()
    del non_existing_token['identifier']
    non_existing_address = make_ethereum_address()
    non_existing_token['address'] = non_existing_address
    response = requests.patch(
        api_url_for(
            rotkehlchen_api_server,
            'ethereumassetsresource',
        ),
        json={'token': non_existing_token},
    )
    expected_msg = (
        f'Tried to edit non existing ethereum token with '
        f'address {non_existing_address}',
    )
    assert_error_response(
        response=response,
        contained_in_msg=expected_msg,
        status_code=HTTPStatus.CONFLICT,
    )
Beispiel #14
0
def test_edit_exchange_credentials(rotkehlchen_api_server_with_exchanges):
    server = rotkehlchen_api_server_with_exchanges
    rotki = rotkehlchen_api_server_with_exchanges.rest_api.rotkehlchen

    # Test that valid api key/secret is edited properly
    new_key = 'new_key'
    new_secret = 'new_secret'
    for location in SUPPORTED_EXCHANGES:
        exchange = try_get_first_exchange(rotki.exchange_manager, location)
        # change both passphrase and name -- kucoin
        data = {
            'name': exchange.name,
            'location': str(location),
            'new_name': f'my_{exchange.name}',
            'api_key': new_key,
            'api_secret': new_secret,
        }
        with mock_validate_api_key_success(location):
            response = requests.patch(api_url_for(server, 'exchangesresource'),
                                      json=data)
            assert_simple_ok_response(response)
            assert exchange.api_key == new_key
            assert exchange.secret == new_secret.encode()
            if location == Location.ICONOMI:
                continue  # except for iconomi
            # all of the api keys end up in session headers. Check they are properly
            # updated there
            assert any(new_key in value
                       for _, value in exchange.session.headers.items())

    # Test that api key validation failure is handled correctly
    for location in SUPPORTED_EXCHANGES:
        exchange = try_get_first_exchange(rotki.exchange_manager, location)
        # change both passphrase and name -- kucoin
        data = {
            'name': exchange.name,
            'location': str(location),
            'new_name': f'my_{exchange.name}',
            'api_key': 'invalid',
            'api_secret': 'invalid',
        }
        with mock_validate_api_key_failure(location):
            response = requests.patch(api_url_for(server, 'exchangesresource'),
                                      json=data)
            assert_error_response(
                response=response,
                contained_in_msg='BOOM ERROR',
                status_code=HTTPStatus.CONFLICT,
            )
            # Test that the api key/secret DID NOT change
            assert exchange.api_key == new_key
            assert exchange.secret == new_secret.encode()
            if location == Location.ICONOMI:
                continue  # except for iconomi
            # all of the api keys end up in session headers. Check they are properly
            # updated there
            assert any(new_key in value
                       for _, value in exchange.session.headers.items())
Beispiel #15
0
def test_query_aave_history_non_premium(rotkehlchen_api_server, ethereum_accounts):  # pylint: disable=unused-argument  # noqa: E501
    response = requests.get(api_url_for(
        rotkehlchen_api_server,
        "aavehistoryresource",
    ))
    assert_error_response(
        response=response,
        contained_in_msg='Currently logged in user testuser does not have a premium subscription',
        status_code=HTTPStatus.CONFLICT,
    )
Beispiel #16
0
def test_query_vaults_details_non_premium(rotkehlchen_api_server):
    """Check querying the vaults details endpoint without premium does not work"""
    response = requests.get(api_url_for(
        rotkehlchen_api_server,
        "makerdaovaultdetailsresource",
    ))
    assert_error_response(
        response=response,
        contained_in_msg='Currently logged in user testuser does not have a premium subscription',
        status_code=HTTPStatus.CONFLICT,
    )
Beispiel #17
0
def test_edit_exchange_kraken_account_type(
        rotkehlchen_api_server_with_exchanges):
    server = rotkehlchen_api_server_with_exchanges
    rotki = rotkehlchen_api_server_with_exchanges.rest_api.rotkehlchen
    kraken = try_get_first_exchange(rotki.exchange_manager, Location.KRAKEN)
    assert kraken.account_type == DEFAULT_KRAKEN_ACCOUNT_TYPE
    assert kraken.call_limit == 15
    assert kraken.reduction_every_secs == 3

    data = {
        'name': 'mockkraken',
        'location': 'kraken',
        'kraken_account_type': 'intermediate'
    }
    response = requests.patch(api_url_for(server, 'exchangesresource'),
                              json=data)
    result = assert_proper_response_with_result(response)
    assert result is True
    kraken = try_get_first_exchange(rotki.exchange_manager, Location.KRAKEN)
    assert kraken.name == 'mockkraken'
    assert kraken.account_type == KrakenAccountType.INTERMEDIATE
    assert kraken.call_limit == 20
    assert kraken.reduction_every_secs == 2

    # at second edit, also change name
    data = {
        'name': 'mockkraken',
        'new_name': 'lolkraken',
        'location': 'kraken',
        'kraken_account_type': 'pro'
    }  # noqa: E501
    response = requests.patch(api_url_for(server, 'exchangesresource'),
                              json=data)
    result = assert_proper_response_with_result(response)
    assert result is True
    kraken = try_get_first_exchange(rotki.exchange_manager, Location.KRAKEN)
    assert kraken.name == 'lolkraken'
    assert kraken.account_type == KrakenAccountType.PRO
    assert kraken.call_limit == 20
    assert kraken.reduction_every_secs == 1

    # Make sure invalid type is caught
    data = {
        'name': 'lolkraken',
        'location': 'kraken',
        'kraken_account_type': 'pleb'
    }
    response = requests.patch(api_url_for(server, 'exchangesresource'),
                              json=data)
    assert_error_response(
        response=response,
        status_code=HTTPStatus.BAD_REQUEST,
        contained_in_msg='pleb is not a valid kraken account type',
    )
Beispiel #18
0
def test_get_balancer_module_not_activated(
        rotkehlchen_api_server,
        ethereum_accounts,  # pylint: disable=unused-argument
):
    response = requests.get(
        api_url_for(rotkehlchen_api_server, 'balancerbalancesresource'), )
    assert_error_response(
        response=response,
        contained_in_msg='balancer module is not activated',
        status_code=HTTPStatus.CONFLICT,
    )
Beispiel #19
0
def test_edit_ledger_actions(rotkehlchen_api_server):
    """Test that editing the ledger actions endpoint works as expected"""
    actions = _add_ledger_actions(rotkehlchen_api_server)

    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            'ledgeractionsresource',
        ), )
    result = assert_proper_response_with_result(response)
    result = [x['entry'] for x in result['entries']]
    assert result == actions

    new_action = actions[1]
    new_action['timestamp'] = 1337
    new_action['location'] = 'kraken'
    new_action['action_type'] = 'airdrop'
    new_action['amount'] = '10'
    new_action['asset'] = 'ETH'
    new_action['rate'] = '85'
    new_action['rate_asset'] = 'GBP'
    new_action['link'] = 'a link'
    new_action['notes'] = 'new notes'

    # Now get the actions and make sure that one is edited
    response = requests.patch(
        api_url_for(
            rotkehlchen_api_server,
            'ledgeractionsresource',
        ),
        json=new_action,
    )
    result = assert_proper_response_with_result(response)
    result = [x['entry'] for x in result['entries']]
    assert result == [actions[3], actions[2], actions[0], new_action]

    # Try to edit unknown identifier and see it fails
    new_action['identifier'] = 666
    new_action['action_type'] = 'loss'
    response = requests.patch(
        api_url_for(
            rotkehlchen_api_server,
            'ledgeractionsresource',
        ),
        json=new_action,
    )
    assert_error_response(
        response,
        contained_in_msg=
        (f'Tried to edit ledger action with identifier {new_action["identifier"]}'
         f' but it was not found in the DB', ),
        status_code=HTTPStatus.CONFLICT,
    )
Beispiel #20
0
def test_set_unknown_settings(rotkehlchen_api_server):
    """Test that setting an unknown setting """
    # Unknown setting
    data = {
        'invalid_setting': 5555,
    }
    response = requests.put(api_url_for(rotkehlchen_api_server, "settingsresource"), json=data)
    assert_error_response(
        response=response,
        contained_in_msg='todo',
        status_code=HTTPStatus.BAD_REQUEST,
    )
Beispiel #21
0
def test_update_no_user_loggedin(rotkehlchen_api_server):
    response = requests.post(
        api_url_for(
            rotkehlchen_api_server,
            'assetupdatesresource',
        ),
    )
    assert_error_response(
        response=response,
        contained_in_msg='No user is currently logged in',
        status_code=HTTPStatus.CONFLICT,
    )
Beispiel #22
0
def test_process_grants_non_premium(rotkehlchen_api_server):
    json_data = {
        'from_timestamp': 1599177600,  # 04/09/2020
        'to_timestamp': 1600387200,  # 18/09/2020
    }
    response = requests.put(api_url_for(
        rotkehlchen_api_server,
        'gitcoinreportresource',
    ), json=json_data)
    assert_error_response(
        response=response,
        contained_in_msg='does not have a premium subscription',
        status_code=HTTPStatus.CONFLICT,
    )
Beispiel #23
0
def test_set_unknown_settings(rotkehlchen_api_server):
    """Test that setting an unknown setting results in an error

    This is the only test for unknown arguments in marshmallow schemas after
    https://github.com/rotki/rotki/issues/532 was implemented"""
    # Unknown setting
    data = {
        'invalid_setting': 5555,
    }
    response = requests.put(api_url_for(rotkehlchen_api_server, "settingsresource"), json=data)
    assert_error_response(
        response=response,
        contained_in_msg="{'invalid_setting': ['Unknown field.'",
        status_code=HTTPStatus.BAD_REQUEST,
    )
def test_querying_fiat_exchange_rates(rotkehlchen_api_server):
    """Make sure that querying fiat exchange rates works also without logging in"""
    # Test with empty list of currencies
    data = {'currencies': []}
    response = requests.get(
        api_url_for(rotkehlchen_api_server, 'fiatexchangeratesresource'),
        json=data,
    )
    assert_error_response(
        response=response,
        contained_in_msg='Empty list of currencies provided',
        status_code=HTTPStatus.BAD_REQUEST,
    )

    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

    # Test with some currencies, both JSON body and query parameters
    data = {'currencies': ['EUR', 'USD', 'KRW']}
    response = requests.get(
        api_url_for(rotkehlchen_api_server, 'fiatexchangeratesresource'),
        json=data,
    )
    assert_okay(response)
    # The query parameters test serves as a test that a list of parametrs works with query args too
    response = requests.get(
        api_url_for(rotkehlchen_api_server, 'fiatexchangeratesresource') +
        '?currencies=' + ','.join(data['currencies']), )
    assert_okay(response)

    # Test with all currencies (give no input)
    response = requests.get(
        api_url_for(rotkehlchen_api_server, 'fiatexchangeratesresource'))
    assert_proper_response(response)
    json_data = response.json()
    assert json_data['message'] == ''
    result = json_data['result']
    assert len(result) == len(FIAT_CURRENCIES)
    for currency in FIAT_CURRENCIES:
        assert FVal(result[currency.identifier]) > 0
Beispiel #25
0
def test_query_trades_errors(rotkehlchen_api_server_with_exchanges):
    """Test that the trades endpoint handles invalid get requests properly"""
    # Test that invalid value for from_timestamp is handled
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server_with_exchanges,
            "tradesresource",
        ),
        json={'from_timestamp': 'fooo'},
    )
    assert_error_response(
        response=response,
        contained_in_msg=
        'Failed to deserialize a timestamp entry from string fooo',
        status_code=HTTPStatus.BAD_REQUEST,
    )
    # Test that invalid value for to_timestamp is handled
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server_with_exchanges,
            "tradesresource",
        ),
        json={'to_timestamp': [55.2]},
    )
    assert_error_response(
        response=response,
        contained_in_msg=
        'Failed to deserialize a timestamp entry. Unexpected type',
        status_code=HTTPStatus.BAD_REQUEST,
    )
    # Test that invalid type for location is handled
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server_with_exchanges,
            "tradesresource",
        ),
        json={'location': 3452},
    )
    assert_error_response(
        response=response,
        contained_in_msg='Failed to deserialize location symbol',
        status_code=HTTPStatus.BAD_REQUEST,
    )
    # Test that non-existing location is handled
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server_with_exchanges,
            "tradesresource",
        ),
        json={'location': 'foo'},
    )
    assert_error_response(
        response=response,
        contained_in_msg=
        'Failed to deserialize location symbol. Unknown symbol foo for location',
        status_code=HTTPStatus.BAD_REQUEST,
    )
Beispiel #26
0
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 = rotki.exchange_manager.get('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",
                name='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",
                name='kraken',
            ), )
    assert_proper_response(response=response)
    data = response.json()
    assert data['result'] == {}
    assert data['message'] == ""
Beispiel #27
0
def test_remove_ignored_actions(rotkehlchen_api_server):
    data = _populate_ignored_actions(rotkehlchen_api_server)

    # get all entries and make sure they are there
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            "ignoredactionsresource",
        ),
    )
    result = assert_proper_response_with_result(response)
    assert result == {entry[0]: entry[1] for entry in data}

    # remove a few entries of one type
    response = requests.delete(
        api_url_for(
            rotkehlchen_api_server,
            "ignoredactionsresource",
        ), json={'action_type': 'asset movement', 'action_ids': ['1', '7']},
    )
    result = assert_proper_response_with_result(response)
    assert result == {'asset movement': ['4', '5']}

    # remove all entries of one type
    response = requests.delete(
        api_url_for(
            rotkehlchen_api_server,
            "ignoredactionsresource",
        ), json={'action_type': 'ethereum transaction', 'action_ids': data[2][1]},
    )
    result = assert_proper_response_with_result(response)
    assert result == {}

    # try to remove non existing entries
    response = requests.delete(
        api_url_for(
            rotkehlchen_api_server,
            "ignoredactionsresource",
        ), json={'action_type': 'ledger action', 'action_ids': ['1', '5', '2']},
    )
    result = assert_error_response(
        response=response,
        status_code=HTTPStatus.CONFLICT,
        contained_in_msg='Tried to remove 1 ignored actions that do not exist',
    )

    # get all entries again and make sure deleted ones do not appear
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            "ignoredactionsresource",
        ),
    )
    result = assert_proper_response_with_result(response)
    assert result == {
        'asset movement': ['4', '5'],
        'ledger action': ['1', '2', '3'],
        'trade': ['1', '2', '3'],
    }
Beispiel #28
0
def test_user_creation_with_already_loggedin_user(rotkehlchen_api_server, username):
    """Test that creating a user while another one is logged in fails"""
    # Missing username
    data = {
        'name': username,
        'password': '******',
    }
    response = requests.put(api_url_for(rotkehlchen_api_server, "usersresource"), json=data)
    msg = (
        f'Can not create a new user because user {username} is already logged in. '
        f'Log out of that user first'
    )
    assert_error_response(
        response=response,
        contained_in_msg=msg,
        status_code=HTTPStatus.CONFLICT,
    )
Beispiel #29
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 = {
        'location': 'kraken',
        'name': 'my_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.CONFLICT,
    )

    # Now try to register the exchange again
    data = {
        'location': 'kraken',
        'name': 'my_kraken',
        'api_key': 'ddddd',
        'api_secret': 'fffffff'
    }
    with mock_validate_api_key_success(Location.KRAKEN):
        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'))
    result = assert_proper_response_with_result(response)
    assert result == [{
        'location': 'kraken',
        'name': 'my_kraken',
        'kraken_account_type': 'starter'
    }]  # noqa: E501
def test_add_get_ignored_actions(rotkehlchen_api_server):
    data = _populate_ignored_actions(rotkehlchen_api_server)

    # get only one type via json args
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            "ignoredactionsresource",
        ),
        json={'action_type': data[1][0]},
    )
    result = assert_proper_response_with_result(response)
    assert result == {data[1][0]: data[1][1]}

    # get only one type via query args
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            "ignoredactionsresource",
        ) + f'?action_type={data[2][0]}', )
    result = assert_proper_response_with_result(response)
    assert result == {data[2][0]: data[2][1]}

    # get all entries
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            "ignoredactionsresource",
        ), )
    result = assert_proper_response_with_result(response)
    assert result == {entry[0]: entry[1] for entry in data}

    # try to add at least one already existing id
    response = requests.put(
        api_url_for(
            rotkehlchen_api_server,
            "ignoredactionsresource",
        ),
        json={
            'action_type': 'trade',
            'action_ids': ['1', '9', '11']
        },
    )
    result = assert_error_response(
        response=response,
        status_code=HTTPStatus.CONFLICT,
        contained_in_msg=
        'One of the given action ids already exists in the dataase',
    )

    # get all entries again and make sure nothing new slipped in
    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            "ignoredactionsresource",
        ), )
    result = assert_proper_response_with_result(response)
    assert result == {entry[0]: entry[1] for entry in data}