From 0b07456ea51bbd4d431dd670b04895f23a902292 Mon Sep 17 00:00:00 2001 From: Christoforou Manolis Date: Thu, 23 May 2019 13:18:51 +0300 Subject: [PATCH 01/11] fix get_coin_market_chart_by_id test --- tests/test_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index ba4cac5..a5dd13b 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -168,7 +168,7 @@ def test_failed_get_coin_market_chart_by_id(self): # Act Assert with pytest.raises(HTTPError) as HE: - CoinGeckoAPI().get_coin_market_chart_by_id('bitcoin', 'usd', 0) + CoinGeckoAPI().get_coin_market_chart_by_id('bitcoin', 'usd', 1) @responses.activate @@ -180,7 +180,7 @@ def test_get_coin_market_chart_by_id(self): json = json_response, status = 200) # Act - response = CoinGeckoAPI().get_coin_market_chart_by_id('bitcoin', 'usd', 0) + response = CoinGeckoAPI().get_coin_market_chart_by_id('bitcoin', 'usd', 1) ## Assert assert response == json_response From 9b1a998da5ca8f6037a2f58642f71f49ce4edec6 Mon Sep 17 00:00:00 2001 From: Christoforou Manolis Date: Thu, 23 May 2019 22:22:30 +0300 Subject: [PATCH 02/11] convert every list arg to comma-separated string --- README.md | 6 ++++++ pycoingecko/api.py | 31 +++++++++++++++++++++++++------ pycoingecko/utils.py | 13 +++++++++++++ 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a2e9353..ae3d239 100644 --- a/README.md +++ b/README.md @@ -31,14 +31,20 @@ Usage examples: >>> cg.get_price(ids='bitcoin', vs_currencies='usd') {'bitcoin': {'usd': 3462.04}} +>>> cg.get_price(ids='bitcoin,litecoin,ethereum', vs_currencies='usd') +# OR >>> cg.get_price(ids=['bitcoin', 'litecoin', 'ethereum'], vs_currencies='usd') {'bitcoin': {'usd': 3461.27}, 'ethereum': {'usd': 106.92}, 'litecoin': {'usd': 32.72}} +>>> cg.get_price(ids='bitcoin,litecoin,ethereum', vs_currencies='usd,eur') +# OR >>> cg.get_price(ids=['bitcoin', 'litecoin', 'ethereum'], vs_currencies=['usd', 'eur']) {'bitcoin': {'usd': 3459.39, 'eur': 3019.33}, 'ethereum': {'usd': 106.91, 'eur': 93.31}, 'litecoin': {'usd': 32.72, 'eur': 28.56}} # optional parameteres can be passed as defined in the API doc (https://www.coingecko.com/api/docs/v3) >>> cg.get_price(ids='bitcoin', vs_currencies='usd', include_market_cap='true', include_24hr_vol='true', include_24hr_change='true', include_last_updated_at='true') +# OR +>>> cg.get_price(ids='bitcoin', vs_currencies='usd', include_market_cap='true', include_24hr_vol='true', include_24hr_change='true', include_last_updated_at='true') {'bitcoin': {'usd': 3458.74, 'usd_market_cap': 60574330199.29028, 'usd_24h_vol': 4182664683.6247883, 'usd_24h_change': 1.2295378479069035, 'last_updated_at': 1549071865}} ``` diff --git a/pycoingecko/api.py b/pycoingecko/api.py index dfe642f..c9dec73 100644 --- a/pycoingecko/api.py +++ b/pycoingecko/api.py @@ -4,8 +4,7 @@ from requests.adapters import HTTPAdapter from requests.packages.urllib3.util.retry import Retry -from .utils import get_comma_separated_values - +from .utils import list_args_to_comma_separated class CoinGeckoAPI: @@ -49,22 +48,29 @@ def ping(self): #---------- SIMPLE ----------# + @list_args_to_comma_separated def get_price(self, ids, vs_currencies, **kwargs): """Get the current price of any cryptocurrencies in any other supported currencies that you need""" - kwargs['ids'] = get_comma_separated_values(ids) - kwargs['vs_currencies'] = get_comma_separated_values(vs_currencies) + ids=ids.replace(' ','') + kwargs['ids'] = ids + vs_currencies=vs_currencies.replace(' ','') + kwargs['vs_currencies'] = vs_currencies api_url = '{0}simple/price'.format(self.api_base_url) api_url = self.__api_url_params(api_url, kwargs) return self.__request(api_url) + + @list_args_to_comma_separated def get_token_price(self, id, contract_addresses, vs_currencies, **kwargs): """Get the current price of any tokens on this coin (ETH only at this stage as per api docs) in any other supported currencies that you need""" - kwargs['contract_addresses'] = get_comma_separated_values(contract_addresses) - kwargs['vs_currencies'] = get_comma_separated_values(vs_currencies) + contract_addresses=contract_addresses.replace(' ','') + kwargs['contract_addresses'] = contract_addresses + vs_currencies=vs_currencies.replace(' ','') + kwargs['vs_currencies'] = vs_currencies api_url = '{0}simple/token_price/{1}'.format(self.api_base_url, id) api_url = self.__api_url_params(api_url, kwargs) @@ -79,6 +85,7 @@ def get_supported_vs_currencies(self): #---------- COINS ----------# + @list_args_to_comma_separated def get_coins(self, **kwargs): """List all coins with data (name, price, market, developer, community, etc)""" @@ -97,6 +104,7 @@ def get_coins_list(self): return self.__request(api_url) + @list_args_to_comma_separated def get_coins_markets(self, vs_currency, **kwargs): """List all supported coins price, market cap, volume, and market related data (no pagination required)""" @@ -108,6 +116,7 @@ def get_coins_markets(self, vs_currency, **kwargs): return self.__request(api_url) + @list_args_to_comma_separated def get_coin_by_id(self, id, **kwargs): """Get current data (name, price, market, ... including exchange tickers) for a coin""" @@ -117,6 +126,7 @@ def get_coin_by_id(self, id, **kwargs): return self.__request(api_url) + @list_args_to_comma_separated def get_coin_ticker_by_id(self, id, **kwargs): """Get coin tickers (paginated to 100 items)""" @@ -126,6 +136,7 @@ def get_coin_ticker_by_id(self, id, **kwargs): return self.__request(api_url) + @list_args_to_comma_separated def get_coin_history_by_id(self, id, date, **kwargs): """Get historical data (name, price, market, stats) at a given date for a coin""" @@ -137,6 +148,7 @@ def get_coin_history_by_id(self, id, date, **kwargs): return self.__request(api_url) + @list_args_to_comma_separated def get_coin_market_chart_by_id(self, id, vs_currency, days): """Get historical market data include price, market cap, and 24h volume (granularity auto)""" @@ -145,6 +157,7 @@ def get_coin_market_chart_by_id(self, id, vs_currency, days): return self.__request(api_url) + @list_args_to_comma_separated def get_coin_status_updates_by_id(self, id, **kwargs): """Get status updates for a given coin""" @@ -154,6 +167,7 @@ def get_coin_status_updates_by_id(self, id, **kwargs): return self.__request(api_url) + @list_args_to_comma_separated def get_coin_info_from_contract_address_by_id(self, id, contract_address): """Get coin info from contract address""" @@ -179,6 +193,7 @@ def get_exchanges_id_name_list(self): return self.__request(api_url) + @list_args_to_comma_separated def get_exchanges_by_id(self, id): """Get exchange volume in BTC and tickers""" @@ -187,6 +202,7 @@ def get_exchanges_by_id(self, id): return self.__request(api_url) + @list_args_to_comma_separated def get_exchanges_tickers_by_id(self, id, **kwargs): """Get exchange tickers (paginated)""" @@ -196,6 +212,7 @@ def get_exchanges_tickers_by_id(self, id, **kwargs): return self.__request(api_url) + @list_args_to_comma_separated def get_exchanges_status_updates_by_id(self, id, **kwargs): """Get status updates for a given exchange""" @@ -206,6 +223,7 @@ def get_exchanges_status_updates_by_id(self, id, **kwargs): #---------- STATUS UPDATES ----------# + @list_args_to_comma_separated def get_status_updates(self, **kwargs): """List all status_updates with data (description, category, created_at, user, user_title and pin)""" @@ -216,6 +234,7 @@ def get_status_updates(self, **kwargs): #---------- EVENTS ----------# + @list_args_to_comma_separated def get_events(self, **kwargs): """Get events, paginated by 100""" diff --git a/pycoingecko/utils.py b/pycoingecko/utils.py index babaaec..93cbd06 100644 --- a/pycoingecko/utils.py +++ b/pycoingecko/utils.py @@ -1,3 +1,15 @@ +def list_args_to_comma_separated(func): + """Return function that converts list input arguments to comma-separated strings""" + def input_args(*args,**kwargs): + for v in kwargs: + # check in **kwargs for lists and convert to comma-separated string + if isinstance(kwargs[v], list): kwargs[v]=','.join(kwargs[v]) + # check in *args for lists and convert to comma-separated string + args=[','.join(v) if isinstance(v, list) else v for v in args] + return func(*args, **kwargs) + return input_args + + def get_comma_separated_values(values): """Return the values as a comma-separated string""" @@ -5,3 +17,4 @@ def get_comma_separated_values(values): if not isinstance(values, list) and not isinstance(values, tuple): values = [values] return ','.join(values) + From b0cda2a41fea6d7617b19f5ae348273a3de7b274 Mon Sep 17 00:00:00 2001 From: Christoforou Manolis Date: Thu, 23 May 2019 22:31:18 +0300 Subject: [PATCH 03/11] Update README.md --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ae3d239..bfe5ac6 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ cg = CoinGeckoAPI() ### Examples The required parameters for each endpoint are defined as required (mandatory) parameters for the coresponding functions. -Optional parameters can be also passed using same names, as defined in CoinGecko API doc (https://www.coingecko.com/api/docs/v3) +**Any optional parameters** can be also passed using same names, as defined in CoinGecko API doc (https://www.coingecko.com/api/docs/v3) Usage examples: ```python @@ -37,14 +37,12 @@ Usage examples: {'bitcoin': {'usd': 3461.27}, 'ethereum': {'usd': 106.92}, 'litecoin': {'usd': 32.72}} >>> cg.get_price(ids='bitcoin,litecoin,ethereum', vs_currencies='usd,eur') -# OR +# OR (lists can be used for multiple-valued arguments) >>> cg.get_price(ids=['bitcoin', 'litecoin', 'ethereum'], vs_currencies=['usd', 'eur']) {'bitcoin': {'usd': 3459.39, 'eur': 3019.33}, 'ethereum': {'usd': 106.91, 'eur': 93.31}, 'litecoin': {'usd': 32.72, 'eur': 28.56}} # optional parameteres can be passed as defined in the API doc (https://www.coingecko.com/api/docs/v3) >>> cg.get_price(ids='bitcoin', vs_currencies='usd', include_market_cap='true', include_24hr_vol='true', include_24hr_change='true', include_last_updated_at='true') -# OR ->>> cg.get_price(ids='bitcoin', vs_currencies='usd', include_market_cap='true', include_24hr_vol='true', include_24hr_change='true', include_last_updated_at='true') {'bitcoin': {'usd': 3458.74, 'usd_market_cap': 60574330199.29028, 'usd_24h_vol': 4182664683.6247883, 'usd_24h_change': 1.2295378479069035, 'last_updated_at': 1549071865}} ``` From cebb01bc2a882466ceec73dff4cc5ccfd86df31f Mon Sep 17 00:00:00 2001 From: Christoforou Manolis Date: Thu, 23 May 2019 22:36:41 +0300 Subject: [PATCH 04/11] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bfe5ac6..51fd060 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ cg = CoinGeckoAPI() ### Examples The required parameters for each endpoint are defined as required (mandatory) parameters for the coresponding functions. **Any optional parameters** can be also passed using same names, as defined in CoinGecko API doc (https://www.coingecko.com/api/docs/v3) +*For parameters that accetp multiple-valued arguments as comma-separated (see /simple/price endpoint), lists can be used directly* Usage examples: ```python @@ -32,7 +33,7 @@ Usage examples: {'bitcoin': {'usd': 3462.04}} >>> cg.get_price(ids='bitcoin,litecoin,ethereum', vs_currencies='usd') -# OR +# OR (lists can be used for multiple-valued arguments) >>> cg.get_price(ids=['bitcoin', 'litecoin', 'ethereum'], vs_currencies='usd') {'bitcoin': {'usd': 3461.27}, 'ethereum': {'usd': 106.92}, 'litecoin': {'usd': 32.72}} From 2151f9a603ea3e50107f4f65cee39d2a6ae6db8b Mon Sep 17 00:00:00 2001 From: Christoforou Manolis Date: Thu, 23 May 2019 22:39:41 +0300 Subject: [PATCH 05/11] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 51fd060..9358e6b 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,8 @@ cg = CoinGeckoAPI() ### Examples The required parameters for each endpoint are defined as required (mandatory) parameters for the coresponding functions. **Any optional parameters** can be also passed using same names, as defined in CoinGecko API doc (https://www.coingecko.com/api/docs/v3) -*For parameters that accetp multiple-valued arguments as comma-separated (see /simple/price endpoint), lists can be used directly* + +*Besides comma-separated strings for multiple-valued arguments (see /simple/price endpoint), lists can be also used directly.* Usage examples: ```python From d7471238811ac7a0a5c029b052e9d8e653f05368 Mon Sep 17 00:00:00 2001 From: Christoforou Manolis Date: Fri, 24 May 2019 17:19:44 +0300 Subject: [PATCH 06/11] include more tests --- tests/test_api.py | 193 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) diff --git a/tests/test_api.py b/tests/test_api.py index a5dd13b..6ce6fc4 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -32,6 +32,116 @@ def test_ping(self): ## Assert assert response == ping_json + + #---------- SIMPLE ----------# + + #---------- /simple/price ----------# + @responses.activate + def test_get_price(self): + # Arrange + coins_json_sample = {"bitcoin": {"usd": 7984.89}} + + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd', + json = coins_json_sample, status = 200) + + # Act + response = CoinGeckoAPI().get_price('bitcoin', 'usd') + + ## Assert + assert response == coins_json_sample + + @responses.activate + def test_failed_get_price(self): + # Arrange + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd', + status = 404) + exception = HTTPError("HTTP Error") + + # Act Assert + with pytest.raises(HTTPError) as HE: + CoinGeckoAPI().get_price('bitcoin', 'usd') + + #---------- /simple/token_price/{id} ----------# + @responses.activate + def test_get_token_price(self): + # Arrange + coins_json_sample = {'0xB8c77482e45F1F44dE1745F52C74426C631bDD52': {'bnb': 1.0, 'bnb_market_cap': 144443301.0, 'bnb_24h_vol': 17983938.686249834, 'last_updated_at': 1558704332}} + + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/simple/token_price/ethereum?include_market_cap=true&include_24hr_vol=true&include_last_updated_at=true&contract_addresses=0xB8c77482e45F1F44dE1745F52C74426C631bDD52&vs_currencies=bnb', + json = coins_json_sample, status = 200) + + # Act + response = CoinGeckoAPI().get_token_price('ethereum', '0xB8c77482e45F1F44dE1745F52C74426C631bDD52', 'bnb', include_market_cap='true', include_24hr_vol='true', include_last_updated_at='true') + + ## Assert + assert response == coins_json_sample + + @responses.activate + def test_failed_get_token_price(self): + # Arrange + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/simple/token_price/ethereum?include_market_cap=true&include_24hr_vol=true&include_last_updated_at=true&contract_addresses=0xB8c77482e45F1F44dE1745F52C74426C631bDD52&vs_currencies=bnb', + status = 404) + exception = HTTPError("HTTP Error") + + # Act Assert + with pytest.raises(HTTPError) as HE: + CoinGeckoAPI().get_token_price('ethereum', '0xB8c77482e45F1F44dE1745F52C74426C631bDD52', 'bnb', include_market_cap='true', include_24hr_vol='true', include_last_updated_at='true') + + #---------- /simple/supported_vs_currencies ----------# + @responses.activate + def test_get_supported_vs_currencies(self): + # Arrange + coins_json_sample = ['btc', 'eth', 'ltc', 'bch', 'bnb', 'eos', 'xrp', 'xlm', 'usd', 'aed', 'ars', 'aud', 'bdt', 'bhd', 'bmd', 'brl', 'cad', 'chf', 'clp', 'cny', 'czk', 'dkk', 'eur', 'gbp', 'hkd', 'huf', 'idr', 'ils', 'inr', 'jpy', 'krw', 'kwd', 'lkr', 'mmk', 'mxn', 'myr', 'nok', 'nzd', 'php', 'pkr', 'pln', 'rub', 'sar', 'sek', 'sgd', 'thb', 'try', 'twd', 'uah', 'vef', 'vnd', 'zar', 'xdr', 'xag', 'xau'] + + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/simple/supported_vs_currencies', + json = coins_json_sample, status = 200) + + # Act + response = CoinGeckoAPI().get_supported_vs_currencies() + + ## Assert + assert response == coins_json_sample + + @responses.activate + def test_failed_get_supported_vs_currencies(self): + # Arrange + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/simple/supported_vs_currencies', + status = 404) + exception = HTTPError("HTTP Error") + + # Act Assert + with pytest.raises(HTTPError) as HE: + CoinGeckoAPI().get_supported_vs_currencies() + + + #---------- /simple/supported_vs_currencies ----------# + @responses.activate + def test_get_supported_vs_currencies(self): + # Arrange + coins_json_sample = ['btc', 'eth', 'ltc', 'bch', 'bnb', 'eos', 'xrp', 'xlm', 'usd', 'aed', 'ars', 'aud', 'bdt', 'bhd', 'bmd', 'brl', 'cad', 'chf', 'clp', 'cny', 'czk', 'dkk', 'eur', 'gbp', 'hkd', 'huf', 'idr', 'ils', 'inr', 'jpy', 'krw', 'kwd', 'lkr', 'mmk', 'mxn', 'myr', 'nok', 'nzd', 'php', 'pkr', 'pln', 'rub', 'sar', 'sek', 'sgd', 'thb', 'try', 'twd', 'uah', 'vef', 'vnd', 'zar', 'xdr', 'xag', 'xau'] + + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/simple/supported_vs_currencies', + json = coins_json_sample, status = 200) + + # Act + response = CoinGeckoAPI().get_supported_vs_currencies() + + ## Assert + assert response == coins_json_sample + + @responses.activate + def test_failed_get_supported_vs_currencies(self): + # Arrange + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/simple/supported_vs_currencies', + status = 404) + exception = HTTPError("HTTP Error") + + # Act Assert + with pytest.raises(HTTPError) as HE: + CoinGeckoAPI().get_supported_vs_currencies() + + + #---------- COINS ----------# @responses.activate def test_failed_get_coins(self): # Arrange @@ -133,6 +243,33 @@ def test_get_coin_by_id(self): ## Assert assert response == bitcoin_json_sample + @responses.activate + def test_failed_get_coin_ticker_by_id(self): + # Arrange + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/bitcoin/tickers', + status = 404) + exception = HTTPError("HTTP Error") + + # Act Assert + with pytest.raises(HTTPError) as HE: + CoinGeckoAPI().get_coin_ticker_by_id('bitcoin') + + + @responses.activate + def test_get_get_coin_ticker_by_id(self): + # Arrange + bitcoin_json_sample = {'name': 'Bitcoin', 'tickers': [{'base': 'BTC', 'target': 'USDT', 'market': {'name': 'BW.com', 'identifier': 'bw', 'has_trading_incentive': False}, 'last': 7963.0, ' volume': 93428.7568, 'converted_last': {'btc': 0.99993976, 'eth': 31.711347, 'usd': 7979.23}, 'converted_volume': {'btc': 93423, 'eth': 2962752, 'usd': 745489919}, ' bid_ask_spread_percentage': 0.111969, 'timestamp': '2019-05-24T11:20:14+00:00', 'is_anomaly': False, 'is_stale': False, 'trade_url': 'https://www.bw.com/trade/btc_us dt', 'coin_id': 'bitcoin'}]} + + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/bitcoin/tickers', + json = bitcoin_json_sample, status = 200) + + # Act + response = CoinGeckoAPI().get_coin_ticker_by_id('bitcoin') + + ## Assert + assert response == bitcoin_json_sample + + @responses.activate def test_failed_get_coin_history_by_id(self): # Arrange @@ -185,6 +322,62 @@ def test_get_coin_market_chart_by_id(self): ## Assert assert response == json_response + + @responses.activate + def test_failed_get_coin_status_updates_by_id(self): + # Arrange + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/litecoin/status_updates', + status = 404) + exception = HTTPError("HTTP Error") + + # Act Assert + with pytest.raises(HTTPError) as HE: + CoinGeckoAPI().get_coin_status_updates_by_id('litecoin') + + + @responses.activate + def test_get_coin_status_updates_by_id(self): + # Arrange + json_response = [ {'description': 'Travala.com Partners with Litecoin Foundation to Champion Crypto Payments. \r\n#TravelWithLitecoin www.travala.com/litecoin\r\n\r\nRead the full announcement here: bit.ly/2LumY3b', 'category': 'general', 'created_at': '2019-05-14T13:56:43.282Z', 'user': 'Keith Yong', 'user_title': 'Operations Director', 'pin': False, 'project': {'type': 'Coin', 'id': 'litecoin', 'name': 'Litecoin', 'symbol': 'ltc', 'image': {'thumb': 'https://assets.coingecko.com/coins/images/2/thumb/litecoin.png?1547033580', 'small': 'https://assets.coingecko.com/coins/images/2/small/litecoin.png?1547033580', 'large': 'https://assets.coingecko.com/coins/images/2/large/litecoin.png?1547033580'}}} ] + + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/litecoin/status_updates', + json = json_response, status = 200) + + # Act + response = CoinGeckoAPI().get_coin_status_updates_by_id('litecoin') + + ## Assert + assert response == json_response + + + @responses.activate + def test_failed_get_coin_info_from_contract_address_by_id(self): + # Arrange + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/ethereum/contract/0xe41d2489571d322189246dafa5ebde1f4699f498', + status = 404) + exception = HTTPError("HTTP Error") + + # Act Assert + with pytest.raises(HTTPError) as HE: + CoinGeckoAPI().get_coin_info_from_contract_address_by_id(id='ethereum',contract_address='0xe41d2489571d322189246dafa5ebde1f4699f498') + + + @responses.activate + def test_get_coin_info_from_contract_address_by_id(self): + # Arrange + json_response = {'id': '0x', 'symbol': 'zrx', 'name': '0x', 'block_time_in_minutes': 0, 'categories': ['Protocol'], 'localization': {'en': '0x', 'es': '0x', 'de': '0x', 'nl': '0x', 'pt': '0x', 'fr': '0x', 'it': '0x', 'hu': '0x', 'ro': '0x', 'sv': '0x', 'pl': '0x', 'id': '0x', 'zh': '0x协议', 'zh-tw': '0x協議', 'ja': 'ロエックス', 'ko': '제로엑스', 'ru': '0x', 'ar': '0x', 'th': '0x', 'vi': '0x', 'tr': '0x'}} + + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/ethereum/contract/0xe41d2489571d322189246dafa5ebde1f4699f498', + json = json_response, status = 200) + + # Act + response = CoinGeckoAPI().get_coin_info_from_contract_address_by_id(id='ethereum',contract_address='0xe41d2489571d322189246dafa5ebde1f4699f498') + + ## Assert + assert response == json_response + + + #---------- EXCHANGES ----------# @responses.activate def test_failed_get_exchanges_list(self): # Arrange From 158420a97c82732e42a684fe2721a5e70c6e2d4c Mon Sep 17 00:00:00 2001 From: Christoforou Manolis Date: Fri, 24 May 2019 18:26:40 +0300 Subject: [PATCH 07/11] exceptions include API error message --- pycoingecko/api.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pycoingecko/api.py b/pycoingecko/api.py index c9dec73..f603c29 100644 --- a/pycoingecko/api.py +++ b/pycoingecko/api.py @@ -23,10 +23,14 @@ def __request(self, url): #print(url) try: response = self.session.get(url, timeout = self.request_timeout) - response.raise_for_status() content = json.loads(response.content.decode('utf-8')) + response.raise_for_status() return content except Exception as e: + try: + raise ValueError(content) + except UnboundLocalError as e: + pass raise From 513deb8ad2758041a5b06e9e0cf52ec2f89d3f4d Mon Sep 17 00:00:00 2001 From: Christoforou Manolis Date: Thu, 30 May 2019 23:25:06 +0300 Subject: [PATCH 08/11] update tests --- tests/test_api.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tests/test_api.py b/tests/test_api.py index 6ce6fc4..bba531d 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -142,6 +142,8 @@ def test_failed_get_supported_vs_currencies(self): #---------- COINS ----------# + + #---------- /price/coins ----------# @responses.activate def test_failed_get_coins(self): # Arrange @@ -167,6 +169,8 @@ def test_get_coins(self): ## Assert assert response == coins_json_sample + + #---------- /price/coins/list ----------# @responses.activate def test_failed_get_coins_list(self): # Arrange @@ -192,6 +196,8 @@ def test_get_coins_list(self): ## Assert assert response == coins_json_sample + + #---------- /price/coins/markets ----------# @responses.activate def test_failed_get_coins_markets(self): # Arrange @@ -217,6 +223,8 @@ def test_get_coins_markets(self): ## Assert assert response == markets_json_sample + + #---------- /price/coins/{id} ----------# @responses.activate def test_failed_get_coin_by_id(self): # Arrange @@ -243,6 +251,8 @@ def test_get_coin_by_id(self): ## Assert assert response == bitcoin_json_sample + + #---------- /price/coins/{id}/tickers ----------# @responses.activate def test_failed_get_coin_ticker_by_id(self): # Arrange @@ -270,6 +280,7 @@ def test_get_get_coin_ticker_by_id(self): assert response == bitcoin_json_sample + #---------- /price/coins/{id}/history ----------# @responses.activate def test_failed_get_coin_history_by_id(self): # Arrange @@ -296,6 +307,8 @@ def test_get_coin_history_by_id(self): ## Assert assert response == history_json_sample + + #---------- /price/coins/{id}/market_chart ----------# @responses.activate def test_failed_get_coin_market_chart_by_id(self): # Arrange @@ -323,6 +336,7 @@ def test_get_coin_market_chart_by_id(self): assert response == json_response + #---------- /price/coins/{id}/status_updates ----------# @responses.activate def test_failed_get_coin_status_updates_by_id(self): # Arrange @@ -350,6 +364,7 @@ def test_get_coin_status_updates_by_id(self): assert response == json_response + #---------- /price/coins/{id}/contract/{contract_address} ----------# @responses.activate def test_failed_get_coin_info_from_contract_address_by_id(self): # Arrange @@ -378,6 +393,9 @@ def test_get_coin_info_from_contract_address_by_id(self): #---------- EXCHANGES ----------# + + + #---------- /exchanges ----------# @responses.activate def test_failed_get_exchanges_list(self): # Arrange @@ -404,6 +422,37 @@ def test_get_exchanges_list(self): ## Assert assert response == json_response + + #---------- /exchanges/list ----------# + @responses.activate + def test_failed_get_exchanges_id_name_list(self): + # Arrange + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/exchanges/list', + status = 404) + exception = HTTPError("HTTP Error") + + # Act Assert + with pytest.raises(HTTPError) as HE: + CoinGeckoAPI().get_exchanges_id_name_list() + + + @responses.activate + def test_get_exchanges_id_name_list(self): + # Arrange + json_response = [{'id': 'abcc', 'name': 'ABCC'}, {'id': 'acx', 'name': 'ACX'}, {'id': 'airswap', 'name': 'AirSwap'}] + + responses.add(responses.GET, 'https://api.coingecko.com/api/v3/exchanges/list', + json = json_response, status = 200) + + # Act + response = CoinGeckoAPI().get_exchanges_id_name_list() + + ## Assert + assert response == json_response + + + + #---------- /exchanges/{id} ----------# @responses.activate def test_failed_get_exchanges_by_id(self): # Arrange @@ -430,6 +479,10 @@ def test_get_exchanges_by_id(self): ## Assert assert response == json_response + + #---------- EXCHANGE RATES ----------# + + #---------- /exchange_rates ----------# @responses.activate def test_failed_get_exchange_rates(self): # Arrange @@ -456,6 +509,10 @@ def test_get_exchange_rates(self): ## Assert assert response == json_response + + #---------- GLOBAL ----------# + + #---------- /global ----------# @responses.activate def test_failed_get_global(self): # Arrange From 8876985c620bf69e018786f65c92b95899203b7b Mon Sep 17 00:00:00 2001 From: Christoforou Manolis Date: Thu, 30 May 2019 23:28:14 +0300 Subject: [PATCH 09/11] update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9358e6b..7b51ec9 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ cg = CoinGeckoAPI() The required parameters for each endpoint are defined as required (mandatory) parameters for the coresponding functions. **Any optional parameters** can be also passed using same names, as defined in CoinGecko API doc (https://www.coingecko.com/api/docs/v3) -*Besides comma-separated strings for multiple-valued arguments (see /simple/price endpoint), lists can be also used directly.* +*Lists are also supported as input for multiple-valued comma-separated parameters (e.g. see /simple/price usage examples).* Usage examples: ```python From 515fd3f0bda21a59d963b6906828cab3c8cf6ea4 Mon Sep 17 00:00:00 2001 From: Christoforou Manolis Date: Fri, 31 May 2019 00:39:31 +0300 Subject: [PATCH 10/11] add pypi badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7b51ec9..48f9108 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # CoinGecko API wrapper +[![PyPi Version](https://img.shields.io/pypi/v/pycoingecko.svg)](https://pypi.python.org/pypi/pycoingecko/) Python3 wrapper around the [CoinGecko](https://www.coingecko.com/) API (V3) From 5c820a8ce50fdb852717563f4f51c5dfb24b638b Mon Sep 17 00:00:00 2001 From: Christoforou Manolis Date: Fri, 31 May 2019 00:40:56 +0300 Subject: [PATCH 11/11] increase version release --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index dbc4194..7acf0fc 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setuptools.setup( name='pycoingecko', - version='0.2.0', + version='0.3.0', packages=['pycoingecko',], license='MIT', description = 'Python wrapper around the CoinGecko API',