Skip to content

Commit

Permalink
Merge branch 'release/0.0.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
man-c committed Nov 17, 2019
2 parents 864bb42 + 138fe1e commit 1cc5eda
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 9 deletions.
53 changes: 53 additions & 0 deletions Changelog.md
@@ -0,0 +1,53 @@

1.0.0 / 2019-11-17
==================

* update tests
* include more contract endpoints
* include /coins/{id}/market_chart/range endpoint
* basic methods for finance endpoints with tests
* updated error handling
* added check for json format in __request; coingecko returns a html string when something goes wrong in the request, which results in an error when json.loads is called on the html string.

0.4.0 / 2019-08-20
==================

* include /exchanges/{id}/volume_chart endpoint

0.3.0 / 2019-05-31
==================

* exceptions include API error message
* fix get_coin_market_chart_by_id test
* Use a list or tuple for multiple-valued arguments
* convert every list arg to comma-separated string

0.2.0 / 2019-05-17
==================

* Fixed arguments for get_token_price
* Added get_token_price function

0.1.6 / 2019-02-02
==================

* README incude examples
* include /exchanges/list endpoint

0.1.0 / 2019-01-02
==================

* add /coins/{id}/tickers endpoint
* include events endpoints
* include status_updates endpoints
* update exchanges endpoints
* update coins endpoints
* include simple endpoints

0.0.2 / 2018-11-20
==================

* use requests session to include retries
* Fixed bug when querying exchanges and added more unit tests
* First unit tests for coingecko wrappers
* initial commit
26 changes: 24 additions & 2 deletions README.md
Expand Up @@ -96,14 +96,27 @@ https://www.coingecko.com/api/docs/v3
```python
cg.get_coin_market_chart_by_id()
```
- /coins/{id}/status_updates (Get status updates for a given coin (beta))
- /coins/{id}/market_chart/range (Get historical market data include price, market cap, and 24h volume within a range of timestamp (granularity auto))
```python
cg.get_coin_market_chart_range_by_id()
```
- /coins/{id}/status_updates (Get status updates for a given coin (beta))
```python
cg.get_coin_status_updates_by_id()
```
- contract
- /coins/{id}/contract/{contract_address} (Get coin info from contract address)
```python
```python
cg.get_coin_info_from_contract_address_by_id()
```
- /coins/{id}/contract/{contract_address}/market_chart/ (Get historical market data include price, market cap, and 24h volume (granularity auto) from a contract address)
```python
cg.get_coin_market_chart_from_contract_address_by_id()
```
- /coins/{id}/contract/{contract_address}/market_chart/range (Get historical market data include price, market cap, and 24h volume within a range of timestamp (granularity auto) from a contract address)
```python
cg.get_coin_market_chart_range_from_contract_address_by_id()
```
- exchanges (beta)
- /exchanges (List all exchanges)
```python
Expand All @@ -129,6 +142,15 @@ https://www.coingecko.com/api/docs/v3
```python
cg.get_exchanges_volume_chart_by_id()
```
- finance (beta)
- /finance_platforms (List all finance platforms)
```python
cg.get_finance_platforms()
```
- /finance_products (List all finance products)
```python
cg.get_finance_products()
```
- status_updates (beta)
- /status_updates (List all status_updates with data (description, category, created_at, user, user_title and pin))
```python
Expand Down
54 changes: 52 additions & 2 deletions pycoingecko/api.py
Expand Up @@ -23,14 +23,19 @@ def __request(self, url):
#print(url)
try:
response = self.session.get(url, timeout = self.request_timeout)
content = json.loads(response.content.decode('utf-8'))
response.raise_for_status()
content = json.loads(response.content.decode('utf-8'))
return content
except Exception as e:
# check if json (with error message) is returned
try:
content = json.loads(response.content.decode('utf-8'))
raise ValueError(content)
except UnboundLocalError as e:
# if no json
except json.decoder.JSONDecodeError:
pass
#except UnboundLocalError as e:
# pass
raise


Expand Down Expand Up @@ -161,6 +166,15 @@ 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_market_chart_range_by_id(self, id, vs_currency, from_timestamp, to_timestamp):
"""Get historical market data include price, market cap, and 24h volume within a range of timestamp (granularity auto)"""

api_url = '{0}coins/{1}/market_chart/range?vs_currency={2}&from={3}&to={4}'.format(self.api_base_url, id, vs_currency, from_timestamp, to_timestamp)

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"""
Expand All @@ -171,6 +185,7 @@ def get_coin_status_updates_by_id(self, id, **kwargs):
return self.__request(api_url)


#---------- Contract ----------#
@list_args_to_comma_separated
def get_coin_info_from_contract_address_by_id(self, id, contract_address):
"""Get coin info from contract address"""
Expand All @@ -180,6 +195,24 @@ def get_coin_info_from_contract_address_by_id(self, id, contract_address):
return self.__request(api_url)


@list_args_to_comma_separated
def get_coin_market_chart_from_contract_address_by_id(self, id, contract_address, vs_currency, days):
"""Get historical market data include price, market cap, and 24h volume (granularity auto) from a contract address"""

api_url = '{0}coins/{1}/contract/{2}/market_chart/?vs_currency={3}&days={4}'.format(self.api_base_url, id, contract_address, vs_currency, days)

return self.__request(api_url)


@list_args_to_comma_separated
def get_coin_market_chart_range_from_contract_address_by_id(self, id, contract_address, vs_currency, from_timestamp, to_timestamp):
"""Get historical market data include price, market cap, and 24h volume within a range of timestamp (granularity auto) from a contract address"""

api_url = '{0}coins/{1}/contract/{2}/market_chart/range?vs_currency={3}&from={4}&to={5}'.format(self.api_base_url, id, contract_address, vs_currency, from_timestamp, to_timestamp)

return self.__request(api_url)


#---------- EXCHANGES ----------#
def get_exchanges_list(self):
"""List all exchanges"""
Expand Down Expand Up @@ -238,6 +271,22 @@ def get_exchanges_volume_chart_by_id(self, id, days, **kwargs):
return self.__request(api_url)


#---------- FINANCE ----------#
def get_finance_platforms(self):
"""Get cryptocurrency finance platforms data"""

api_url = '{0}finance_platforms'.format(self.api_base_url)

return self.__request(api_url)

def get_finance_products(self):
"""Get cryptocurrency finance products data"""

api_url = '{0}finance_products'.format(self.api_base_url)

return self.__request(api_url)


#---------- STATUS UPDATES ----------#
@list_args_to_comma_separated
def get_status_updates(self, **kwargs):
Expand Down Expand Up @@ -292,3 +341,4 @@ def get_global(self):
api_url = '{0}global'.format(self.api_base_url)

return self.__request(api_url)['data']

2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -3,7 +3,7 @@

setuptools.setup(
name='pycoingecko',
version='0.4.0',
version='1.0.0',
packages=['pycoingecko',],
license='MIT',
description = 'Python wrapper around the CoinGecko API',
Expand Down
68 changes: 64 additions & 4 deletions tests/test_api.py
Expand Up @@ -368,25 +368,25 @@ def test_get_coin_status_updates_by_id(self):
@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',
responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/ethereum/contract/0x0D8775F648430679A709E98d2b0Cb6250d2887EF',
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')
CoinGeckoAPI().get_coin_info_from_contract_address_by_id(id='ethereum',contract_address='0x0D8775F648430679A709E98d2b0Cb6250d2887EF')


@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',
responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/ethereum/contract/0x0D8775F648430679A709E98d2b0Cb6250d2887EF',
json = json_response, status = 200)

# Act
response = CoinGeckoAPI().get_coin_info_from_contract_address_by_id(id='ethereum',contract_address='0xe41d2489571d322189246dafa5ebde1f4699f498')
response = CoinGeckoAPI().get_coin_info_from_contract_address_by_id(id='ethereum',contract_address='0x0D8775F648430679A709E98d2b0Cb6250d2887EF')

## Assert
assert response == json_response
Expand Down Expand Up @@ -539,3 +539,63 @@ def test_get_global(self):
## Assert
expected_response = { "active_cryptocurrencies": 2517, "upcoming_icos": 360, "ongoing_icos": 423, "ended_icos": 2037, "markets": 197 }
assert response == expected_response



#---------- FINANCE ----------#

#---------- /finance_platforms ----------#

@responses.activate
def test_failed_get_finance_platforms(self):
# Arrange
responses.add(responses.GET, 'https://api.coingecko.com/api/v3/finance_platforms',
status = 404)
exception = HTTPError("HTTP Error")

# Act Assert
with pytest.raises(HTTPError) as HE:
CoinGeckoAPI().get_finance_platforms()

@responses.activate
def test_get_finance_platforms(self):
# Arrange
json_response = [{"name": "Binance Lending", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Celsius Network", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Compound Finance", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "dYdX", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Nexo", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Staked US", "facts": "", "category": "", "centralized": False, "website_url": "https://staked.us/"}, {"name": "Cobo", "facts": "", "category": "", "centralized": False, "website_url": "https://cobo.com/"}, {"name": "Crypto.com", "facts": "", "category": "", "centralized": True, "website_url": "https://crypto.com/en/"}]

responses.add(responses.GET, 'https://api.coingecko.com/api/v3/finance_platforms',
json = json_response, status = 200)

# Act
response = CoinGeckoAPI().get_finance_platforms()

## Assert
expected_response = [{"name": "Binance Lending", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Celsius Network", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Compound Finance", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "dYdX", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Nexo", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Staked US", "facts": "", "category": "", "centralized": False, "website_url": "https://staked.us/"}, {"name": "Cobo", "facts": "", "category": "", "centralized": False, "website_url": "https://cobo.com/"}, {"name": "Crypto.com", "facts": "", "category": "", "centralized": True, "website_url": "https://crypto.com/en/"}]
assert response == expected_response

#---------- /finance_products ----------#

@responses.activate
def test_failed_get_finance_products(self):
# Arrange
responses.add(responses.GET, 'https://api.coingecko.com/api/v3/finance_products',
status = 404)
exception = HTTPError("HTTP Error")

# Act Assert
with pytest.raises(HTTPError) as HE:
CoinGeckoAPI().get_finance_products()

@responses.activate
def test_get_finance_products(self):
# Arrange
json_response = [{"name": "Binance Lending", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Celsius Network", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Compound Finance", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "dYdX", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Nexo", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Staked US", "facts": "", "category": "", "centralized": False, "website_url": "https://staked.us/"}, {"name": "Cobo", "facts": "", "category": "", "centralized": False, "website_url": "https://cobo.com/"}, {"name": "Crypto.com", "facts": "", "category": "", "centralized": True, "website_url": "https://crypto.com/en/"}]

responses.add(responses.GET, 'https://api.coingecko.com/api/v3/finance_platforms',
json = json_response, status = 200)

# Act
response = CoinGeckoAPI().get_finance_platforms()

## Assert
expected_response = [{"name": "Binance Lending", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Celsius Network", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Compound Finance", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "dYdX", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Nexo", "facts": "", "category": "", "centralized": False, "website_url": ""}, {"name": "Staked US", "facts": "", "category": "", "centralized": False, "website_url": "https://staked.us/"}, {"name": "Cobo", "facts": "", "category": "", "centralized": False, "website_url": "https://cobo.com/"}, {"name": "Crypto.com", "facts": "", "category": "", "centralized": True, "website_url": "https://crypto.com/en/"}]
assert response == expected_response

0 comments on commit 1cc5eda

Please sign in to comment.