├── .gitignore ├── LICENSE ├── README.md ├── setup.py ├── src └── pythonpancakes │ ├── __init__.py │ └── api.py └── tests └── test_api_unittest.py /.gitignore: -------------------------------------------------------------------------------- 1 | /venv/ 2 | /.idea/ 3 | /build/ 4 | /dist/ 5 | /*.egg-info/ 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Scott Burlovich 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # THIS MODULE IS DEPRECATED 2 | 11/20/2022: Pancakeswap has recently discontinued their info API.. this module will no longer be maintained. 3 | 4 | --- 5 | 6 | # 🐍 Python Pancakes 🥞 7 | A simple request wrapper for the Pancake-Swap API. 8 | 9 | ## Installation 10 | Install package 11 | ```bash 12 | # Using pip 13 | $ pip install pythonpancakes 14 | 15 | # Or from source 16 | $ git clone https://github.com/scottburlovich/pythonpancakes.git pythonpancakes 17 | $ cd pythonpancakes 18 | $ python3 setup.py install 19 | ``` 20 | 21 | Import module into your project and initialize API class 22 | ```python 23 | from pythonpancakes import PancakeSwapAPI 24 | ps = PancakeSwapAPI() 25 | ``` 26 | 27 | ## Usage 28 | Please note, the API functionality currently exposed by PancakeSwap is quite basic. This package will be updated 29 | as they add new functionality. 30 | 31 | ## `summary()` 32 | Returns a dictionary containing data for the top ~1000 PancakeSwap pairs, sorted by reserves. 33 | 34 | Example invocation: 35 | ```python 36 | summary = ps.summary() 37 | ``` 38 | Example output: 39 | ```python 40 | # output: 41 | { 42 | "updated_at": 1234567, // UNIX timestamp 43 | "data": { 44 | "0x..._0x...": { // BEP20 token addresses, joined by an underscore 45 | "price": "...", // price denominated in token1/token0 46 | "base_volume": "...", // last 24h volume denominated in token0 47 | "quote_volume": "...", // last 24h volume denominated in token1 48 | "liquidity": "...", // liquidity denominated in USD 49 | "liquidity_BNB": "..." // liquidity denominated in BNB 50 | }, 51 | // ... 52 | } 53 | } 54 | ``` 55 | --- 56 | ## `tokens(address)` 57 | If address parameter is specified, returns the token information, based on address. Otherwise, 58 | returns the tokens in the top ~1000 pairs on PancakeSwap, sorted by reserves. 59 | 60 | Example invocation without address: 61 | ```python 62 | tokens = ps.tokens() 63 | ``` 64 | Example output without address: 65 | ```python 66 | { 67 | "updated_at": 1234567, // UNIX timestamp 68 | "data": { 69 | "0x...": { // the address of the BEP20 token 70 | "name": "...", // not necessarily included for BEP20 tokens 71 | "symbol": "...", // not necessarily included for BEP20 tokens 72 | "price": "...", // price denominated in USD 73 | "price_BNB": "...", // price denominated in BNB 74 | }, 75 | // ... 76 | } 77 | } 78 | ``` 79 | Example invocation with address: 80 | ```python 81 | token = ps.tokens('0x00000000000...') 82 | ``` 83 | Example output with address: 84 | ```python 85 | # output 86 | { 87 | "updated_at": 1234567, // UNIX timestamp 88 | "data": { 89 | "name": "...", // not necessarily included for BEP20 tokens 90 | "symbol": "...", // not necessarily included for BEP20 tokens 91 | "price": "...", // price denominated in USD 92 | "price_BNB": "...", // price denominated in BNB 93 | } 94 | } 95 | ``` 96 | --- 97 | ## `pairs()` 98 | Returns data for the top ~1000 PancakeSwap pairs, sorted by reserves. 99 | 100 | Example invocation: 101 | ```python 102 | pairs = ps.pairs() 103 | ``` 104 | Example output 105 | ```python 106 | { 107 | "updated_at": 1234567, // UNIX timestamp 108 | "data": { 109 | "0x..._0x...": { // the asset ids of BNB and BEP20 tokens, joined by an underscore 110 | "pair_address": "0x...", // pair address 111 | "base_name": "...", // token0 name 112 | "base_symbol": "...", // token0 symbol 113 | "base_address": "0x...", // token0 address 114 | "quote_name": "...", // token1 name 115 | "quote_symbol": "...", // token1 symbol 116 | "quote_address": "0x...", // token1 address 117 | "price": "...", // price denominated in token1/token0 118 | "base_volume": "...", // volume denominated in token0 119 | "quote_volume": "...", // volume denominated in token1 120 | "liquidity": "...", // liquidity denominated in USD 121 | "liquidity_BNB": "..." // liquidity denominated in BNB 122 | }, 123 | // ... 124 | } 125 | } 126 | ``` 127 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | from setuptools import setup 3 | 4 | # The directory containing this file 5 | HERE = pathlib.Path(__file__).parent 6 | 7 | # The text of the README file 8 | README = (HERE / "README.md").read_text() 9 | 10 | # This call to setup() does all the work 11 | setup( 12 | name="pythonpancakes", 13 | version="1.0.1", 14 | description="A basic request wrapper for the PancakeSwap API", 15 | long_description=README, 16 | long_description_content_type="text/markdown", 17 | url="https://github.com/scottburlovich/pythonpancakes", 18 | author="Scott Burlovich", 19 | author_email="teedot@gmail.com", 20 | license="MIT", 21 | classifiers=[ 22 | "License :: OSI Approved :: MIT License", 23 | "Programming Language :: Python :: 3", 24 | "Programming Language :: Python :: 3.8", 25 | ], 26 | packages=['pythonpancakes'], 27 | package_dir={'pythonpancakes': 'src/pythonpancakes'}, 28 | include_package_data=True, 29 | install_requires=["requests"] 30 | ) 31 | -------------------------------------------------------------------------------- /src/pythonpancakes/__init__.py: -------------------------------------------------------------------------------- 1 | from .api import PancakeSwapAPI 2 | __version__ = "1.0.1" 3 | -------------------------------------------------------------------------------- /src/pythonpancakes/api.py: -------------------------------------------------------------------------------- 1 | import json 2 | import re 3 | import requests 4 | 5 | 6 | class PancakeSwapAPI: 7 | __BASE_URL = "https://api.pancakeswap.info/api/v2/" 8 | 9 | """ 10 | Basic API request wrapper for PancakeSwap 11 | Scott Burlovich (github.com/scottburlovich) 12 | Last Update: Jul 28, 2021 13 | """ 14 | 15 | def __init__(self, base_url=__BASE_URL): 16 | self.base_url = base_url 17 | self.request_timeout = 60 18 | 19 | def __get(self, request_url: str): 20 | """ 21 | GET request wrapper 22 | :param request_url: str 23 | """ 24 | with requests.Session() as session: 25 | response = session.get(request_url, timeout=self.request_timeout) 26 | response.raise_for_status() 27 | return json.loads(response.content.decode('utf-8')) 28 | 29 | def summary(self): 30 | """ 31 | Returns data for the top ~1000 PancakeSwap pairs, sorted by reserves. 32 | :return: Dict 33 | """ 34 | url = f"{self.base_url}summary" 35 | return self.__get(url) 36 | 37 | def tokens(self, address: str = None): 38 | """ 39 | If address parameter is specified, returns the token information, based on address. 40 | Otherwise, returns the tokens in the top ~1000 pairs on PancakeSwap, sorted by reserves. 41 | :type address: str 42 | :return: Dict 43 | """ 44 | if address: 45 | # Trim any whitespace from address 46 | address = address.replace(' ', '') 47 | # Validate provided address matches ERC20 format - does not check if the address is valid on chain! 48 | if not re.match("^0x([A-Fa-f0-9]{40})$", address): 49 | raise ValueError(f"Provided address hash ({address}) is not in a valid format.") 50 | 51 | url = f"{self.base_url}tokens{'/' + address if address is not None else ''}" 52 | return self.__get(url) 53 | 54 | def pairs(self): 55 | """ 56 | Returns data for the top ~1000 PancakeSwap pairs, sorted by reserves. 57 | :return: Dict 58 | """ 59 | url = f"{self.base_url}pairs" 60 | return self.__get(url) 61 | -------------------------------------------------------------------------------- /tests/test_api_unittest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from src.pythonpancakes import PancakeSwapAPI 3 | 4 | 5 | class TestAPI(unittest.TestCase): 6 | def setUp(self): 7 | self.ps = PancakeSwapAPI() 8 | 9 | def test_summary(self): 10 | """Verify that valid data is returned from the summary() request""" 11 | response = self.ps.summary() 12 | self.assertIn('updated_at', response.keys()) 13 | self.assertIn('data', response.keys()) 14 | 15 | def test_tokens_without_address(self): 16 | """Verify that valid data is returned from the tokens() request when called without an address parameter""" 17 | response = self.ps.tokens() 18 | self.assertIn('updated_at', response.keys()) 19 | self.assertIn('data', response.keys()) 20 | 21 | def test_tokens_with_address(self): 22 | """Verify that valid data is returned from the tokens() request when called with an address parameter""" 23 | # Use pancakeswap-token (CAKE) for test 24 | token = "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82" 25 | response = self.ps.tokens(token) 26 | self.assertIn('updated_at', response.keys()) 27 | self.assertIn('data', response.keys()) 28 | self.assertEqual(response['data']['name'], "PancakeSwap Token") 29 | self.assertEqual(response['data']['symbol'], "Cake") 30 | 31 | def test_pairs(self): 32 | """Verify that valid data is returned from the pairs() request""" 33 | response = self.ps.pairs() 34 | self.assertIn('updated_at', response.keys()) 35 | self.assertIn('data', response.keys()) 36 | 37 | 38 | if __name__ == '__main__': 39 | unittest.main() 40 | --------------------------------------------------------------------------------