2018-01-28 01:33:04 +00:00
|
|
|
# pragma pylint: disable=missing-docstring, too-many-arguments, too-many-ancestors,
|
|
|
|
# pragma pylint: disable=protected-access, C0103
|
2017-12-25 07:51:41 +00:00
|
|
|
|
2021-05-22 15:15:35 +00:00
|
|
|
import datetime
|
2017-12-25 07:51:41 +00:00
|
|
|
from unittest.mock import MagicMock
|
|
|
|
|
2018-01-10 07:51:36 +00:00
|
|
|
import pytest
|
2018-05-21 18:03:25 +00:00
|
|
|
from requests.exceptions import RequestException
|
|
|
|
|
2021-04-10 11:36:16 +00:00
|
|
|
from freqtrade.rpc.fiat_convert import CryptoToFiatConverter
|
2020-03-07 10:52:26 +00:00
|
|
|
from tests.conftest import log_has, log_has_re
|
2017-12-25 07:51:41 +00:00
|
|
|
|
|
|
|
|
2018-06-16 11:42:25 +00:00
|
|
|
def test_fiat_convert_is_supported(mocker):
|
2017-12-25 07:51:41 +00:00
|
|
|
fiat_convert = CryptoToFiatConverter()
|
|
|
|
assert fiat_convert._is_supported_fiat(fiat='USD') is True
|
|
|
|
assert fiat_convert._is_supported_fiat(fiat='usd') is True
|
|
|
|
assert fiat_convert._is_supported_fiat(fiat='abc') is False
|
|
|
|
assert fiat_convert._is_supported_fiat(fiat='ABC') is False
|
|
|
|
|
|
|
|
|
|
|
|
def test_fiat_convert_find_price(mocker):
|
|
|
|
fiat_convert = CryptoToFiatConverter()
|
|
|
|
|
2021-08-17 18:41:08 +00:00
|
|
|
fiat_convert._coinlistings = {}
|
2021-05-22 10:04:24 +00:00
|
|
|
fiat_convert._backoff = 0
|
|
|
|
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._load_cryptomap',
|
|
|
|
return_value=None)
|
|
|
|
assert fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='EUR') == 0.0
|
|
|
|
|
2017-12-25 07:51:41 +00:00
|
|
|
with pytest.raises(ValueError, match=r'The fiat ABC is not supported.'):
|
|
|
|
fiat_convert._find_price(crypto_symbol='BTC', fiat_symbol='ABC')
|
|
|
|
|
2018-04-21 21:20:12 +00:00
|
|
|
assert fiat_convert.get_price(crypto_symbol='XRP', fiat_symbol='USD') == 0.0
|
2018-03-17 23:42:24 +00:00
|
|
|
|
2018-12-11 19:26:53 +00:00
|
|
|
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._find_price',
|
|
|
|
return_value=12345.0)
|
2017-12-25 07:51:41 +00:00
|
|
|
assert fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='USD') == 12345.0
|
|
|
|
assert fiat_convert.get_price(crypto_symbol='btc', fiat_symbol='usd') == 12345.0
|
2018-01-07 04:07:40 +00:00
|
|
|
|
2018-12-11 19:26:53 +00:00
|
|
|
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._find_price',
|
|
|
|
return_value=13000.2)
|
2017-12-25 07:51:41 +00:00
|
|
|
assert fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='EUR') == 13000.2
|
|
|
|
|
|
|
|
|
2018-06-02 22:29:29 +00:00
|
|
|
def test_fiat_convert_unsupported_crypto(mocker, caplog):
|
2021-08-17 18:41:08 +00:00
|
|
|
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._coinlistings', return_value=[])
|
2018-06-02 22:29:29 +00:00
|
|
|
fiat_convert = CryptoToFiatConverter()
|
|
|
|
assert fiat_convert._find_price(crypto_symbol='CRYPTO_123', fiat_symbol='EUR') == 0.0
|
2019-08-11 18:17:22 +00:00
|
|
|
assert log_has('unsupported crypto-symbol CRYPTO_123 - returning 0.0', caplog)
|
2018-06-02 22:29:29 +00:00
|
|
|
|
|
|
|
|
2017-12-25 07:51:41 +00:00
|
|
|
def test_fiat_convert_get_price(mocker):
|
2021-04-10 11:36:16 +00:00
|
|
|
find_price = mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._find_price',
|
|
|
|
return_value=28000.0)
|
2017-12-25 07:51:41 +00:00
|
|
|
|
|
|
|
fiat_convert = CryptoToFiatConverter()
|
|
|
|
|
2020-03-07 10:52:26 +00:00
|
|
|
with pytest.raises(ValueError, match=r'The fiat us dollar is not supported.'):
|
|
|
|
fiat_convert.get_price(crypto_symbol='btc', fiat_symbol='US Dollar')
|
2017-12-25 07:51:41 +00:00
|
|
|
|
|
|
|
# Check the value return by the method
|
2021-04-10 11:36:16 +00:00
|
|
|
pair_len = len(fiat_convert._pair_price)
|
2018-01-28 01:33:04 +00:00
|
|
|
assert pair_len == 0
|
2020-03-07 10:52:26 +00:00
|
|
|
assert fiat_convert.get_price(crypto_symbol='btc', fiat_symbol='usd') == 28000.0
|
2021-04-10 11:36:16 +00:00
|
|
|
assert fiat_convert._pair_price['btc/usd'] == 28000.0
|
|
|
|
assert len(fiat_convert._pair_price) == 1
|
|
|
|
assert find_price.call_count == 1
|
2017-12-25 07:51:41 +00:00
|
|
|
|
|
|
|
# Verify the cached is used
|
2021-04-10 11:36:16 +00:00
|
|
|
fiat_convert._pair_price['btc/usd'] = 9867.543
|
2020-03-07 10:52:26 +00:00
|
|
|
assert fiat_convert.get_price(crypto_symbol='btc', fiat_symbol='usd') == 9867.543
|
2021-04-10 11:36:16 +00:00
|
|
|
assert find_price.call_count == 1
|
2018-01-07 04:07:40 +00:00
|
|
|
|
|
|
|
|
2018-06-02 03:58:07 +00:00
|
|
|
def test_fiat_convert_same_currencies(mocker):
|
|
|
|
fiat_convert = CryptoToFiatConverter()
|
|
|
|
|
|
|
|
assert fiat_convert.get_price(crypto_symbol='USD', fiat_symbol='USD') == 1.0
|
|
|
|
|
|
|
|
|
2018-06-02 20:26:24 +00:00
|
|
|
def test_fiat_convert_two_FIAT(mocker):
|
|
|
|
fiat_convert = CryptoToFiatConverter()
|
|
|
|
|
|
|
|
assert fiat_convert.get_price(crypto_symbol='USD', fiat_symbol='EUR') == 0.0
|
|
|
|
|
|
|
|
|
2018-05-13 18:46:02 +00:00
|
|
|
def test_loadcryptomap(mocker):
|
|
|
|
|
|
|
|
fiat_convert = CryptoToFiatConverter()
|
2021-08-17 18:41:08 +00:00
|
|
|
assert len(fiat_convert._coinlistings) == 2
|
2018-05-13 18:46:02 +00:00
|
|
|
|
2024-04-25 08:28:25 +00:00
|
|
|
assert fiat_convert._get_gecko_id("btc") == "bitcoin"
|
2018-05-13 18:46:02 +00:00
|
|
|
|
|
|
|
|
2018-05-21 18:03:25 +00:00
|
|
|
def test_fiat_init_network_exception(mocker):
|
|
|
|
# Because CryptoToFiatConverter is a Singleton we reset the listings
|
|
|
|
listmock = MagicMock(side_effect=RequestException)
|
|
|
|
mocker.patch.multiple(
|
2020-03-07 10:52:26 +00:00
|
|
|
'freqtrade.rpc.fiat_convert.CoinGeckoAPI',
|
|
|
|
get_coins_list=listmock,
|
2018-05-21 18:03:25 +00:00
|
|
|
)
|
|
|
|
# with pytest.raises(RequestEsxception):
|
|
|
|
fiat_convert = CryptoToFiatConverter()
|
2021-08-17 18:41:08 +00:00
|
|
|
fiat_convert._coinlistings = {}
|
2018-05-21 18:03:25 +00:00
|
|
|
fiat_convert._load_cryptomap()
|
|
|
|
|
2021-08-17 18:41:08 +00:00
|
|
|
assert len(fiat_convert._coinlistings) == 0
|
2018-05-21 18:03:25 +00:00
|
|
|
|
|
|
|
|
2018-06-16 11:42:25 +00:00
|
|
|
def test_fiat_convert_without_network(mocker):
|
2024-04-25 08:27:16 +00:00
|
|
|
# Because CryptoToFiatConverter is a Singleton we reset the value of _coingecko
|
2018-01-07 04:07:40 +00:00
|
|
|
|
|
|
|
fiat_convert = CryptoToFiatConverter()
|
2018-04-07 18:06:53 +00:00
|
|
|
|
2024-04-25 08:27:16 +00:00
|
|
|
cmc_temp = CryptoToFiatConverter._coingecko
|
|
|
|
CryptoToFiatConverter._coingecko = None
|
2018-04-07 18:06:53 +00:00
|
|
|
|
2024-04-25 08:27:16 +00:00
|
|
|
assert fiat_convert._coingecko is None
|
2020-03-07 10:52:26 +00:00
|
|
|
assert fiat_convert._find_price(crypto_symbol='btc', fiat_symbol='usd') == 0.0
|
2024-04-25 08:27:16 +00:00
|
|
|
CryptoToFiatConverter._coingecko = cmc_temp
|
2018-06-02 22:12:02 +00:00
|
|
|
|
|
|
|
|
2021-05-22 10:04:24 +00:00
|
|
|
def test_fiat_too_many_requests_response(mocker, caplog):
|
|
|
|
# Because CryptoToFiatConverter is a Singleton we reset the listings
|
|
|
|
req_exception = "429 Too Many Requests"
|
|
|
|
listmock = MagicMock(return_value="{}", side_effect=RequestException(req_exception))
|
|
|
|
mocker.patch.multiple(
|
|
|
|
'freqtrade.rpc.fiat_convert.CoinGeckoAPI',
|
|
|
|
get_coins_list=listmock,
|
|
|
|
)
|
|
|
|
# with pytest.raises(RequestEsxception):
|
|
|
|
fiat_convert = CryptoToFiatConverter()
|
2021-08-17 18:41:08 +00:00
|
|
|
fiat_convert._coinlistings = {}
|
2021-05-22 10:04:24 +00:00
|
|
|
fiat_convert._load_cryptomap()
|
|
|
|
|
2021-08-17 18:41:08 +00:00
|
|
|
assert len(fiat_convert._coinlistings) == 0
|
2021-05-22 10:04:24 +00:00
|
|
|
assert fiat_convert._backoff > datetime.datetime.now().timestamp()
|
2021-05-22 11:43:48 +00:00
|
|
|
assert log_has(
|
2022-04-01 18:57:09 +00:00
|
|
|
'Too many requests for CoinGecko API, backing off and trying again later.',
|
2021-08-06 22:19:36 +00:00
|
|
|
caplog
|
|
|
|
)
|
2021-05-22 11:43:48 +00:00
|
|
|
|
2021-05-22 10:04:24 +00:00
|
|
|
|
2021-08-17 18:41:08 +00:00
|
|
|
def test_fiat_multiple_coins(mocker, caplog):
|
|
|
|
fiat_convert = CryptoToFiatConverter()
|
|
|
|
fiat_convert._coinlistings = [
|
|
|
|
{'id': 'helium', 'symbol': 'hnt', 'name': 'Helium'},
|
|
|
|
{'id': 'hymnode', 'symbol': 'hnt', 'name': 'Hymnode'},
|
|
|
|
{'id': 'bitcoin', 'symbol': 'btc', 'name': 'Bitcoin'},
|
2022-01-28 10:17:16 +00:00
|
|
|
{'id': 'ethereum', 'symbol': 'eth', 'name': 'Ethereum'},
|
|
|
|
{'id': 'ethereum-wormhole', 'symbol': 'eth', 'name': 'Ethereum Wormhole'},
|
2021-08-17 18:41:08 +00:00
|
|
|
]
|
|
|
|
|
2024-04-25 08:28:25 +00:00
|
|
|
assert fiat_convert._get_gecko_id('btc') == 'bitcoin'
|
|
|
|
assert fiat_convert._get_gecko_id('hnt') is None
|
|
|
|
assert fiat_convert._get_gecko_id('eth') == 'ethereum'
|
2021-08-17 18:41:08 +00:00
|
|
|
|
2022-04-01 18:57:09 +00:00
|
|
|
assert log_has('Found multiple mappings in CoinGecko for hnt.', caplog)
|
2021-08-17 18:41:08 +00:00
|
|
|
|
|
|
|
|
2018-07-21 17:50:38 +00:00
|
|
|
def test_fiat_invalid_response(mocker, caplog):
|
|
|
|
# Because CryptoToFiatConverter is a Singleton we reset the listings
|
2021-08-17 18:41:08 +00:00
|
|
|
listmock = MagicMock(return_value=None)
|
2018-07-21 17:50:38 +00:00
|
|
|
mocker.patch.multiple(
|
2020-03-07 10:52:26 +00:00
|
|
|
'freqtrade.rpc.fiat_convert.CoinGeckoAPI',
|
|
|
|
get_coins_list=listmock,
|
2018-07-21 17:50:38 +00:00
|
|
|
)
|
|
|
|
# with pytest.raises(RequestEsxception):
|
|
|
|
fiat_convert = CryptoToFiatConverter()
|
2021-08-17 18:41:08 +00:00
|
|
|
fiat_convert._coinlistings = []
|
2018-07-21 17:50:38 +00:00
|
|
|
fiat_convert._load_cryptomap()
|
|
|
|
|
2021-08-17 18:41:08 +00:00
|
|
|
assert len(fiat_convert._coinlistings) == 0
|
2020-03-07 10:52:26 +00:00
|
|
|
assert log_has_re('Could not load FIAT Cryptocurrency map for the following problem: .*',
|
|
|
|
caplog)
|
2018-07-21 17:50:38 +00:00
|
|
|
|
2021-05-22 11:43:48 +00:00
|
|
|
|
2018-06-02 22:12:02 +00:00
|
|
|
def test_convert_amount(mocker):
|
2018-12-11 19:26:53 +00:00
|
|
|
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter.get_price', return_value=12345.0)
|
2018-06-02 22:12:02 +00:00
|
|
|
|
|
|
|
fiat_convert = CryptoToFiatConverter()
|
|
|
|
result = fiat_convert.convert_amount(
|
|
|
|
crypto_amount=1.23,
|
|
|
|
crypto_symbol="BTC",
|
|
|
|
fiat_symbol="USD"
|
|
|
|
)
|
|
|
|
assert result == 15184.35
|
|
|
|
|
|
|
|
result = fiat_convert.convert_amount(
|
|
|
|
crypto_amount=1.23,
|
|
|
|
crypto_symbol="BTC",
|
|
|
|
fiat_symbol="BTC"
|
|
|
|
)
|
|
|
|
assert result == 1.23
|
2019-09-09 17:59:41 +00:00
|
|
|
|
|
|
|
result = fiat_convert.convert_amount(
|
|
|
|
crypto_amount="1.23",
|
|
|
|
crypto_symbol="BTC",
|
|
|
|
fiat_symbol="BTC"
|
|
|
|
)
|
|
|
|
assert result == 1.23
|