diff --git a/README.md b/README.md index fe8df19..eb8c551 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,14 @@ pip3 install cryptocompare import cryptocompare ``` +## API Key + +If you have an API key, you can either set it as environment variable `CRYPTOCOMPARE_API_KEY` or set it manually with: + +``` +cryptocompare.cryptocompare._set_api_key_parameter(KEY_HERE) +``` + ### Coin List ```python @@ -135,7 +143,7 @@ pairs = cryptocompare.get_pairs(exchange='Kraken') ## Developing -Install the dev dependencies and run the tests: +Tests run assuming you have an API key, otherwise they will error due to rate limiting. Install the dev dependencies and run the tests: ```sh pip3 install -r requirements.txt python3 -m pytest diff --git a/cryptocompare/cryptocompare.py b/cryptocompare/cryptocompare.py index 6c79587..7e15e39 100644 --- a/cryptocompare/cryptocompare.py +++ b/cryptocompare/cryptocompare.py @@ -5,11 +5,13 @@ import time import datetime import typing +import os from typing import Union, Optional, List, Dict Timestamp = Union[datetime.datetime, datetime.date, int, float] # API -_URL_COIN_LIST = 'https://www.cryptocompare.com/api/data/coinlist/' +_API_KEY_PARAMETER = "" +_URL_COIN_LIST = 'https://www.cryptocompare.com/api/data/coinlist?' _URL_PRICE = 'https://min-api.cryptocompare.com/data/pricemulti?fsyms={}&tsyms={}' _URL_PRICE_MULTI = 'https://min-api.cryptocompare.com/data/pricemulti?fsyms={}&tsyms={}' _URL_PRICE_MULTI_FULL = 'https://min-api.cryptocompare.com/data/pricemultifull?fsyms={}&tsyms={}' @@ -18,7 +20,7 @@ _URL_HIST_PRICE_HOUR = 'https://min-api.cryptocompare.com/data/histohour?fsym={}&tsym={}&limit={}&e={}&toTs={}' _URL_HIST_PRICE_MINUTE = 'https://min-api.cryptocompare.com/data/histominute?fsym={}&tsym={}&limit={}&e={}&toTs={}' _URL_AVG = 'https://min-api.cryptocompare.com/data/generateAvg?fsym={}&tsym={}&e={}' -_URL_EXCHANGES = 'https://www.cryptocompare.com/api/data/exchanges' +_URL_EXCHANGES = 'https://www.cryptocompare.com/api/data/exchanges?' _URL_PAIRS = 'https://min-api.cryptocompare.com/data/pair/mapping/exchange?e={}' # DEFAULTS @@ -27,16 +29,18 @@ ############################################################################### -def _query_cryptocompare(url: str, errorCheck: bool = True) -> Optional[Dict]: +def _query_cryptocompare(url: str, errorCheck: bool = True, api_key: str = None) -> Optional[Dict]: """ Query the url and return the result or None on failure. :param url: the url :param errorCheck: run extra error checks (default: True) :returns: respones, or nothing if errorCheck=True + :api_key: optional, if you want to add an API Key """ + api_key_parameter = _set_api_key_parameter(api_key) try: - response = requests.get(url).json() + response = requests.get(url + api_key_parameter).json() except Exception as e: print('Error getting coin information. %s' % str(e)) return None @@ -72,6 +76,14 @@ def _format_timestamp(timestamp: Timestamp) -> int: return int(timestamp) +def _set_api_key_parameter(api_key: str = None) -> str: + if api_key is None: + api_key = os.getenv('CRYPTOCOMPARE_API_KEY') + if api_key is not None: + _API_KEY = "&api_key={}".format(api_key) + return _API_KEY + return "" + ############################################################################### diff --git a/tests/test_cryptocompare.py b/tests/test_cryptocompare.py index 9ec721b..138743e 100644 --- a/tests/test_cryptocompare.py +++ b/tests/test_cryptocompare.py @@ -3,96 +3,119 @@ import unittest import cryptocompare import datetime +import os class TestCryptoCompare(unittest.TestCase): - def assertCoinAndCurrInPrice(self, coin, curr, price): - if isinstance(coin, list): - for co in coin: - self.assertCoinAndCurrInPrice(co, curr, price) - return - else: - self.assertIn(coin, price) - - if isinstance(curr, list): - for cu in curr: - self.assertIn(cu, price[coin]) - else: - self.assertIn(curr, price[coin]) - - def test_coin_list(self): - lst = cryptocompare.get_coin_list() - self.assertTrue('BTC' in lst.keys()) - lst = cryptocompare.get_coin_list(True) - self.assertTrue('BTC' in lst) - - def test_get_price(self): - coin = 'BTC' - price = cryptocompare.get_price(coin) - self.assertCoinAndCurrInPrice(coin, 'EUR', price) - price = cryptocompare.get_price(coin, curr='USD') - self.assertCoinAndCurrInPrice(coin, 'USD', price) - currencies = ['EUR', 'USD', 'GBP'] - price = cryptocompare.get_price(coin, curr=currencies) - self.assertCoinAndCurrInPrice(coin, currencies, price) - coins = ['BTC', 'XMR'] - price = cryptocompare.get_price(coins, curr=currencies) - self.assertCoinAndCurrInPrice(coins, currencies, price) - - def test_get_price_full(self): - price = cryptocompare.get_price('ETH', full=True) - self.assertIn('RAW', price) - self.assertIn('ETH', price['RAW']) - self.assertIn('EUR', price['RAW']['ETH']) - self.assertIn('PRICE', price['RAW']['ETH']['EUR']) - - def test_get_historical_price(self): - coin = 'XMR' - curr = 'EUR' - price = cryptocompare.get_historical_price( - 'XMR', timestamp=datetime.date(2017, 6, 6)) - self.assertCoinAndCurrInPrice(coin, curr, price) - price2 = cryptocompare.get_historical_price( - 'XMR', 'EUR', datetime.datetime(2017, 6, 6)) - self.assertCoinAndCurrInPrice(coin, curr, price2) - self.assertEqual(price, price2) - - def test_price_day(self): - coin = 'BTC' - curr = 'USD' - price = cryptocompare.get_historical_price_day(coin, curr=curr, limit=3, exchange='CCCAGG', toTs=datetime.datetime(2019,6,6)) - for frame in price: - self.assertIn('time', frame) - - def test_price_hour(self): - coin = 'BTC' - curr = 'USD' - price = cryptocompare.get_historical_price_hour(coin, curr=curr, limit=3, exchange='CCCAGG', toTs=datetime.datetime(2019,6,6,12)) - for frame in price: - self.assertIn('time', frame) - - def test_price_minute(self): - coin = 'BTC' - curr = 'USD' - price = cryptocompare.get_historical_price_minute(coin, curr=curr, limit=3, exchange='CCCAGG', toTs=datetime.datetime.now()) - for frame in price: - self.assertIn('time', frame) - - def test_get_avg(self): - coin = 'BTC' - curr = 'USD' - avg = cryptocompare.get_avg(coin, curr, exchange='Kraken') - self.assertEqual(avg['LASTMARKET'], 'Kraken') - self.assertEqual(avg['FROMSYMBOL'], coin) - self.assertEqual(avg['TOSYMBOL'], curr) - - def test_get_exchanges(self): - exchanges = cryptocompare.get_exchanges() - self.assertIn('Kraken', exchanges) - - def test_get_pairs(self): - pairs = cryptocompare.get_pairs(exchange='Kraken') - self.assertEqual('Kraken', pairs[0]['exchange']) + def assertCoinAndCurrInPrice(self, coin, curr, price): + if isinstance(coin, list): + for co in coin: + self.assertCoinAndCurrInPrice(co, curr, price) + return + else: + self.assertIn(coin, price) + + if isinstance(curr, list): + for cu in curr: + self.assertIn(cu, price[coin]) + else: + self.assertIn(curr, price[coin]) + + def test_coin_list(self): + lst = cryptocompare.get_coin_list() + self.assertTrue('BTC' in lst.keys()) + lst = cryptocompare.get_coin_list(True) + self.assertTrue('BTC' in lst) + + def test_get_price(self): + coin = 'BTC' + price = cryptocompare.get_price(coin) + self.assertCoinAndCurrInPrice(coin, 'EUR', price) + price = cryptocompare.get_price(coin, curr='USD') + self.assertCoinAndCurrInPrice(coin, 'USD', price) + currencies = ['EUR', 'USD', 'GBP'] + price = cryptocompare.get_price(coin, curr=currencies) + self.assertCoinAndCurrInPrice(coin, currencies, price) + coins = ['BTC', 'XMR'] + price = cryptocompare.get_price(coins, curr=currencies) + self.assertCoinAndCurrInPrice(coins, currencies, price) + + def test_get_price_full(self): + price = cryptocompare.get_price('ETH', full=True) + self.assertIn('RAW', price) + self.assertIn('ETH', price['RAW']) + self.assertIn('EUR', price['RAW']['ETH']) + self.assertIn('PRICE', price['RAW']['ETH']['EUR']) + + def test_get_historical_price(self): + coin = 'XMR' + curr = 'EUR' + price = cryptocompare.get_historical_price( + 'XMR', timestamp=datetime.date(2017, 6, 6)) + self.assertCoinAndCurrInPrice(coin, curr, price) + price2 = cryptocompare.get_historical_price( + 'XMR', 'EUR', datetime.datetime(2017, 6, 6)) + self.assertCoinAndCurrInPrice(coin, curr, price2) + self.assertEqual(price, price2) + + def test_price_day(self): + coin = 'BTC' + curr = 'USD' + price = cryptocompare.get_historical_price_day( + coin, curr=curr, limit=3, exchange='CCCAGG', toTs=datetime.datetime(2019, 6, 6)) + for frame in price: + self.assertIn('time', frame) + + def test_price_hour(self): + coin = 'BTC' + curr = 'USD' + price = cryptocompare.get_historical_price_hour( + coin, curr=curr, limit=3, exchange='CCCAGG', toTs=datetime.datetime(2019, 6, 6, 12)) + for frame in price: + self.assertIn('time', frame) + + def test_price_minute(self): + coin = 'BTC' + curr = 'USD' + price = cryptocompare.get_historical_price_minute( + coin, curr=curr, limit=3, exchange='CCCAGG', toTs=datetime.datetime.now()) + for frame in price: + self.assertIn('time', frame) + + def test_get_avg(self): + coin = 'BTC' + curr = 'USD' + avg = cryptocompare.get_avg(coin, curr, exchange='Kraken') + self.assertEqual(avg['LASTMARKET'], 'Kraken') + self.assertEqual(avg['FROMSYMBOL'], coin) + self.assertEqual(avg['TOSYMBOL'], curr) + + def test_get_exchanges(self): + exchanges = cryptocompare.get_exchanges() + self.assertIn('Kraken', exchanges) + + def test_get_pairs(self): + pairs = cryptocompare.get_pairs(exchange='Kraken') + self.assertEqual('Kraken', pairs[0]['exchange']) + + def test_sets_api_key_using_environment_variable(self): + os.environ["CRYPTOCOMPARE_API_KEY"] = "Key" + api_key_parameter = cryptocompare.cryptocompare._set_api_key_parameter( + None) + assert api_key_parameter == "&api_key=Key" + + def test_sets_api_key_with_no_env_var_and_none_passed(self): + if os.getenv("CRYPTOCOMPARE_API_KEY"): + del os.environ['CRYPTOCOMPARE_API_KEY'] + api_key_parameter = cryptocompare.cryptocompare._set_api_key_parameter( + None) + assert api_key_parameter == "" + + def test_sets_api_key_passed_in_works(self): + api_key_parameter = cryptocompare.cryptocompare._set_api_key_parameter( + "keytest") + assert api_key_parameter == "&api_key=keytest" + if __name__ == "__main__": - unittest.main() + unittest.main()