├── .gitignore ├── CHANGELOG.md ├── LICENCE ├── README.md ├── pycoingecko ├── __init__.py ├── api.py ├── utils.py └── version.py ├── setup.py └── tests └── test_api.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # IPython 76 | profile_default/ 77 | ipython_config.py 78 | 79 | # pyenv 80 | .python-version 81 | 82 | # celery beat schedule file 83 | celerybeat-schedule 84 | 85 | # SageMath parsed files 86 | *.sage.py 87 | 88 | # Environments 89 | .env 90 | .venv 91 | env/ 92 | venv/ 93 | ENV/ 94 | env.bak/ 95 | venv.bak/ 96 | 97 | # Spyder project settings 98 | .spyderproject 99 | .spyproject 100 | 101 | # Rope project settings 102 | .ropeproject 103 | 104 | # mkdocs documentation 105 | /site 106 | 107 | # mypy 108 | .mypy_cache/ 109 | .dmypy.json 110 | dmypy.json 111 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3.2.0 / 2024-11-13 3 | ================== 4 | 5 | * support both public (with or without demo_api_key) and pro (with pro api key) api in requests 6 | * added new methods in coins, asset_platforms, exchanges, nfts, global 7 | 8 | 3.1.0 / 2022-10-26 9 | ================== 10 | 11 | * added nfts (beta) endpoints (/nfts/list, /nfts/{id}, /nfts/{asset_platform_id}/contract/{contract_address}) 12 | * updated tests 13 | 14 | 3.0.0 / 2022-09-01 15 | ================== 16 | 17 | * removed deprecated endpoints (status_updates, finance and events): 18 | * /coins/{id}/status_updates -> cg.get_coin_status_updates_by_id() 19 | * /exchanges/{id}/status_updates -> cg.get_exchanges_status_updates_by_id() 20 | * /finance_platforms -> cg.get_finance_platforms() 21 | * /finance_products -> cg.get_finance_products() 22 | * /status_updates -> cg.get_status_updates() 23 | * /events -> cg.get_events() 24 | * /events/countries -> cg.get_events_countries() 25 | * /events/types -> cg.get_events_types() 26 | * removed deprecated api_base_url param from CoinGeckoAPI init 27 | 28 | 2.3.0 / 2022-08-30 29 | ================== 30 | 31 | * added /search endpoint 32 | * added CoinGecko Pro API support using api_key param in CoinGeckoAPI init (required in PRO version API calls) 33 | * added ability to modify how many retries to do in requests session using param retries in CoinGeckoAPI init (default: retries=5) 34 | * fixed session to mount retry adapter on https instead of http 35 | * fixed params passed in get_coin_market_chart_range_from_contract_address_by_id for /coins/{id}/contract/{contract_address}/market_chart/range endpoint 36 | 37 | 2.2.0 / 2021-06-17 38 | ================== 39 | 40 | * added /indexes/{market_id}/{id} and /companies/public_treasury/{coin_id} endpoints 41 | 42 | 2.1.0 / 2021-06-03 43 | ================== 44 | 45 | * added asset_platforms (/asset_platforms) and categories (/coins/categories/list, coins/categories) endpoints 46 | 47 | 2.0.0 / 2021-04-23 48 | ================== 49 | 50 | * allow Python Lists and Booleans for any endpoint parameter (list converted to comma-separated string & bool converted to lower case string) 51 | * removed /indexes/{id} endpoint (Get market index by id) -> cg.get_indexes_by_id() 52 | * improved request exceptions handling (Fixed unbound local exception on GET request failure) 53 | 54 | 1.4.1 / 2021-03-30 55 | ================== 56 | 57 | * fixed __api_url_params issue for optional parametes of few endpoints (such as /coins/{id}/market_chart) 58 | 59 | 1.4.0 / 2020-10-03 60 | ================== 61 | 62 | * added new endpoints (/coins/{id}/ohlc, /search/trending, /global/decentralized_finance_defi) 63 | * updated tests 64 | 65 | 1.3.0 / 2020-07-12 66 | ================== 67 | 68 | * allow optional arguments for **ALL** endopoints 69 | 70 | 1.2.0 / 2019-12-13 71 | ================== 72 | 73 | * added indexes endpoints (/indexes, /indexes/{id}, /indexes/list) 74 | 75 | 1.1.0 / 2019-12-06 76 | ================== 77 | 78 | * added derivatives endpoints (/derivatives, /derivatives/exchanges, /derivatives/exchanges/{id}, /derivatives/exchanges/list) 79 | 80 | 1.0.0 / 2019-11-17 81 | ================== 82 | 83 | * updated tests 84 | * included more contract endpoints 85 | * included /coins/{id}/market_chart/range endpoint 86 | * basic methods for finance endpoints with tests 87 | * updated error handling 88 | * 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. 89 | 90 | 0.4.0 / 2019-08-20 91 | ================== 92 | 93 | * included /exchanges/{id}/volume_chart endpoint 94 | 95 | 0.3.0 / 2019-05-31 96 | ================== 97 | 98 | * exceptions include API error message 99 | * fix get_coin_market_chart_by_id test 100 | * Use a list or tuple for multiple-valued arguments 101 | * convert every list arg to comma-separated string 102 | 103 | 0.2.0 / 2019-05-17 104 | ================== 105 | 106 | * Fixed arguments for get_token_price 107 | * Added get_token_price function 108 | 109 | 0.1.6 / 2019-02-02 110 | ================== 111 | 112 | * README incude examples 113 | * included /exchanges/list endpoint 114 | 115 | 0.1.0 / 2019-01-02 116 | ================== 117 | 118 | * added /coins/{id}/tickers endpoint 119 | * included events endpoints 120 | * included status_updates endpoints 121 | * updated exchanges endpoints 122 | * updated coins endpoints 123 | * included simple endpoints 124 | 125 | 0.0.2 / 2018-11-20 126 | ================== 127 | 128 | * use requests session to include retries 129 | * fixed bug when querying exchanges and added more unit tests 130 | * first unit tests for coingecko wrappers 131 | * initial commit 132 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Christoforou Emmanouil 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CoinGecko API wrapper 2 | [![PyPi Version](https://img.shields.io/pypi/v/pycoingecko.svg)](https://pypi.python.org/pypi/pycoingecko/) 3 | ![GitHub](https://img.shields.io/github/license/man-c/pycoingecko) 4 | 5 | Python3 wrapper around the [CoinGecko](https://www.coingecko.com/) API (V3) 🦎
Supports both Public and Pro API: 6 | * [Public API v3.0.1](https://docs.coingecko.com/v3.0.1/reference/introduction) 7 | * [Pro API v3.1.1](https://docs.coingecko.com/v3.1.1/reference/introduction) 8 | 9 | ### Installation 10 | PyPI 11 | ```bash 12 | pip install -U pycoingecko 13 | ``` 14 | or from source 15 | ```bash 16 | git clone https://github.com/man-c/pycoingecko.git 17 | cd pycoingecko 18 | python3 setup.py install 19 | ``` 20 | 21 | ### Usage 22 | 23 | For free **Public API**: 24 | 25 | * without any demo api key (x-cg-demo-api-key): 26 | ```python 27 | from pycoingecko import CoinGeckoAPI 28 | cg = CoinGeckoAPI() 29 | ``` 30 | * 🔑 with a demo api key: 31 | ```python 32 | from pycoingecko import CoinGeckoAPI 33 | cg = CoinGeckoAPI(demo_api_key='YOUR_DEMO_API_KEY') 34 | ``` 35 | 36 | For **Pro API**: 37 | * 🔑 with a pro api key: 38 | ```python 39 | from pycoingecko import CoinGeckoAPI 40 | cg = CoinGeckoAPI(api_key='YOUR_PRO_API_KEY') 41 | ``` 42 | 43 | ### Examples 44 | The required parameters for each endpoint are defined as required (mandatory) parameters for the corresponding functions.\ 45 | **Any optional parameters** can be passed using same names, as defined in CoinGecko API doc (https://www.coingecko.com/en/api/documentation). 46 | 47 | For any parameter: 48 | - ***Lists** are supported as input for multiple-valued comma-separated parameters\ 49 | (e.g. see /simple/price usage examples).* 50 | - ***Booleans** are supported as input for boolean type parameters; they can be `str` ('true', 'false'') or `bool` (`True`, `False`)\ 51 | (e.g. see /simple/price usage examples).* 52 | 53 | Usage examples: 54 | ```python 55 | # /simple/price endpoint with the required parameters 56 | >>> cg.get_price(ids='bitcoin', vs_currencies='usd') 57 | {'bitcoin': {'usd': 3462.04}} 58 | 59 | >>> cg.get_price(ids='bitcoin,litecoin,ethereum', vs_currencies='usd') 60 | # OR (lists can be used for multiple-valued arguments) 61 | >>> cg.get_price(ids=['bitcoin', 'litecoin', 'ethereum'], vs_currencies='usd') 62 | {'bitcoin': {'usd': 3461.27}, 'ethereum': {'usd': 106.92}, 'litecoin': {'usd': 32.72}} 63 | 64 | >>> cg.get_price(ids='bitcoin,litecoin,ethereum', vs_currencies='usd,eur') 65 | # OR (lists can be used for multiple-valued arguments) 66 | >>> cg.get_price(ids=['bitcoin', 'litecoin', 'ethereum'], vs_currencies=['usd', 'eur']) 67 | {'bitcoin': {'usd': 3459.39, 'eur': 3019.33}, 'ethereum': {'usd': 106.91, 'eur': 93.31}, 'litecoin': {'usd': 32.72, 'eur': 28.56}} 68 | 69 | # optional parameters can be passed as defined in the API doc (https://www.coingecko.com/api/docs/v3) 70 | >>> 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') 71 | {'bitcoin': {'usd': 3458.74, 'usd_market_cap': 60574330199.29028, 'usd_24h_vol': 4182664683.6247883, 'usd_24h_change': 1.2295378479069035, 'last_updated_at': 1549071865}} 72 | # OR (also booleans can be used for boolean type arguments) 73 | >>> 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) 74 | {'bitcoin': {'usd': 3458.74, 'usd_market_cap': 60574330199.29028, 'usd_24h_vol': 4182664683.6247883, 'usd_24h_change': 1.2295378479069035, 'last_updated_at': 1549071865}} 75 | ``` 76 | 77 | ### API documentation 78 | https://www.coingecko.com/en/api/documentation 79 | 80 | ### 📡 Endpoints included 81 | > :warning: **Endpoints documentation**: To make sure that you are using properly each endpoint you should check the [API documentation](https://www.coingecko.com/en/api/documentation). Return behaviour and parameters of the endpoints, such as *pagination*, might have changed.
Any **optional parameters** defined in CoinGecko API doc can be passed as function parameters using same parameters names with the API *(see Examples above)*. 82 |
ping 83 |

84 | 85 | * **/ping** 86 | 87 | _Check API server status_ 88 | ```python 89 | cg.ping() 90 | ``` 91 |

92 | 93 |
key 94 |

95 | 96 | * [Pro API] 💼 **/key** 97 | 98 | _Monitor your account's API usage, including rate limits, monthly total credits, remaining credits, and more_ 99 | ```python 100 | cg.key() 101 | ``` 102 |

103 | 104 |
simple 105 |

106 | 107 | * **/simple/price** 108 | 109 | _Get the current price of any cryptocurrencies in any other supported currencies that you need_ 110 | ```python 111 | cg.get_price() 112 | ``` 113 | * **/simple/token_price/{id}** 114 | 115 | _Get current price of tokens (using contract addresses) for a given platform in any other currency that you need_ 116 | ```python 117 | cg.get_token_price() 118 | ``` 119 | * **/simple/supported_vs_currencies** 120 | 121 | _Get list of supported_vs_currencies_ 122 | ```python 123 | cg.get_supported_vs_currencies() 124 | ``` 125 |

126 | 127 |
coins 128 |

129 | 130 | * **/coins/list** 131 | 132 | _List all supported coins id, name and symbol (no pagination required)_ 133 | ```python 134 | cg.get_coins_list() 135 | ``` 136 | 137 | * [Pro API] 💼 **/coins/top_gainers_losers** 138 | 139 | _Query the top 30 coins with largest price gain and loss by a specific time duration_ 140 | ```python 141 | cg.get_coin_top_gainers_losers() 142 | ``` 143 | 144 | * [Pro API] 💼 **/coins/list/new** 145 | 146 | _Query the latest 200 coins that recently listed on CoinGecko_ 147 | ```python 148 | cg.get_coins_list_new() 149 | ``` 150 | 151 | * **/coins/markets** 152 | 153 | _List all supported coins price, market cap, volume, and market related data_ 154 | ```python 155 | cg.get_coins_markets() 156 | ``` 157 | * **/coins/{id}** 158 | 159 | _Get current data (name, price, market, ... including exchange tickers) for a coin_ 160 | ```python 161 | cg.get_coin_by_id() 162 | ``` 163 | * **/coins/{id}/tickers** 164 | 165 | _Get coin tickers (paginated to 100 items)_ 166 | ```python 167 | cg.get_coin_ticker_by_id() 168 | ``` 169 | * **/coins/{id}/history** 170 | 171 | _Get historical data (name, price, market, stats) at a given date for a coin_ 172 | ```python 173 | cg.get_coin_history_by_id() 174 | ``` 175 | * **/coins/{id}/market_chart** 176 | 177 | _Get historical market data include price, market cap, and 24h volume (granularity auto)_ 178 | ```python 179 | cg.get_coin_market_chart_by_id() 180 | ``` 181 | * **/coins/{id}/market_chart/range** 182 | 183 | _Get historical market data include price, market cap, and 24h volume within a range of timestamp (granularity auto)_ 184 | ```python 185 | cg.get_coin_market_chart_range_by_id() 186 | ``` 187 | 188 | [//]: # (* **/coins/{id}/status_updates** (Get status updates for a given coin (beta))) 189 | 190 | [//]: # ( ```python) 191 | 192 | [//]: # ( cg.get_coin_status_updates_by_id()) 193 | 194 | [//]: # ( ```) 195 | * **/coins/{id}/ohlc** 196 | 197 | _Get the OHLC chart (Open, High, Low, Close) of a coin based on particular coin id_ 198 | ```python 199 | cg.get_coin_ohlc_by_id() 200 | ``` 201 | 202 | * [Pro API] 💼 **/coins/{id}/ohlc/range** 203 | 204 | _Get the OHLC chart (Open, High, Low, Close) of a coin within a range of timestamp based on particular coin id_ 205 | ```python 206 | cg.get_coin_ohlc_by_id_range() 207 | ``` 208 | 209 | * [Pro API] 👑 **/coins/{id}/circulating_supply_chart** 210 | 211 | _Query historical circulating supply of a coin by number of days away from now based on provided coin id_ 212 | ```python 213 | cg.get_coin_circulating_supply_chart() 214 | ``` 215 | 216 | * [Pro API] 👑 **/coins/{id}/circulating_supply_chart/range** 217 | 218 | _Query historical circulating supply of a coin, within a range of timestamp based on the provided coin id_ 219 | ```python 220 | cg.get_coin_circulating_supply_chart_range() 221 | ``` 222 | 223 | * [Pro API] 👑 **/coins/{id}/total_supply_chart** 224 | 225 | _Query historical total supply of a coin by number of days away from now based on provided coin id_ 226 | ```python 227 | cg.get_coin_total_supply_chart() 228 | ``` 229 | 230 | * [Pro API] 👑 **/coins/{id}/total_supply_chart/range** 231 | 232 | _Query historical total supply of a coin, within a range of timestamp based on the provided coin id_ 233 | ```python 234 | cg.get_coin_total_supply_chart_range() 235 | ``` 236 | 237 |

238 | 239 | 240 |
contract 241 |

242 | 243 | * **/coins/{id}/contract/{contract_address}** 244 | 245 | _Get coin info from contract address_ 246 | ```python 247 | cg.get_coin_info_from_contract_address_by_id() 248 | ``` 249 | * **/coins/{id}/contract/{contract_address}/market_chart/** 250 | 251 | _Get historical market data include price, market cap, and 24h volume (granularity auto) from a contract address_ 252 | ```python 253 | cg.get_coin_market_chart_from_contract_address_by_id() 254 | ``` 255 | * **/coins/{id}/contract/{contract_address}/market_chart/range** 256 | 257 | _Get historical market data include price, market cap, and 24h volume within a range of timestamp (granularity auto) from a contract address_ 258 | ```python 259 | cg.get_coin_market_chart_range_from_contract_address_by_id() 260 | ``` 261 |

262 | 263 |
asset_platforms 264 |

265 | 266 | * **/asset_platforms** 267 | 268 | _List all asset platforms (Blockchain networks)_ 269 | ```python 270 | cg.get_asset_platforms() 271 | ``` 272 | 273 | * [Pro API] 👑 **/token_lists/{asset_platform_id}/all.json** 274 | 275 | _Get full list of tokens of a blockchain network (asset platform) that is supported by Ethereum token list standard_ 276 | ```python 277 | cg.get_asset_platform_by_id() 278 | ``` 279 | 280 |

281 | 282 |
categories 283 |

284 | 285 | * **/coins/categories/list** 286 | 287 | _List all categories_ 288 | ```python 289 | cg.get_coins_categories_list() 290 | ``` 291 | * **coins/categories** 292 | 293 | _List all categories with market data_ 294 | ```python 295 | cg.get_coins_categories() 296 | ``` 297 |

298 | 299 |
exchanges 300 |

301 | 302 | * **/exchanges** 303 | 304 | _List all exchanges_ 305 | ```python 306 | cg.get_exchanges_list() 307 | ``` 308 | * **/exchanges/list** 309 | 310 | _List all supported markets id and name (no pagination required)_ 311 | ```python 312 | cg.get_exchanges_id_name_list() 313 | ``` 314 | * **/exchanges/{id}** 315 | 316 | _Get exchange volume in BTC and top 100 tickers only_ 317 | ```python 318 | cg.get_exchanges_by_id() 319 | ``` 320 | * **/exchanges/{id}/tickers** 321 | 322 | _Get exchange tickers (paginated, 100 tickers per page)_ 323 | ```python 324 | cg.get_exchanges_tickers_by_id() 325 | ``` 326 | 327 | [//]: # (* **/exchanges/{id}/status_updates** (Get status updates for a given exchange (beta))) 328 | 329 | [//]: # ( ```python) 330 | 331 | [//]: # ( cg.get_exchanges_status_updates_by_id()) 332 | 333 | [//]: # ( ```) 334 | * **/exchanges/{id}/volume_chart** 335 | 336 | _Get volume_chart data for a given exchange_ 337 | ```python 338 | cg.get_exchanges_volume_chart_by_id() 339 | ``` 340 | 341 | * [Pro API] 💼 **/exchanges/{id}/volume_chart/range** 342 | 343 | _Query the historical volume chart data in BTC by specifying date range in UNIX based on exchange’s id_ 344 | ```python 345 | cg.get_exchanges_volume_chart_by_id_within_time_range() 346 | ``` 347 | 348 |

349 | 350 | [//]: # (
finance) 351 | 352 | [//]: # (

) 353 | 354 | [//]: # () 355 | [//]: # (* **/finance_platforms** (List all finance platforms)) 356 | 357 | [//]: # ( ```python) 358 | 359 | [//]: # ( cg.get_finance_platforms()) 360 | 361 | [//]: # ( ```) 362 | 363 | [//]: # (* **/finance_products** (List all finance products)) 364 | 365 | [//]: # ( ```python) 366 | 367 | [//]: # ( cg.get_finance_products()) 368 | 369 | [//]: # ( ```) 370 | 371 | [//]: # (

) 372 | 373 |
indexes 374 |

375 | 376 | * **/indexes** 377 | 378 | _List all market indexes_ 379 | ```python 380 | cg.get_indexes() 381 | ``` 382 | * **/indexes/{market_id}/{id}** 383 | 384 | _Get market index by market id and index id_ 385 | ```python 386 | cg.get_indexes_by_market_id_and_index_id() 387 | ``` 388 | * **/indexes/list** 389 | 390 | _List market indexes id and name_ 391 | ```python 392 | cg.get_indexes_list() 393 | ``` 394 |

395 | 396 |
derivatives 397 |

398 | 399 | * **/derivatives** 400 | 401 | _List all derivative tickers_ 402 | ```python 403 | cg.get_derivatives() 404 | ``` 405 | * **/derivatives/exchanges** 406 | 407 | _List all derivative exchanges_ 408 | ```python 409 | cg.get_derivatives_exchanges() 410 | ``` 411 | * **/derivatives/exchanges/{id}** 412 | 413 | _Show derivative exchange data_ 414 | ```python 415 | cg.get_derivatives_exchanges_by_id() 416 | ``` 417 | * **/derivatives/exchanges/list** 418 | 419 | _List all derivative exchanges name and identifier_ 420 | ```python 421 | cg.get_derivatives_exchanges_list() 422 | ``` 423 |

424 | 425 |
nfts (beta) 426 |

427 | 428 | * **/nfts/list** 429 | 430 | _List all supported NFT ids, paginated by 100 items per page, paginated to 100 items_ 431 | ```python 432 | cg.get_nfts_list() 433 | ``` 434 | * **/nfts/{id}** 435 | 436 | _Get current data (name, price_floor, volume_24h ...) for an NFT collection. native_currency (string) is only a representative of the currency_ 437 | ```python 438 | cg.get_nfts_by_id() 439 | ``` 440 | * **/nfts/{asset_platform_id}/contract/{contract_address}** 441 | 442 | _Get current data (name, price_floor, volume_24h ...) for an NFT collection. native_currency (string) is only a representative of the currency_ 443 | ```python 444 | cg.get_nfts_collection_by_asset_platform_id_and_contract_address() 445 | ``` 446 | 447 | * [Pro API] 💼 **/nfts/markets** 448 | 449 | _Query all the supported NFT collections with floor price, market cap, volume and market related data on CoinGecko_ 450 | ```python 451 | cg.get_nfts_markets() 452 | ``` 453 | 454 | * [Pro API] 💼 **/nfts/{id}/market_chart** 455 | 456 | _Query historical market data of a NFT collection, including floor price, market cap, and 24h volume, by number of days away from now_ 457 | ```python 458 | cg.get_nfts_market_chart_by_id() 459 | ``` 460 | 461 | * [Pro API] 💼 **/nfts/{asset_platform_id}/contract/{contract_address}/market_chart** 462 | 463 | _Query historical market data of a NFT collection, including floor price, market cap, and 24h volume, by number of days away from now based on the provided contract address_ 464 | ```python 465 | cg.get_ntfs_market_chart_by_asset_platform_id_and_contract_address() 466 | ``` 467 | 468 | * [Pro API] 💼 **/nfts/{id}/tickers** 469 | 470 | _Query the latest floor price and 24h volume of a NFT collection, on each NFT marketplace, e.g. OpenSea and LooksRare_ 471 | ```python 472 | cg.get_nfts_tickers_by_id() 473 | ``` 474 | 475 |

476 | 477 | [//]: # (
status_updates) 478 | 479 | [//]: # (

) 480 | 481 | [//]: # () 482 | [//]: # (* **/status_updates** (List all status_updates with data (description, category, created_at, user, user_title and pin))) 483 | 484 | [//]: # ( ```python) 485 | 486 | [//]: # ( cg.get_status_updates()) 487 | 488 | [//]: # ( ```) 489 | 490 | [//]: # (

) 491 | 492 | [//]: # (
events) 493 | 494 | [//]: # (

) 495 | 496 | [//]: # () 497 | [//]: # (* **/events** (Get events, paginated by 100)) 498 | 499 | [//]: # ( ```python) 500 | 501 | [//]: # ( cg.get_events()) 502 | 503 | [//]: # ( ```) 504 | 505 | [//]: # (* **/events/countries** (Get list of event countries)) 506 | 507 | [//]: # ( ```python) 508 | 509 | [//]: # ( cg.get_events_countries()) 510 | 511 | [//]: # ( ```) 512 | 513 | [//]: # (* **/events/types** (Get list of events types)) 514 | 515 | [//]: # ( ```python) 516 | 517 | [//]: # ( cg.get_events_types()) 518 | 519 | [//]: # ( ```) 520 | 521 | [//]: # (

) 522 | 523 |
exchange_rates 524 |

525 | 526 | * **/exchange_rates** 527 | 528 | _Get BTC-to-Currency exchange rates_ 529 | ```python 530 | cg.get_exchange_rates() 531 | ``` 532 |

533 | 534 |
search 535 |

536 | 537 | * **/search** 538 | 539 | _Search for coins, categories and markets on CoinGecko_ 540 | ```python 541 | cg.search() 542 | ``` 543 |

544 | 545 |
trending 546 |

547 | 548 | * **/search/trending** 549 | 550 | _Get trending search coins (Top-7) on CoinGecko in the last 24 hours_ 551 | ```python 552 | cg.get_search_trending() 553 | ``` 554 |

555 | 556 |
global 557 |

558 | 559 | * **/global** 560 | 561 | _Get cryptocurrency global data_ 562 | ```python 563 | cg.get_global() 564 | ``` 565 | * **/global/decentralized_finance_defi** 566 | 567 | _Get cryptocurrency global decentralized finance(defi) data_ 568 | ```python 569 | cg.get_global_decentralized_finance_defi() 570 | ``` 571 | 572 | * [Pro API] 💼 **/global/market_cap_chart** 573 | 574 | _Query historical global market cap and volume data by number of days away from now)_ 575 | ```python 576 | cg.get_global_market_cap_chart() 577 | ``` 578 | 579 |

580 | 581 |
companies (beta) 582 |

583 | 584 | * **/companies/public_treasury/{coin_id}** 585 | 586 | _Query public companies’ bitcoin or ethereum holdings_ 587 | ```python 588 | cg.get_companies_public_treasury_by_coin_id() 589 | ``` 590 |

591 | 592 | ### Test 593 | 594 | #### Installation 595 | Install required packages for testing using: 596 | ```bash 597 | pip install pytest responses 598 | ``` 599 | 600 | #### Usage 601 | 602 | Run unit tests with: 603 | 604 | ``` 605 | # after installing pytest and responses using pip3 606 | pytest tests 607 | ``` 608 | 609 | ## License 610 | [MIT](https://choosealicense.com/licenses/mit/) 611 | -------------------------------------------------------------------------------- /pycoingecko/__init__.py: -------------------------------------------------------------------------------- 1 | from .api import CoinGeckoAPI 2 | from .version import __version__ 3 | -------------------------------------------------------------------------------- /pycoingecko/api.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | 4 | from requests.adapters import HTTPAdapter 5 | from requests.packages.urllib3.util.retry import Retry 6 | 7 | from .utils import func_args_preprocessing 8 | 9 | 10 | class CoinGeckoAPI: 11 | __API_URL_BASE = 'https://api.coingecko.com/api/v3/' 12 | __PRO_API_URL_BASE = 'https://pro-api.coingecko.com/api/v3/' 13 | 14 | def __init__(self, api_key: str = '', retries=5, demo_api_key: str = ''): 15 | 16 | self.extra_params = None 17 | # self.headers = None 18 | if api_key: 19 | self.api_base_url = self.__PRO_API_URL_BASE 20 | self.extra_params = {'x_cg_pro_api_key': api_key} 21 | # self.headers = {"accept": "application/json", 22 | # "x-cg-pro-api-key": api_key} 23 | else: 24 | self.api_base_url = self.__API_URL_BASE 25 | if demo_api_key: 26 | self.extra_params = {'x_cg_demo_api_key': demo_api_key} 27 | # self.headers = {"accept": "application/json", 28 | # "x-cg-demo-api-key": demo_api_key} 29 | 30 | self.request_timeout = 120 31 | 32 | self.session = requests.Session() 33 | retries = Retry(total=retries, backoff_factor=0.5, status_forcelist=[502, 503, 504]) 34 | self.session.mount('https://', HTTPAdapter(max_retries=retries)) 35 | 36 | # self.session.headers = self.headers 37 | 38 | def __request(self, url, params): 39 | # if using pro or demo version of CoinGecko with api key, inject key in every call 40 | if self.extra_params is not None: 41 | params.update(self.extra_params) 42 | 43 | try: 44 | response = self.session.get(url, params=params, timeout=self.request_timeout) 45 | except requests.exceptions.RequestException: 46 | raise 47 | 48 | try: 49 | response.raise_for_status() 50 | # self._headers = response.headers 51 | content = json.loads(response.content.decode('utf-8')) 52 | return content 53 | except Exception as e: 54 | # check if json (with error message) is returned 55 | try: 56 | content = json.loads(response.content.decode('utf-8')) 57 | raise ValueError(content) 58 | # if no json 59 | except json.decoder.JSONDecodeError: 60 | pass 61 | 62 | raise 63 | 64 | # def __api_url_params(self, api_url, params, api_url_has_params=False): 65 | # # if using pro version of CoinGecko, inject key in every call 66 | # if self.api_key: 67 | # params['x_cg_pro_api_key'] = self.api_key 68 | # 69 | # if params: 70 | # # if api_url contains already params and there is already a '?' avoid 71 | # # adding second '?' (api_url += '&' if '?' in api_url else '?'); causes 72 | # # issues with request parametes (usually for endpoints with required 73 | # # arguments passed as parameters) 74 | # api_url += '&' if api_url_has_params else '?' 75 | # for key, value in params.items(): 76 | # if type(value) == bool: 77 | # value = str(value).lower() 78 | # 79 | # api_url += "{0}={1}&".format(key, value) 80 | # api_url = api_url[:-1] 81 | # return api_url 82 | 83 | # ---------- PING ----------# 84 | def ping(self, **kwargs): 85 | """Check API server status""" 86 | 87 | api_url = '{0}ping'.format(self.api_base_url) 88 | # api_url = self.__api_url_params(api_url, kwargs) 89 | 90 | return self.__request(api_url, kwargs) 91 | 92 | # ---------- KEY ----------# 93 | def key(self, **kwargs): 94 | """Monitor your account's API usage, including rate limits, monthly total credits, remaining credits, and more""" 95 | 96 | api_url = '{0}key'.format(self.api_base_url) 97 | # api_url = self.__api_url_params(api_url, kwargs) 98 | 99 | return self.__request(api_url, kwargs) 100 | 101 | # ---------- SIMPLE ----------# 102 | @func_args_preprocessing 103 | def get_price(self, ids, vs_currencies, **kwargs): 104 | """Get the current price of any cryptocurrencies in any other supported currencies that you need""" 105 | 106 | ids = ids.replace(' ', '') 107 | kwargs['ids'] = ids 108 | vs_currencies = vs_currencies.replace(' ', '') 109 | kwargs['vs_currencies'] = vs_currencies 110 | 111 | api_url = '{0}simple/price'.format(self.api_base_url) 112 | # api_url = self.__api_url_params(api_url, kwargs) 113 | 114 | return self.__request(api_url, kwargs) 115 | 116 | @func_args_preprocessing 117 | def get_token_price(self, id, contract_addresses, vs_currencies, **kwargs): 118 | """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""" 119 | 120 | contract_addresses = contract_addresses.replace(' ', '') 121 | kwargs['contract_addresses'] = contract_addresses 122 | vs_currencies = vs_currencies.replace(' ', '') 123 | kwargs['vs_currencies'] = vs_currencies 124 | 125 | api_url = '{0}simple/token_price/{1}'.format(self.api_base_url, id) 126 | # api_url = self.__api_url_params(api_url, kwargs) 127 | return self.__request(api_url, kwargs) 128 | 129 | @func_args_preprocessing 130 | def get_supported_vs_currencies(self, **kwargs): 131 | """Get list of supported_vs_currencies""" 132 | 133 | api_url = '{0}simple/supported_vs_currencies'.format(self.api_base_url) 134 | # api_url = self.__api_url_params(api_url, kwargs) 135 | 136 | return self.__request(api_url, kwargs) 137 | 138 | # ---------- COINS ----------# 139 | @func_args_preprocessing 140 | def get_coins(self, **kwargs): 141 | """List all coins with data (name, price, market, developer, community, etc)""" 142 | 143 | api_url = '{0}coins'.format(self.api_base_url) 144 | # ['order', 'per_page', 'page', 'localization'] 145 | # api_url = self.__api_url_params(api_url, kwargs) 146 | 147 | return self.__request(api_url, kwargs) 148 | 149 | @func_args_preprocessing 150 | def get_coin_top_gainers_losers(self, vs_currency, **kwargs): 151 | """Get top gainers and losers""" 152 | 153 | kwargs['vs_currency'] = vs_currency 154 | 155 | api_url = '{0}coins/top_gainers_losers'.format(self.api_base_url) 156 | 157 | return self.__request(api_url, kwargs) 158 | 159 | @func_args_preprocessing 160 | def get_coins_list_new(self, **kwargs): 161 | """This endpoint allows you to query the latest 200 coins that recently listed on CoinGecko""" 162 | 163 | api_url = '{0}coins/list/new'.format(self.api_base_url) 164 | # api_url = self.__api_url_params(api_url, kwargs) 165 | 166 | return self.__request(api_url, kwargs) 167 | 168 | @func_args_preprocessing 169 | def get_coins_list(self, **kwargs): 170 | """List all supported coins id, name and symbol (no pagination required)""" 171 | 172 | api_url = '{0}coins/list'.format(self.api_base_url) 173 | # api_url = self.__api_url_params(api_url, kwargs) 174 | 175 | return self.__request(api_url, kwargs) 176 | 177 | @func_args_preprocessing 178 | def get_coins_markets(self, vs_currency, **kwargs): 179 | """List all supported coins price, market cap, volume, and market related data""" 180 | 181 | kwargs['vs_currency'] = vs_currency 182 | 183 | api_url = '{0}coins/markets'.format(self.api_base_url) 184 | # api_url = self.__api_url_params(api_url, kwargs) 185 | 186 | return self.__request(api_url, kwargs) 187 | 188 | @func_args_preprocessing 189 | def get_coin_by_id(self, id, **kwargs): 190 | """Get current data (name, price, market, ... including exchange tickers) for a coin""" 191 | 192 | api_url = '{0}coins/{1}/'.format(self.api_base_url, id) 193 | # api_url = self.__api_url_params(api_url, kwargs) 194 | 195 | return self.__request(api_url, kwargs) 196 | 197 | @func_args_preprocessing 198 | def get_coin_ticker_by_id(self, id, **kwargs): 199 | """Get coin tickers (paginated to 100 items)""" 200 | 201 | api_url = '{0}coins/{1}/tickers'.format(self.api_base_url, id) 202 | # api_url = self.__api_url_params(api_url, kwargs) 203 | 204 | return self.__request(api_url, kwargs) 205 | 206 | @func_args_preprocessing 207 | def get_coin_history_by_id(self, id, date, **kwargs): 208 | """Get historical data (name, price, market, stats) at a given date for a coin""" 209 | 210 | kwargs['date'] = date 211 | 212 | api_url = '{0}coins/{1}/history'.format(self.api_base_url, id) 213 | # api_url = self.__api_url_params(api_url, kwargs) 214 | 215 | return self.__request(api_url, kwargs) 216 | 217 | @func_args_preprocessing 218 | def get_coin_market_chart_by_id(self, id, vs_currency, days, **kwargs): 219 | """Get historical market data include price, market cap, and 24h volume (granularity auto)""" 220 | 221 | # api_url = '{0}coins/{1}/market_chart?vs_currency={2}&days={3}'.format(self.api_base_url, id, vs_currency, days) 222 | # api_url = self.__api_url_params(api_url, kwargs, api_url_has_params=True) 223 | api_url = '{0}coins/{1}/market_chart'.format(self.api_base_url, id, vs_currency, days) 224 | kwargs['vs_currency'] = vs_currency 225 | kwargs['days'] = days 226 | 227 | return self.__request(api_url, kwargs) 228 | 229 | @func_args_preprocessing 230 | def get_coin_market_chart_range_by_id(self, id, vs_currency, from_timestamp, to_timestamp, **kwargs): 231 | """Get historical market data include price, market cap, and 24h volume within a range of timestamp (granularity auto)""" 232 | 233 | # api_url = '{0}coins/{1}/market_chart/range?vs_currency={2}&from={3}&to={4}'.format(self.api_base_url, id, 234 | # vs_currency, from_timestamp, 235 | # to_timestamp) 236 | # api_url = self.__api_url_params(api_url, kwargs, api_url_has_params=True) 237 | api_url = '{0}coins/{1}/market_chart/range'.format(self.api_base_url, id) 238 | kwargs['vs_currency'] = vs_currency 239 | kwargs['from'] = from_timestamp 240 | kwargs['to'] = to_timestamp 241 | 242 | return self.__request(api_url, kwargs) 243 | 244 | # @func_args_preprocessing 245 | # def get_coin_status_updates_by_id(self, id, **kwargs): 246 | # """Get status updates for a given coin""" 247 | # 248 | # api_url = '{0}coins/{1}/status_updates'.format(self.api_base_url, id) 249 | # api_url = self.__api_url_params(api_url, kwargs) 250 | # 251 | # return self.__request(api_url) 252 | 253 | @func_args_preprocessing 254 | def get_coin_ohlc_by_id(self, id, vs_currency, days, **kwargs): 255 | """Get coin's OHLC""" 256 | 257 | # api_url = '{0}coins/{1}/ohlc?vs_currency={2}&days={3}'.format(self.api_base_url, id, vs_currency, days) 258 | # api_url = self.__api_url_params(api_url, kwargs, api_url_has_params=True) 259 | api_url = '{0}coins/{1}/ohlc'.format(self.api_base_url, id) 260 | kwargs['vs_currency'] = vs_currency 261 | kwargs['days'] = days 262 | 263 | return self.__request(api_url, kwargs) 264 | 265 | @func_args_preprocessing 266 | def get_coin_ohlc_by_id_range(self, id, vs_currency, from_timestamp, to_timestamp, interval, **kwargs): 267 | """Get coin's OHLC within a range of timestamp""" 268 | 269 | kwargs['vs_currency'] = vs_currency 270 | kwargs['from'] = from_timestamp 271 | kwargs['to'] = to_timestamp 272 | kwargs['interval'] = interval 273 | 274 | api_url = '{0}coins/{1}/ohlc/range'.format(self.api_base_url, id) 275 | # api_url = self.__api_url_params(api_url, kwargs) 276 | 277 | return self.__request(api_url, kwargs) 278 | 279 | @func_args_preprocessing 280 | def get_coin_circulating_supply_chart(self, id, days, **kwargs): 281 | """Get coin's circulating supply chart""" 282 | 283 | kwargs['days'] = days 284 | 285 | api_url = '{0}coins/{1}/circulating_supply_chart'.format(self.api_base_url, id) 286 | # api_url = self.__api_url_params(api_url, kwargs) 287 | 288 | return self.__request(api_url, kwargs) 289 | 290 | @func_args_preprocessing 291 | def get_coin_circulating_supply_chart_range(self, id, from_timestamp, to_timestamp, **kwargs): 292 | """Get coin's circulating supply chart within a range of timestamp""" 293 | 294 | kwargs['from'] = from_timestamp 295 | kwargs['to'] = to_timestamp 296 | 297 | api_url = '{0}coins/{1}/circulating_supply_chart/range'.format(self.api_base_url, id) 298 | # api_url = self.__api_url_params(api_url, kwargs) 299 | 300 | return self.__request(api_url, kwargs) 301 | 302 | @func_args_preprocessing 303 | def get_coin_total_supply_chart(self, id, days, **kwargs): 304 | """Get coin's total supply chart""" 305 | 306 | kwargs['days'] = days 307 | 308 | api_url = '{0}coins/{1}/total_supply_chart'.format(self.api_base_url, id) 309 | # api_url = self.__api_url_params(api_url, kwargs) 310 | 311 | return self.__request(api_url, kwargs) 312 | 313 | @func_args_preprocessing 314 | def get_coin_total_supply_chart_range(self, id, from_timestamp, to_timestamp, **kwargs): 315 | """Get coin's total supply chart within a range of timestamp""" 316 | 317 | kwargs['from'] = from_timestamp 318 | kwargs['to'] = to_timestamp 319 | 320 | api_url = '{0}coins/{1}/total_supply_chart/range'.format(self.api_base_url, id) 321 | # api_url = self.__api_url_params(api_url, kwargs) 322 | 323 | return self.__request(api_url, kwargs) 324 | 325 | # ---------- Contract ----------# 326 | @func_args_preprocessing 327 | def get_coin_info_from_contract_address_by_id(self, id, contract_address, **kwargs): 328 | """Get coin info from contract address""" 329 | 330 | api_url = '{0}coins/{1}/contract/{2}'.format(self.api_base_url, id, contract_address) 331 | # api_url = self.__api_url_params(api_url, kwargs) 332 | 333 | return self.__request(api_url, kwargs) 334 | 335 | @func_args_preprocessing 336 | def get_coin_market_chart_from_contract_address_by_id(self, id, contract_address, vs_currency, days, **kwargs): 337 | """Get historical market data include price, market cap, and 24h volume (granularity auto) from a contract address""" 338 | 339 | # api_url = '{0}coins/{1}/contract/{2}/market_chart/?vs_currency={3}&days={4}'.format(self.api_base_url, id, 340 | # contract_address, 341 | # vs_currency, days) 342 | # api_url = self.__api_url_params(api_url, kwargs, api_url_has_params=True) 343 | api_url = '{0}coins/{1}/contract/{2}/market_chart'.format(self.api_base_url, id, contract_address) 344 | kwargs['vs_currency'] = vs_currency 345 | kwargs['days'] = days 346 | 347 | return self.__request(api_url, kwargs) 348 | 349 | @func_args_preprocessing 350 | def get_coin_market_chart_range_from_contract_address_by_id(self, id, contract_address, vs_currency, from_timestamp, 351 | to_timestamp, **kwargs): 352 | """Get historical market data include price, market cap, and 24h volume within a range of timestamp (granularity auto) from a contract address""" 353 | 354 | # api_url = '{0}coins/{1}/contract/{2}/market_chart/range?vs_currency={3}&from={4}&to={5}'.format( 355 | # self.api_base_url, id, contract_address, vs_currency, from_timestamp, to_timestamp) 356 | # api_url = self.__api_url_params(api_url, kwargs, api_url_has_params=True) 357 | api_url = '{0}coins/{1}/contract/{2}/market_chart/range'.format(self.api_base_url, id, contract_address) 358 | kwargs['vs_currency'] = vs_currency 359 | kwargs['from'] = from_timestamp 360 | kwargs['to'] = to_timestamp 361 | 362 | return self.__request(api_url, kwargs) 363 | 364 | # ---------- ASSET PLATFORMS ----------# 365 | @func_args_preprocessing 366 | def get_asset_platforms(self, **kwargs): 367 | """List all asset platforms (Blockchain networks)""" 368 | 369 | api_url = '{0}asset_platforms'.format(self.api_base_url) 370 | # api_url = self.__api_url_params(api_url, kwargs) 371 | 372 | return self.__request(api_url, kwargs) 373 | 374 | @func_args_preprocessing 375 | def get_asset_platform_by_id(self, asset_platform_id, **kwargs): 376 | """ List all asset platforms (Blockchain networks) by platform id """ 377 | 378 | api_url = '{0}token_lists/{1}/all.json'.format(self.api_base_url, asset_platform_id) 379 | # api_url = self.__api_url_params(api_url, kwargs) 380 | 381 | return self.__request(api_url, kwargs) 382 | 383 | # ---------- CATEGORIES ----------# 384 | @func_args_preprocessing 385 | def get_coins_categories_list(self, **kwargs): 386 | """List all categories""" 387 | 388 | api_url = '{0}coins/categories/list'.format(self.api_base_url) 389 | # api_url = self.__api_url_params(api_url, kwargs) 390 | 391 | return self.__request(api_url, kwargs) 392 | 393 | @func_args_preprocessing 394 | def get_coins_categories(self, **kwargs): 395 | """List all categories with market data""" 396 | 397 | api_url = '{0}coins/categories'.format(self.api_base_url) 398 | # api_url = self.__api_url_params(api_url, kwargs) 399 | 400 | return self.__request(api_url, kwargs) 401 | 402 | # ---------- EXCHANGES ----------# 403 | @func_args_preprocessing 404 | def get_exchanges_list(self, **kwargs): 405 | """List all exchanges""" 406 | 407 | api_url = '{0}exchanges'.format(self.api_base_url) 408 | # api_url = self.__api_url_params(api_url, kwargs) 409 | 410 | return self.__request(api_url, kwargs) 411 | 412 | @func_args_preprocessing 413 | def get_exchanges_id_name_list(self, **kwargs): 414 | """List all supported markets id and name (no pagination required)""" 415 | 416 | api_url = '{0}exchanges/list'.format(self.api_base_url) 417 | # api_url = self.__api_url_params(api_url, kwargs) 418 | 419 | return self.__request(api_url, kwargs) 420 | 421 | @func_args_preprocessing 422 | def get_exchanges_by_id(self, id, **kwargs): 423 | """Get exchange volume in BTC and tickers""" 424 | 425 | api_url = '{0}exchanges/{1}'.format(self.api_base_url, id) 426 | # api_url = self.__api_url_params(api_url, kwargs) 427 | 428 | return self.__request(api_url, kwargs) 429 | 430 | @func_args_preprocessing 431 | def get_exchanges_tickers_by_id(self, id, **kwargs): 432 | """Get exchange tickers (paginated, 100 tickers per page)""" 433 | 434 | api_url = '{0}exchanges/{1}/tickers'.format(self.api_base_url, id) 435 | # api_url = self.__api_url_params(api_url, kwargs) 436 | 437 | return self.__request(api_url, kwargs) 438 | 439 | # @func_args_preprocessing 440 | # def get_exchanges_status_updates_by_id(self, id, **kwargs): 441 | # """Get status updates for a given exchange""" 442 | # 443 | # api_url = '{0}exchanges/{1}/status_updates'.format(self.api_base_url, id) 444 | # api_url = self.__api_url_params(api_url, kwargs) 445 | # 446 | # return self.__request(api_url) 447 | 448 | @func_args_preprocessing 449 | def get_exchanges_volume_chart_by_id(self, id, days, **kwargs): 450 | """Get volume chart data for a given exchange""" 451 | 452 | kwargs['days'] = days 453 | 454 | api_url = '{0}exchanges/{1}/volume_chart'.format(self.api_base_url, id) 455 | # api_url = self.__api_url_params(api_url, kwargs) 456 | 457 | return self.__request(api_url, kwargs) 458 | 459 | @func_args_preprocessing 460 | def get_exchanges_volume_chart_by_id_within_time_range(self, id, from_timestamp, to_timestamp, **kwargs): 461 | """Get volume chart data for a given exchange within a time range""" 462 | 463 | kwargs['from'] = from_timestamp 464 | kwargs['to'] = to_timestamp 465 | 466 | api_url = '{0}exchanges/{1}/volume_chart/range'.format(self.api_base_url, id) 467 | # api_url = self.__api_url_params(api_url, kwargs) 468 | 469 | return self.__request(api_url, kwargs) 470 | 471 | # # ---------- FINANCE ----------# 472 | # @func_args_preprocessing 473 | # def get_finance_platforms(self, **kwargs): 474 | # """Get cryptocurrency finance platforms data""" 475 | # 476 | # api_url = '{0}finance_platforms'.format(self.api_base_url) 477 | # api_url = self.__api_url_params(api_url, kwargs) 478 | # 479 | # return self.__request(api_url) 480 | # 481 | # @func_args_preprocessing 482 | # def get_finance_products(self, **kwargs): 483 | # """Get cryptocurrency finance products data""" 484 | # 485 | # api_url = '{0}finance_products'.format(self.api_base_url) 486 | # api_url = self.__api_url_params(api_url, kwargs) 487 | # 488 | # return self.__request(api_url) 489 | 490 | # ---------- INDEXES ----------# 491 | @func_args_preprocessing 492 | def get_indexes(self, **kwargs): 493 | """List all market indexes""" 494 | 495 | api_url = '{0}indexes'.format(self.api_base_url) 496 | # api_url = self.__api_url_params(api_url, kwargs) 497 | 498 | return self.__request(api_url, kwargs) 499 | 500 | # @func_args_preprocessing 501 | # def get_indexes_by_id(self, id, **kwargs): 502 | # """Get market index by id""" 503 | # 504 | # api_url = '{0}indexes/{1}'.format(self.api_base_url, id) 505 | # api_url = self.__api_url_params(api_url, kwargs) 506 | # 507 | # return self.__request(api_url) 508 | 509 | @func_args_preprocessing 510 | def get_indexes_by_market_id_and_index_id(self, market_id, id, **kwargs): 511 | """Get market index by market id and index id""" 512 | 513 | api_url = '{0}indexes/{1}/{2}'.format(self.api_base_url, market_id, id) 514 | # api_url = self.__api_url_params(api_url, kwargs) 515 | 516 | return self.__request(api_url, kwargs) 517 | 518 | @func_args_preprocessing 519 | def get_indexes_list(self, **kwargs): 520 | """List market indexes id and name""" 521 | 522 | api_url = '{0}indexes/list'.format(self.api_base_url) 523 | # api_url = self.__api_url_params(api_url, kwargs) 524 | 525 | return self.__request(api_url, kwargs) 526 | 527 | # ---------- DERIVATIVES ----------# 528 | @func_args_preprocessing 529 | def get_derivatives(self, **kwargs): 530 | """List all derivative tickers""" 531 | 532 | api_url = '{0}derivatives'.format(self.api_base_url) 533 | # api_url = self.__api_url_params(api_url, kwargs) 534 | 535 | return self.__request(api_url, kwargs) 536 | 537 | @func_args_preprocessing 538 | def get_derivatives_exchanges(self, **kwargs): 539 | """List all derivative tickers""" 540 | 541 | api_url = '{0}derivatives/exchanges'.format(self.api_base_url) 542 | # api_url = self.__api_url_params(api_url, kwargs) 543 | 544 | return self.__request(api_url, kwargs) 545 | 546 | @func_args_preprocessing 547 | def get_derivatives_exchanges_by_id(self, id, **kwargs): 548 | """List all derivative tickers""" 549 | 550 | api_url = '{0}derivatives/exchanges/{1}'.format(self.api_base_url, id) 551 | # api_url = self.__api_url_params(api_url, kwargs) 552 | 553 | return self.__request(api_url, kwargs) 554 | 555 | @func_args_preprocessing 556 | def get_derivatives_exchanges_list(self, **kwargs): 557 | """List all derivative tickers""" 558 | 559 | api_url = '{0}derivatives/exchanges/list'.format(self.api_base_url) 560 | # api_url = self.__api_url_params(api_url, kwargs) 561 | 562 | return self.__request(api_url, kwargs) 563 | 564 | # ---------- NFTS (BETA) ----------# 565 | @func_args_preprocessing 566 | def get_nfts_list(self, **kwargs): 567 | """List all supported NFT ids, paginated by 100 items per page, paginated to 100 items""" 568 | 569 | api_url = '{0}nfts/list'.format(self.api_base_url) 570 | # api_url = self.__api_url_params(api_url, kwargs) 571 | 572 | return self.__request(api_url, kwargs) 573 | 574 | @func_args_preprocessing 575 | def get_nfts_by_id(self, id, **kwargs): 576 | """Get current data (name, price_floor, volume_24h ...) for an NFT collection. native_currency (string) is only a representative of the currency""" 577 | 578 | api_url = '{0}nfts/{1}'.format(self.api_base_url, id) 579 | # api_url = self.__api_url_params(api_url, kwargs) 580 | 581 | return self.__request(api_url, kwargs) 582 | 583 | @func_args_preprocessing 584 | def get_nfts_by_asset_platform_id_and_contract_address(self, asset_platform_id, contract_address, **kwargs): 585 | """Get current data (name, price_floor, volume_24h ...) for an NFT collection. native_currency (string) is only a representative of the currency""" 586 | 587 | api_url = '{0}nfts/{1}/contract/{2}'.format(self.api_base_url, asset_platform_id, contract_address) 588 | # api_url = self.__api_url_params(api_url, kwargs) 589 | 590 | return self.__request(api_url, kwargs) 591 | 592 | @func_args_preprocessing 593 | def get_nfts_markets(self, **kwargs): 594 | """This endpoint allows you to query all the supported NFT collections with floor price, market cap, volume and market related data on CoinGecko""" 595 | 596 | api_url = '{0}nfts/markets'.format(self.api_base_url) 597 | # api_url = self.__api_url_params(api_url, kwargs) 598 | 599 | return self.__request(api_url, kwargs) 600 | 601 | @func_args_preprocessing 602 | def get_nfts_market_chart_by_id(self, id, days, **kwargs): 603 | """This endpoint allows you query historical market data of a NFT collection, including floor price, market cap, and 24h volume, by number of days away from now""" 604 | 605 | kwargs['days'] = days 606 | 607 | api_url = '{0}nfts/{1}/market_chart'.format(self.api_base_url, id) 608 | # api_url = self.__api_url_params(api_url, kwargs) 609 | 610 | return self.__request(api_url, kwargs) 611 | 612 | @func_args_preprocessing 613 | def get_ntfs_market_chart_by_asset_platform_id_and_contract_address(self, asset_platform_id, contract_address, days, **kwargs): 614 | """This endpoint allows you query historical market data of a NFT collection, including floor price, market cap, and 24h volume, by number of days away from now based on the provided contract address""" 615 | 616 | kwargs['days'] = days 617 | 618 | api_url = '{0}nfts/{1}/contract/{2}/market_chart'.format(self.api_base_url, asset_platform_id, contract_address) 619 | # api_url = self.__api_url_params(api_url, kwargs) 620 | 621 | return self.__request(api_url, kwargs) 622 | 623 | @func_args_preprocessing 624 | def get_nfts_tickers_by_id(self, id, **kwargs): 625 | """This endpoint allows you to query the latest floor price and 24h volume of a NFT collection, on each NFT marketplace, e.g. OpenSea and LooksRare""" 626 | 627 | api_url = '{0}nfts/{1}/tickers'.format(self.api_base_url, id) 628 | # api_url = self.__api_url_params(api_url, kwargs) 629 | 630 | return self.__request(api_url, kwargs) 631 | 632 | # # ---------- STATUS UPDATES ----------# 633 | # @func_args_preprocessing 634 | # def get_status_updates(self, **kwargs): 635 | # """List all status_updates with data (description, category, created_at, user, user_title and pin)""" 636 | # 637 | # api_url = '{0}status_updates'.format(self.api_base_url) 638 | # api_url = self.__api_url_params(api_url, kwargs) 639 | # 640 | # return self.__request(api_url) 641 | 642 | # # ---------- EVENTS ----------# 643 | # @func_args_preprocessing 644 | # def get_events(self, **kwargs): 645 | # """Get events, paginated by 100""" 646 | # 647 | # api_url = '{0}events'.format(self.api_base_url) 648 | # api_url = self.__api_url_params(api_url, kwargs) 649 | # 650 | # return self.__request(api_url) 651 | # 652 | # @func_args_preprocessing 653 | # def get_events_countries(self, **kwargs): 654 | # """Get list of event countries""" 655 | # 656 | # api_url = '{0}events/countries'.format(self.api_base_url) 657 | # api_url = self.__api_url_params(api_url, kwargs) 658 | # 659 | # return self.__request(api_url) 660 | # 661 | # @func_args_preprocessing 662 | # def get_events_types(self, **kwargs): 663 | # """Get list of event types""" 664 | # 665 | # api_url = '{0}events/types'.format(self.api_base_url) 666 | # api_url = self.__api_url_params(api_url, kwargs) 667 | # 668 | # return self.__request(api_url) 669 | 670 | # ---------- EXCHANGE-RATES ----------# 671 | @func_args_preprocessing 672 | def get_exchange_rates(self, **kwargs): 673 | """Get BTC-to-Currency exchange rates""" 674 | 675 | api_url = '{0}exchange_rates'.format(self.api_base_url) 676 | # api_url = self.__api_url_params(api_url, kwargs) 677 | 678 | return self.__request(api_url, kwargs) 679 | 680 | # ---------- SEARCH ----------# 681 | @func_args_preprocessing 682 | def search(self, query, **kwargs): 683 | """Search for coins, categories and markets on CoinGecko""" 684 | 685 | # api_url = '{0}search?query={1}'.format(self.api_base_url, query) 686 | # api_url = self.__api_url_params(api_url, kwargs, api_url_has_params=True) 687 | api_url = '{0}search'.format(self.api_base_url) 688 | kwargs['query'] = query 689 | 690 | return self.__request(api_url, kwargs) 691 | 692 | # ---------- TRENDING ----------# 693 | @func_args_preprocessing 694 | def get_search_trending(self, **kwargs): 695 | """Get top 7 trending coin searches""" 696 | 697 | api_url = '{0}search/trending'.format(self.api_base_url) 698 | # api_url = self.__api_url_params(api_url, kwargs) 699 | 700 | return self.__request(api_url, kwargs) 701 | 702 | # ---------- GLOBAL ----------# 703 | @func_args_preprocessing 704 | def get_global(self, **kwargs): 705 | """Get cryptocurrency global data""" 706 | 707 | api_url = '{0}global'.format(self.api_base_url) 708 | # api_url = self.__api_url_params(api_url, kwargs) 709 | 710 | return self.__request(api_url, kwargs)['data'] 711 | 712 | @func_args_preprocessing 713 | def get_global_decentralized_finance_defi(self, **kwargs): 714 | """Get cryptocurrency global decentralized finance(defi) data""" 715 | 716 | api_url = '{0}global/decentralized_finance_defi'.format(self.api_base_url) 717 | # api_url = self.__api_url_params(api_url, kwargs) 718 | 719 | return self.__request(api_url, kwargs)['data'] 720 | 721 | @func_args_preprocessing 722 | def get_global_market_cap_chart(self, days, **kwargs): 723 | """Get cryptocurrency global market cap chart data""" 724 | 725 | kwargs['days'] = days 726 | 727 | api_url = '{0}global/market_cap_chart'.format(self.api_base_url) 728 | # api_url = self.__api_url_params(api_url, kwargs) 729 | 730 | return self.__request(api_url, kwargs) 731 | 732 | # ---------- COMPANIES ----------# 733 | @func_args_preprocessing 734 | def get_companies_public_treasury_by_coin_id(self, coin_id, **kwargs): 735 | """Get public companies data""" 736 | 737 | api_url = '{0}companies/public_treasury/{1}'.format(self.api_base_url, coin_id) 738 | # api_url = self.__api_url_params(api_url, kwargs) 739 | 740 | return self.__request(api_url, kwargs) 741 | -------------------------------------------------------------------------------- /pycoingecko/utils.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | 3 | 4 | def func_args_preprocessing(func): 5 | """Return function that converts list input arguments to comma-separated strings""" 6 | 7 | @wraps(func) 8 | def input_args(*args, **kwargs): 9 | 10 | # check in **kwargs for lists and booleans 11 | for v in kwargs: 12 | kwargs[v] = arg_preprocessing(kwargs[v]) 13 | # check in *args for lists and booleans 14 | args = [arg_preprocessing(v) for v in args] 15 | 16 | return func(*args, **kwargs) 17 | 18 | return input_args 19 | 20 | 21 | def arg_preprocessing(arg_v): 22 | """Return the values of an argument after preprocessing""" 23 | 24 | # check if arg is list and convert it to comma-separated string 25 | if isinstance(arg_v, list): 26 | arg_v = ','.join(arg_v) 27 | # check if arg is boolean and convert it to string 28 | elif isinstance(arg_v, bool): 29 | arg_v = str(arg_v).lower() 30 | 31 | return arg_v 32 | 33 | 34 | def get_comma_separated_values(values): 35 | """Return the values as a comma-separated string""" 36 | 37 | # Make sure values is a list or tuple 38 | if not isinstance(values, list) and not isinstance(values, tuple): 39 | values = [values] 40 | 41 | return ','.join(values) 42 | 43 | -------------------------------------------------------------------------------- /pycoingecko/version.py: -------------------------------------------------------------------------------- 1 | __version__ = '3.2.0' -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # from distutils.core import setup 2 | import setuptools 3 | 4 | version = {} 5 | exec(open('./pycoingecko/version.py').read(), version) 6 | # print(version['__version__']) 7 | 8 | setuptools.setup( 9 | name='pycoingecko', 10 | version=version['__version__'], 11 | packages=['pycoingecko', ], 12 | license='MIT', 13 | description='Python wrapper around the CoinGecko API', 14 | long_description=open('README.md').read(), 15 | long_description_content_type="text/markdown", 16 | author='Christoforou Manolis', 17 | author_email='emchristoforou@gmail.com', 18 | install_requires=['requests'], 19 | url='https://github.com/man-c/pycoingecko', 20 | classifiers=[ 21 | "Programming Language :: Python :: 3", 22 | "Programming Language :: Python :: 2", 23 | "License :: OSI Approved :: MIT License", 24 | "Operating System :: OS Independent", 25 | ], 26 | ) 27 | -------------------------------------------------------------------------------- /tests/test_api.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import requests.exceptions 3 | import responses 4 | import unittest 5 | import unittest.mock as mock 6 | 7 | from pycoingecko import CoinGeckoAPI 8 | from requests.exceptions import HTTPError 9 | 10 | 11 | class TestWrapper(unittest.TestCase): 12 | 13 | @responses.activate 14 | def test_connection_error(self): 15 | with pytest.raises(requests.exceptions.ConnectionError): 16 | CoinGeckoAPI().ping() 17 | 18 | @responses.activate 19 | def test_failed_ping(self): 20 | # Arrange 21 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/ping', 22 | status = 404) 23 | exception = HTTPError("HTTP Error") 24 | 25 | # Act Assert 26 | with pytest.raises(HTTPError) as HE: 27 | CoinGeckoAPI().ping() 28 | 29 | @responses.activate 30 | def test_ping(self): 31 | # Arrange 32 | ping_json = { 'gecko_says':'(V3) To the Moon!' } 33 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/ping', 34 | json = ping_json, status = 200) 35 | 36 | # Act 37 | response = CoinGeckoAPI().ping() 38 | 39 | ## Assert 40 | assert response == ping_json 41 | 42 | 43 | #---------- SIMPLE ----------# 44 | 45 | #---------- /simple/price ----------# 46 | @responses.activate 47 | def test_get_price(self): 48 | # Arrange 49 | coins_json_sample = {"bitcoin": {"usd": 7984.89}} 50 | 51 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd', 52 | json = coins_json_sample, status = 200) 53 | 54 | # Act 55 | response = CoinGeckoAPI().get_price('bitcoin', 'usd') 56 | 57 | ## Assert 58 | assert response == coins_json_sample 59 | 60 | @responses.activate 61 | def test_failed_get_price(self): 62 | # Arrange 63 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd', 64 | status = 404) 65 | exception = HTTPError("HTTP Error") 66 | 67 | # Act Assert 68 | with pytest.raises(HTTPError) as HE: 69 | CoinGeckoAPI().get_price('bitcoin', 'usd') 70 | 71 | #---------- /simple/token_price/{id} ----------# 72 | @responses.activate 73 | def test_get_token_price(self): 74 | # Arrange 75 | coins_json_sample = {'0xB8c77482e45F1F44dE1745F52C74426C631bDD52': {'bnb': 1.0, 'bnb_market_cap': 144443301.0, 'bnb_24h_vol': 17983938.686249834, 'last_updated_at': 1558704332}} 76 | 77 | 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', 78 | json = coins_json_sample, status = 200) 79 | 80 | # Act 81 | response = CoinGeckoAPI().get_token_price('ethereum', '0xB8c77482e45F1F44dE1745F52C74426C631bDD52', 'bnb', include_market_cap='true', include_24hr_vol='true', include_last_updated_at='true') 82 | 83 | ## Assert 84 | assert response == coins_json_sample 85 | 86 | @responses.activate 87 | def test_failed_get_token_price(self): 88 | # Arrange 89 | 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', 90 | status = 404) 91 | exception = HTTPError("HTTP Error") 92 | 93 | # Act Assert 94 | with pytest.raises(HTTPError) as HE: 95 | CoinGeckoAPI().get_token_price('ethereum', '0xB8c77482e45F1F44dE1745F52C74426C631bDD52', 'bnb', include_market_cap='true', include_24hr_vol='true', include_last_updated_at='true') 96 | 97 | #---------- /simple/supported_vs_currencies ----------# 98 | @responses.activate 99 | def test_get_supported_vs_currencies(self): 100 | # Arrange 101 | 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'] 102 | 103 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/simple/supported_vs_currencies', 104 | json = coins_json_sample, status = 200) 105 | 106 | # Act 107 | response = CoinGeckoAPI().get_supported_vs_currencies() 108 | 109 | ## Assert 110 | assert response == coins_json_sample 111 | 112 | @responses.activate 113 | def test_failed_get_supported_vs_currencies(self): 114 | # Arrange 115 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/simple/supported_vs_currencies', 116 | status = 404) 117 | exception = HTTPError("HTTP Error") 118 | 119 | # Act Assert 120 | with pytest.raises(HTTPError) as HE: 121 | CoinGeckoAPI().get_supported_vs_currencies() 122 | 123 | 124 | #---------- /simple/supported_vs_currencies ----------# 125 | @responses.activate 126 | def test_get_supported_vs_currencies(self): 127 | # Arrange 128 | 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'] 129 | 130 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/simple/supported_vs_currencies', 131 | json = coins_json_sample, status = 200) 132 | 133 | # Act 134 | response = CoinGeckoAPI().get_supported_vs_currencies() 135 | 136 | ## Assert 137 | assert response == coins_json_sample 138 | 139 | @responses.activate 140 | def test_failed_get_supported_vs_currencies(self): 141 | # Arrange 142 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/simple/supported_vs_currencies', 143 | status = 404) 144 | exception = HTTPError("HTTP Error") 145 | 146 | # Act Assert 147 | with pytest.raises(HTTPError) as HE: 148 | CoinGeckoAPI().get_supported_vs_currencies() 149 | 150 | 151 | #---------- COINS ----------# 152 | 153 | #---------- /price/coins ----------# 154 | @responses.activate 155 | def test_failed_get_coins(self): 156 | # Arrange 157 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins', 158 | status = 404) 159 | exception = HTTPError("HTTP Error") 160 | 161 | # Act Assert 162 | with pytest.raises(HTTPError) as HE: 163 | CoinGeckoAPI().get_coins() 164 | 165 | @responses.activate 166 | def test_get_coins(self): 167 | # Arrange 168 | coins_json_sample = [ { "id": "bitcoin", "symbol": "btc", "name": "Bitcoin", "localization": { "en": "Bitcoin", "es": "Bitcoin", "de": "Bitcoin", "nl": "Bitcoin", "pt": "Bitcoin", "fr": "Bitcoin", "it": "Bitcoin", "hu": "Bitcoin", "ro": "Bitcoin", "sv": "Bitcoin", "pl": "Bitcoin", "id": "Bitcoin", "zh": "Bitcoin", "zh-tw": "Bitcoin", "ja": "Bitcoin", "ko": "Bitcoin", "ru": "Bitcoin", "ar": "Bitcoin", "th": "Bitcoin", "vi": "Bitcoin", "tr": "Bitcoin" }, "image": { "thumb": "https://assets.coingecko.com/coins/images/1/thumb/bitcoin.png?1510040391", "small": "https://assets.coingecko.com/coins/images/1/small/bitcoin.png?1510040391", "large": "https://assets.coingecko.com/coins/images/1/large/bitcoin.png?1510040391" } } ] 169 | 170 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins', 171 | json = coins_json_sample, status = 200) 172 | 173 | # Act 174 | response = CoinGeckoAPI().get_coins() 175 | 176 | ## Assert 177 | assert response == coins_json_sample 178 | 179 | 180 | #---------- /price/coins/list ----------# 181 | @responses.activate 182 | def test_failed_get_coins_list(self): 183 | # Arrange 184 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/list', 185 | status = 404) 186 | exception = HTTPError("HTTP Error") 187 | 188 | # Act 189 | with pytest.raises(HTTPError) as HE: 190 | CoinGeckoAPI().get_coins_list() 191 | 192 | @responses.activate 193 | def test_get_coins_list(self): 194 | # Arrange 195 | coins_json_sample = [ { "id": "bitcoin", "symbol": "btc", "name": "Bitcoin" }, { "id": "litecoin", "symbol": "ltc", "name": "Litecoin" }, { "id": "auroracoin", "symbol": "aur", "name": "Auroracoin" }, { "id": "peercoin", "symbol": "ppc", "name": "Peercoin" }, { "id": "dogecoin", "symbol": "doge", "name": "Dogecoin" }, { "id": "nxt", "symbol": "nxt", "name": "NXT" }, { "id": "omni", "symbol": "omni", "name": "Omni (Mastercoin)" } ] 196 | 197 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/list', 198 | json = coins_json_sample, status = 200) 199 | 200 | # Act 201 | response = CoinGeckoAPI().get_coins_list() 202 | 203 | ## Assert 204 | assert response == coins_json_sample 205 | 206 | 207 | #---------- /price/coins/markets ----------# 208 | @responses.activate 209 | def test_failed_get_coins_markets(self): 210 | # Arrange 211 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd', 212 | status = 404) 213 | exception = HTTPError("HTTP Error") 214 | 215 | # Act Assert 216 | with pytest.raises(HTTPError) as HE: 217 | CoinGeckoAPI().get_coins_markets('usd') 218 | 219 | @responses.activate 220 | def test_get_coins_markets(self): 221 | # Arrange 222 | markets_json_sample = [ { "id": "bitcoin", "symbol": "btc", "name": "Bitcoin", "image": "https://assets.coingecko.com/coins/images/1/large/bitcoin.png?1510040391", "current_price": 7015.11823787848, "market_cap": 120934444800.105, "market_cap_rank": 1, "total_volume": 6121170828.21792, "high_24h": 7054.21193531031, "low_24h": 6668.29100755648, "price_change_24h": "299.72373285508", "price_change_percentage_24h": "4.46323343521924", "market_cap_change_24h": "5197755386.983", "market_cap_change_percentage_24h": "4.4910178555649", "circulating_supply": "17236100.0", "ath": 19665.3949272416, "ath_change_percentage": -64.2200698307594, "ath_date": "2017-12-16T00:00:00.000Z", "roi": 0, "last_updated": "2018-08-28T12:12:53.390Z" } ] 223 | 224 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd', 225 | json = markets_json_sample, status = 200) 226 | 227 | # Act 228 | response = CoinGeckoAPI().get_coins_markets('usd') 229 | 230 | ## Assert 231 | assert response == markets_json_sample 232 | 233 | 234 | #---------- /price/coins/{id} ----------# 235 | @responses.activate 236 | def test_failed_get_coin_by_id(self): 237 | # Arrange 238 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/bitcoin/', 239 | status = 404) 240 | exception = HTTPError("HTTP Error") 241 | 242 | # Act Assert 243 | with pytest.raises(HTTPError) as HE: 244 | CoinGeckoAPI().get_coin_by_id('bitcoin') 245 | 246 | 247 | @responses.activate 248 | def test_get_coin_by_id(self): 249 | # Arrange 250 | bitcoin_json_sample = { "id": "bitcoin", "symbol": "btc", "name": "Bitcoin", "categories": [ "Cryptocurrency" ], "localization": { "en": "Bitcoin", "es": "Bitcoin", "de": "Bitcoin", "nl": "Bitcoin", "pt": "Bitcoin", "fr": "Bitcoin", "it": "Bitcoin", "hu": "Bitcoin", "ro": "Bitcoin", "sv": "Bitcoin", "pl": "Bitcoin", "id": "Bitcoin", "zh": "比特币", "zh-tw": "比特幣", "ja": "ビットコイン", "ko": "비트코인", "ru": "биткоина", "ar": "بيتكوين", "th": "บิตคอยน์", "vi": "Bitcoin", "tr": "Bitcoin"}} 251 | 252 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/bitcoin/', 253 | json = bitcoin_json_sample, status = 200) 254 | 255 | # Act 256 | response = CoinGeckoAPI().get_coin_by_id('bitcoin') 257 | 258 | ## Assert 259 | assert response == bitcoin_json_sample 260 | 261 | 262 | #---------- /price/coins/{id}/tickers ----------# 263 | @responses.activate 264 | def test_failed_get_coin_ticker_by_id(self): 265 | # Arrange 266 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/bitcoin/tickers', 267 | status = 404) 268 | exception = HTTPError("HTTP Error") 269 | 270 | # Act Assert 271 | with pytest.raises(HTTPError) as HE: 272 | CoinGeckoAPI().get_coin_ticker_by_id('bitcoin') 273 | 274 | 275 | @responses.activate 276 | def test_get_get_coin_ticker_by_id(self): 277 | # Arrange 278 | 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'}]} 279 | 280 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/bitcoin/tickers', 281 | json = bitcoin_json_sample, status = 200) 282 | 283 | # Act 284 | response = CoinGeckoAPI().get_coin_ticker_by_id('bitcoin') 285 | 286 | ## Assert 287 | assert response == bitcoin_json_sample 288 | 289 | 290 | #---------- /price/coins/{id}/history ----------# 291 | @responses.activate 292 | def test_failed_get_coin_history_by_id(self): 293 | # Arrange 294 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/bitcoin/history?date=27-08-2018', 295 | status = 404) 296 | exception = HTTPError("HTTP Error") 297 | 298 | # Act Assert 299 | with pytest.raises(HTTPError) as HE: 300 | CoinGeckoAPI().get_coin_history_by_id('bitcoin', '27-08-2018') 301 | 302 | 303 | @responses.activate 304 | def test_get_coin_history_by_id(self): 305 | # Arrange 306 | history_json_sample = { "id": "bitcoin", "symbol": "btc", "name": "Bitcoin", "localization": { "en": "Bitcoin", "es": "Bitcoin", "de": "Bitcoin", "nl": "Bitcoin", "pt": "Bitcoin", "fr": "Bitcoin", "it": "Bitcoin", "hu": "Bitcoin", "ro": "Bitcoin", "sv": "Bitcoin", "pl": "Bitcoin", "id": "Bitcoin", "zh": "比特币", "zh-tw": "比特幣", "ja": "ビットコイン", "ko": "비트코인", "ru": "биткоина", "ar": "بيتكوين", "th": "บิตคอยน์", "vi": "Bitcoin", "tr": "Bitcoin" } } 307 | 308 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/bitcoin/history?date=27-08-2018', 309 | json = history_json_sample, status = 200) 310 | 311 | # Act 312 | response = CoinGeckoAPI().get_coin_history_by_id('bitcoin', '27-08-2018') 313 | 314 | ## Assert 315 | assert response == history_json_sample 316 | 317 | 318 | #---------- /price/coins/{id}/market_chart ----------# 319 | @responses.activate 320 | def test_failed_get_coin_market_chart_by_id(self): 321 | # Arrange 322 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/bitcoin/market_chart?vs_currency=usd&days=1', 323 | status = 404) 324 | exception = HTTPError("HTTP Error") 325 | 326 | # Act Assert 327 | with pytest.raises(HTTPError) as HE: 328 | CoinGeckoAPI().get_coin_market_chart_by_id('bitcoin', 'usd', 1) 329 | 330 | 331 | @responses.activate 332 | def test_get_coin_market_chart_by_id(self): 333 | # Arrange 334 | json_response = { "prices": [ [ 1535373899623, 6756.942910425894 ], [ 1535374183927, 6696.894541693875 ], [ 1535374496401, 6689.990513793263 ], [ 1535374779118, 6668.291007556478 ], [ 1535375102688, 6703.7499879964 ], [ 1535375384209, 6706.898948451269 ] ] } 335 | 336 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/bitcoin/market_chart?vs_currency=usd&days=1', 337 | json = json_response, status = 200) 338 | 339 | # Act 340 | response = CoinGeckoAPI().get_coin_market_chart_by_id('bitcoin', 'usd', 1) 341 | 342 | ## Assert 343 | assert response == json_response 344 | 345 | 346 | #---------- /price/coins/{id}/status_updates ----------# 347 | # @responses.activate 348 | # def test_failed_get_coin_status_updates_by_id(self): 349 | # # Arrange 350 | # responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/litecoin/status_updates', 351 | # status = 404) 352 | # exception = HTTPError("HTTP Error") 353 | # 354 | # # Act Assert 355 | # with pytest.raises(HTTPError) as HE: 356 | # CoinGeckoAPI().get_coin_status_updates_by_id('litecoin') 357 | # 358 | # 359 | # @responses.activate 360 | # def test_get_coin_status_updates_by_id(self): 361 | # # Arrange 362 | # 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'}}} ] 363 | # 364 | # responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/litecoin/status_updates', 365 | # json = json_response, status = 200) 366 | # 367 | # # Act 368 | # response = CoinGeckoAPI().get_coin_status_updates_by_id('litecoin') 369 | # 370 | # ## Assert 371 | # assert response == json_response 372 | 373 | 374 | #---------- /price/coins/{id}/contract/{contract_address} ----------# 375 | @responses.activate 376 | def test_failed_get_coin_info_from_contract_address_by_id(self): 377 | # Arrange 378 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/ethereum/contract/0x0D8775F648430679A709E98d2b0Cb6250d2887EF', 379 | status = 404) 380 | exception = HTTPError("HTTP Error") 381 | 382 | # Act Assert 383 | with pytest.raises(HTTPError) as HE: 384 | CoinGeckoAPI().get_coin_info_from_contract_address_by_id(id='ethereum',contract_address='0x0D8775F648430679A709E98d2b0Cb6250d2887EF') 385 | 386 | 387 | @responses.activate 388 | def test_get_coin_info_from_contract_address_by_id(self): 389 | # Arrange 390 | 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'}} 391 | 392 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/coins/ethereum/contract/0x0D8775F648430679A709E98d2b0Cb6250d2887EF', 393 | json = json_response, status = 200) 394 | 395 | # Act 396 | response = CoinGeckoAPI().get_coin_info_from_contract_address_by_id(id='ethereum',contract_address='0x0D8775F648430679A709E98d2b0Cb6250d2887EF') 397 | 398 | ## Assert 399 | assert response == json_response 400 | 401 | 402 | #---------- EXCHANGES ----------# 403 | 404 | 405 | #---------- /exchanges ----------# 406 | @responses.activate 407 | def test_failed_get_exchanges_list(self): 408 | # Arrange 409 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/exchanges', 410 | status = 404) 411 | exception = HTTPError("HTTP Error") 412 | 413 | # Act Assert 414 | with pytest.raises(HTTPError) as HE: 415 | CoinGeckoAPI().get_exchanges_list() 416 | 417 | 418 | @responses.activate 419 | def test_get_exchanges_list(self): 420 | # Arrange 421 | json_response = [ { "id": "bitforex", "name": "Bitforex", "description": "", "url": "https://www.bitforex.com/", "image": "https://assets.coingecko.com/markets/images/214/small/bitforex.jpg?1533199114", "has_trading_incentive": "true", "trade_volume_24h_btc": 680266.637119918 }, { "id": "binance", "name": "Binance", "description": "Binance is a China-based cryptocurrency exchange that lists most of the Chinese coins. It is a popular exchange for its huge number of Initial Coin Offering (ICO) listings and low fees.", "url": "https://www.binance.com/", "image": "https://assets.coingecko.com/markets/images/52/small/binance.jpg?1519353250", "has_trading_incentive": "false", "trade_volume_24h_btc": 189744.350072168 } ] 422 | 423 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/exchanges', 424 | json = json_response, status = 200) 425 | 426 | # Act 427 | response = CoinGeckoAPI().get_exchanges_list() 428 | 429 | ## Assert 430 | assert response == json_response 431 | 432 | 433 | #---------- /exchanges/list ----------# 434 | @responses.activate 435 | def test_failed_get_exchanges_id_name_list(self): 436 | # Arrange 437 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/exchanges/list', 438 | status = 404) 439 | exception = HTTPError("HTTP Error") 440 | 441 | # Act Assert 442 | with pytest.raises(HTTPError) as HE: 443 | CoinGeckoAPI().get_exchanges_id_name_list() 444 | 445 | 446 | @responses.activate 447 | def test_get_exchanges_id_name_list(self): 448 | # Arrange 449 | json_response = [{'id': 'abcc', 'name': 'ABCC'}, {'id': 'acx', 'name': 'ACX'}, {'id': 'airswap', 'name': 'AirSwap'}] 450 | 451 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/exchanges/list', 452 | json = json_response, status = 200) 453 | 454 | # Act 455 | response = CoinGeckoAPI().get_exchanges_id_name_list() 456 | 457 | ## Assert 458 | assert response == json_response 459 | 460 | 461 | 462 | #---------- /exchanges/{id} ----------# 463 | @responses.activate 464 | def test_failed_get_exchanges_by_id(self): 465 | # Arrange 466 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/exchanges/bitforex', 467 | status = 404) 468 | exception = HTTPError("HTTP Error") 469 | 470 | # Act Assert 471 | with pytest.raises(HTTPError) as HE: 472 | CoinGeckoAPI().get_exchanges_by_id('bitforex') 473 | 474 | 475 | @responses.activate 476 | def test_get_exchanges_by_id(self): 477 | # Arrange 478 | json_response = { "name": "Bitforex", "has_trading_incentive": "true", "trade_volume_24h_btc": 680266.637119918, "tickers": [ { "base": "BTC", "target": "USDT", "market": { "name": "Bitforex", "identifier": "bitforex", "has_trading_incentive": "true" }, "last": 7039.55, "converted_last": { "btc": "1.001711841446200081963480716", "eth": "24.4986463149997536428213651518458101194944", "usd": "7043.71831205846008527901735024184383795812" }, "volume": 447378.73, "converted_volume": { "btc": "448144.5713519911718500979009072226084", "eth": "10960173.27267390510353832059421689917189597190216256", "usd": "3151209752.222085727501972469271259554059845134991788" }, "timestamp": "2018-08-28T12:46:25.719Z", "is_anomaly": "false" } ] } 479 | 480 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/exchanges/bitforex', 481 | json = json_response, status = 200) 482 | 483 | # Act 484 | response = CoinGeckoAPI().get_exchanges_by_id('bitforex') 485 | 486 | ## Assert 487 | assert response == json_response 488 | 489 | 490 | #---------- EXCHANGE RATES ----------# 491 | 492 | #---------- /exchange_rates ----------# 493 | @responses.activate 494 | def test_failed_get_exchange_rates(self): 495 | # Arrange 496 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/exchange_rates', 497 | status = 404) 498 | exception = HTTPError("HTTP Error") 499 | 500 | # Act Assert 501 | with pytest.raises(HTTPError) as HE: 502 | CoinGeckoAPI().get_exchange_rates() 503 | 504 | 505 | @responses.activate 506 | def test_get_exchange_rates(self): 507 | # Arrange 508 | json_response = { "rates": { "btc": { "name": "Bitcoin", "unit": "Ƀ", "value": 0, "type": "crypto" }, "eth": { "name": "Ether", "unit": "Ξ", "value": 24.451, "type": "crypto" }, "usd": { "name": "US Dollar", "unit": "$", "value": 7040.152, "type": "fiat" } } } 509 | 510 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/exchange_rates', 511 | json = json_response, status = 200) 512 | 513 | # Act 514 | response = CoinGeckoAPI().get_exchange_rates() 515 | 516 | ## Assert 517 | assert response == json_response 518 | 519 | #---------- TRENDING ----------# 520 | 521 | #---------- /search/trending ----------# 522 | @responses.activate 523 | def test_failed_search_get_trending(self): 524 | # Arrange 525 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/search/trending', 526 | status = 404) 527 | exception = HTTPError("HTTP Error") 528 | 529 | # Act Assert 530 | with pytest.raises(HTTPError) as HE: 531 | CoinGeckoAPI().get_search_trending() 532 | 533 | 534 | @responses.activate 535 | def test_get_search_trending(self): 536 | # Arrange 537 | json_response = { "coins": [{"item": {"id":"iris-network", "name":"IRISnet", "symbol":"IRIS", "market_cap_rank":159, "thumb":"/coins/images/5135/thumb/IRIS.png", "score":0}}, {"item": {"id":"hegic", "name":"Hegic", "symbol":"HEGIC", "market_cap_rank":386, "thumb":"/coins/images/12454/thumb/Hegic.png", "score":1}}, {"item": {"id":"moonswap", "name":"MoonSwap", "symbol":"MOON", "market_cap_rank":373, "thumb":"/coins/images/12441/thumb/moon.jpg", "score":2}}, {"item": {"id":"yfv-finance", "name":"YFValue", "symbol":"YFV", "market_cap_rank":179, "thumb":"/coins/images/12198/thumb/yfv.jpg", "score":3}}, {"item": {"id":"yffi-finance", "name":"yffi finance", "symbol":"YFFI", "market_cap_rank":531, "thumb":"/coins/images/11940/thumb/yffi-finance.jpg", "score":4}}, {"item": {"id":"relevant", "name":"Relevant", "symbol":"REL", "market_cap_rank":915, "thumb":"/coins/images/11586/thumb/Relevant.png", "score":5}}, {"item": {"id":"sake-token", "name":"SakeToken", "symbol":"SAKE", "market_cap_rank":503, "thumb":"/coins/images/12428/thumb/sake.png", "score":6}}], "exchanges": [] } 538 | 539 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/search/trending', 540 | json = json_response, status = 200) 541 | 542 | # Act 543 | response = CoinGeckoAPI().get_search_trending() 544 | 545 | ## Assert 546 | assert response == json_response 547 | 548 | #---------- GLOBAL ----------# 549 | 550 | #---------- /global ----------# 551 | @responses.activate 552 | def test_failed_get_global(self): 553 | # Arrange 554 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/global', 555 | status = 404) 556 | exception = HTTPError("HTTP Error") 557 | 558 | # Act Assert 559 | with pytest.raises(HTTPError) as HE: 560 | CoinGeckoAPI().get_global() 561 | 562 | 563 | @responses.activate 564 | def test_get_global(self): 565 | # Arrange 566 | json_response = { "data": { "active_cryptocurrencies": 2517, "upcoming_icos": 360, "ongoing_icos": 423, "ended_icos": 2037, "markets": 197 } } 567 | 568 | responses.add(responses.GET, 'https://api.coingecko.com/api/v3/global', 569 | json = json_response, status = 200) 570 | 571 | # Act 572 | response = CoinGeckoAPI().get_global() 573 | 574 | ## Assert 575 | expected_response = { "active_cryptocurrencies": 2517, "upcoming_icos": 360, "ongoing_icos": 423, "ended_icos": 2037, "markets": 197 } 576 | assert response == expected_response 577 | 578 | 579 | 580 | # #---------- FINANCE ----------# 581 | # 582 | # #---------- /finance_platforms ----------# 583 | # 584 | # @responses.activate 585 | # def test_failed_get_finance_platforms(self): 586 | # # Arrange 587 | # responses.add(responses.GET, 'https://api.coingecko.com/api/v3/finance_platforms', 588 | # status = 404) 589 | # exception = HTTPError("HTTP Error") 590 | # 591 | # # Act Assert 592 | # with pytest.raises(HTTPError) as HE: 593 | # CoinGeckoAPI().get_finance_platforms() 594 | # 595 | # @responses.activate 596 | # def test_get_finance_platforms(self): 597 | # # Arrange 598 | # 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/"}] 599 | # 600 | # responses.add(responses.GET, 'https://api.coingecko.com/api/v3/finance_platforms', 601 | # json = json_response, status = 200) 602 | # 603 | # # Act 604 | # response = CoinGeckoAPI().get_finance_platforms() 605 | # 606 | # ## Assert 607 | # 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/"}] 608 | # assert response == expected_response 609 | # 610 | # #---------- /finance_products ----------# 611 | # 612 | # @responses.activate 613 | # def test_failed_get_finance_products(self): 614 | # # Arrange 615 | # responses.add(responses.GET, 'https://api.coingecko.com/api/v3/finance_products', 616 | # status = 404) 617 | # exception = HTTPError("HTTP Error") 618 | # 619 | # # Act Assert 620 | # with pytest.raises(HTTPError) as HE: 621 | # CoinGeckoAPI().get_finance_products() 622 | # 623 | # @responses.activate 624 | # def test_get_finance_products(self): 625 | # # Arrange 626 | # 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/"}] 627 | # 628 | # responses.add(responses.GET, 'https://api.coingecko.com/api/v3/finance_platforms', 629 | # json = json_response, status = 200) 630 | # 631 | # # Act 632 | # response = CoinGeckoAPI().get_finance_platforms() 633 | # 634 | # ## Assert 635 | # 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/"}] 636 | # assert response == expected_response 637 | --------------------------------------------------------------------------------