├── .gitignore ├── LICENSE ├── README.md ├── __init__.py ├── bscscan ├── __init__.py ├── accounts.py ├── client.py ├── contracts.py ├── stats.py └── tokens.py ├── examples ├── __init__.py ├── accounts │ ├── __init__.py │ ├── get_all_blocks_mined.py │ ├── get_all_transactions.py │ ├── get_balance.py │ ├── get_balance_multi.py │ ├── get_blocks_mined.py │ ├── get_transaction_page.py │ └── get_transaction_page_erc20.py ├── contracts │ ├── __init__.py │ ├── get_abi.py │ └── get_sourcecode.py ├── stats │ ├── __init__.py │ ├── get_bnb_last_price.py │ ├── get_total_bnb_supply.py │ └── get_validators.py └── tokens │ ├── __init__.py │ ├── get_token_balance.py │ └── get_total_supply.py ├── pip-requirements.txt ├── setup.cfg ├── setup.py └── tests ├── __init__.py ├── test_accounts.py └── test_token.py /.gitignore: -------------------------------------------------------------------------------- 1 | /api_key.json 2 | /.cache/ 3 | .idea 4 | /__pycache__/ 5 | 6 | # User-specific stuff: 7 | .idea/**/workspace.xml 8 | .idea/**/tasks.xml 9 | .idea/dictionaries 10 | 11 | # Sensitive or high-churn files: 12 | .idea/**/dataSources/ 13 | .idea/**/dataSources.ids 14 | .idea/**/dataSources.xml 15 | .idea/**/dataSources.local.xml 16 | .idea/**/sqlDataSources.xml 17 | .idea/**/dynamic.xml 18 | .idea/**/uiDesigner.xml 19 | 20 | # Gradle: 21 | .idea/**/gradle.xml 22 | .idea/**/libraries 23 | 24 | # CMake 25 | cmake-build-debug/ 26 | 27 | # Mongo Explorer plugin: 28 | .idea/**/mongoSettings.xml 29 | 30 | ## File-based project format: 31 | *.iws 32 | 33 | ## Plugin-specific files: 34 | 35 | # IntelliJ 36 | out/ 37 | 38 | # mpeltonen/sbt-idea plugin 39 | .idea_modules/ 40 | 41 | # JIRA plugin 42 | atlassian-ide-plugin.xml 43 | 44 | # Cursive Clojure plugin 45 | .idea/replstate.xml 46 | 47 | # Crashlytics plugin (for Android Studio and IntelliJ) 48 | com_crashlytics_export_strings.xml 49 | crashlytics.properties 50 | crashlytics-build.properties 51 | fabric.properties 52 | ### Python template 53 | # Byte-compiled / optimized / DLL files 54 | __pycache__/ 55 | *.py[cod] 56 | *$py.class 57 | 58 | # C extensions 59 | *.so 60 | 61 | # Distribution / packaging 62 | .Python 63 | build/ 64 | develop-eggs/ 65 | dist/ 66 | downloads/ 67 | eggs/ 68 | .eggs/ 69 | lib/ 70 | lib64/ 71 | parts/ 72 | sdist/ 73 | var/ 74 | wheels/ 75 | *.egg-info/ 76 | .installed.cfg 77 | *.egg 78 | MANIFEST 79 | 80 | # PyInstaller 81 | # Usually these files are written by a python script from a template 82 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 83 | *.manifest 84 | *.spec 85 | 86 | # Installer logs 87 | pip-log.txt 88 | pip-delete-this-directory.txt 89 | 90 | # Unit test / coverage reports 91 | htmlcov/ 92 | .tox/ 93 | .coverage 94 | .coverage.* 95 | .cache 96 | nosetests.xml 97 | coverage.xml 98 | *.cover 99 | .hypothesis/ 100 | 101 | # Translations 102 | *.mo 103 | *.pot 104 | 105 | # Django stuff: 106 | *.log 107 | .static_storage/ 108 | .media/ 109 | local_settings.py 110 | 111 | # Flask stuff: 112 | instance/ 113 | .webassets-cache 114 | 115 | # Scrapy stuff: 116 | .scrapy 117 | 118 | # Sphinx documentation 119 | docs/_build/ 120 | 121 | # PyBuilder 122 | target/ 123 | 124 | # Jupyter Notebook 125 | .ipynb_checkpoints 126 | 127 | # pyenv 128 | .python-version 129 | 130 | # celery beat schedule file 131 | celerybeat-schedule 132 | 133 | # SageMath parsed files 134 | *.sage.py 135 | 136 | # Environments 137 | .env 138 | .venv 139 | env/ 140 | venv/ 141 | ENV/ 142 | env.bak/ 143 | venv.bak/ 144 | 145 | # Spyder project settings 146 | .spyderproject 147 | .spyproject 148 | 149 | # Rope project settings 150 | .ropeproject 151 | 152 | # mkdocs documentation 153 | /site 154 | 155 | # mypy 156 | .mypy_cache/ 157 | 158 | # vscode 159 | .vscode/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 darkzeb 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 | # py-bscscan-api module 2 | 3 | BSCscan.com API python bindings 4 | 5 | Restarted from the famous https://github.com/corpetty/py-etherscan-api by [Corey Petty](https://github.com/corpetty) 6 | 7 | ## Description 8 | 9 | This module is written as an effort to provide python bindings to the BSCscan.com API, which can be found at: 10 | https://bscscan.com/apis. 11 | 12 | In order to use this, you must attain an BSCscan user account, and generate an API key. 13 | 14 | In order to use the API, you must provide an API key at runtime, which can be found at the bscscan.com API website. 15 | If you'd like to use the provided examples without altering them, then the JSON file `api_key.json` must be stored in 16 | the base directory. Its format is as follows: 17 | 18 | { "key" : "YourApiKeyToken" } 19 | 20 | with `YourApiKeyToken` is your provided API key token from BSCscan.com 21 | 22 | ## Installation 23 | 24 | To install the package to your computer, simply run the following command in the base directory: 25 | 26 | python3 -m pip install py-bscscan-api 27 | 28 | ## Available bindings 29 | 30 | Currently, only the following bscscan.com API modules are available: 31 | 32 | - accounts 33 | - contracts 34 | - tokens 35 | - stats 36 | 37 | The remaining available modules provided by bscscan.com will be added eventually... 38 | 39 | ## Available Networks 40 | 41 | Currently, this works for the following networks: 42 | 43 | - Mainnet 44 | 45 | ## Examples 46 | 47 | All possible calls have an associated example file in the examples folder to show how to call the binding 48 | 49 | ## TODO: 50 | 51 | - 52 | 53 | ## A votre bon coeur 54 | 55 | BSC: 0x1326Eb599D470f92C661c8D9172e8b1B3e944c7c 56 | 57 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'darkzeb' 2 | name = "py-bscscan-api" -------------------------------------------------------------------------------- /bscscan/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'darkzeb' 2 | -------------------------------------------------------------------------------- /bscscan/accounts.py: -------------------------------------------------------------------------------- 1 | from .client import Client 2 | import re 3 | 4 | 5 | class Account(Client): 6 | PAGE_NUM_PATTERN = re.compile( 7 | r'[1-9](?:\d{0,2})(?:,\d{3})*(?:\.\d*[1-9])?|0?\.\d*[1-9]|0') 8 | 9 | def __init__(self, address=Client.dao_address, api_key='YourApiKeyToken'): 10 | Client.__init__(self, address=address, api_key=api_key) 11 | self.url_dict[self.MODULE] = 'account' 12 | 13 | def get_balance(self): 14 | self.url_dict[self.ACTION] = 'balance' 15 | self.url_dict[self.TAG] = 'latest' 16 | self.build_url() 17 | req = self.connect() 18 | return req['result'] 19 | 20 | def get_balance_multiple(self): 21 | self.url_dict[self.ACTION] = 'balancemulti' 22 | self.url_dict[self.TAG] = 'latest' 23 | self.build_url() 24 | req = self.connect() 25 | return req['result'] 26 | 27 | def get_transaction_page(self, page=1, offset=10000, sort='asc', 28 | internal=False, erc20=False) -> list: 29 | """ 30 | Get a page of transactions, each transaction 31 | returns list of dict with keys: 32 | nonce 33 | hash 34 | cumulativeGasUsed 35 | gasUsed 36 | timeStamp 37 | blockHash 38 | value (in wei) 39 | input 40 | gas 41 | isInternalTx 42 | contractAddress 43 | confirmations 44 | gasPrice 45 | transactionIncex 46 | to 47 | from 48 | isError 49 | blockNumber 50 | 51 | sort options: 52 | 'asc' -> ascending order 53 | 'desc' -> descending order 54 | 55 | internal options: (currently marked at Beta for bscscan.io) 56 | True -> Gets the internal transactions of the address 57 | False -> (default) get normal external transactions 58 | 59 | erc20 options: (currently marked at Beta for bscscan.io) 60 | True -> Gets the erc20 token transcations of the address 61 | False -> (default) get normal external transactions 62 | 63 | NOTE: not sure if this works for contract addresses, requires testing 64 | """ 65 | if internal: 66 | self.url_dict[self.ACTION] = 'txlistinternal' 67 | elif erc20: 68 | self.url_dict[self.ACTION] = 'tokentx' 69 | else: 70 | self.url_dict[self.ACTION] = 'txlist' 71 | self.url_dict[self.PAGE] = str(page) 72 | self.url_dict[self.OFFSET] = str(offset) 73 | self.url_dict[self.SORT] = sort 74 | self.build_url() 75 | req = self.connect() 76 | return req['result'] 77 | 78 | def get_all_transactions(self, offset=10000, sort='asc', 79 | internal=False) -> list: 80 | if internal: 81 | self.url_dict[self.ACTION] = 'txlistinternal' 82 | else: 83 | self.url_dict[self.ACTION] = 'txlist' 84 | self.url_dict[self.PAGE] = str(1) 85 | self.url_dict[self.OFFSET] = str(offset) 86 | self.url_dict[self.SORT] = sort 87 | self.build_url() 88 | 89 | trans_list = [] 90 | while True: 91 | self.build_url() 92 | req = self.connect() 93 | if "No transactions found" in req['message']: 94 | print( 95 | "Total number of transactions: {}".format(len(trans_list))) 96 | self.page = '' 97 | return trans_list 98 | else: 99 | trans_list += req['result'] 100 | # Find any character block that is a integer of any length 101 | page_number = re.findall(Account.PAGE_NUM_PATTERN, 102 | self.url_dict[self.PAGE]) 103 | print("page {} added".format(page_number[0])) 104 | self.url_dict[self.PAGE] = str(int(page_number[0]) + 1) 105 | 106 | def get_blocks_mined_page(self, blocktype='blocks', page=1, 107 | offset=10000) -> list: 108 | """ 109 | Get a page of blocks mined by given address, 110 | returns list of dict with keys: 111 | blockReward (in wei) 112 | blockNumber 113 | timeStamp 114 | 115 | blocktype options: 116 | 'blocks' -> full blocks only 117 | 'uncles' -> uncles only 118 | """ 119 | self.url_dict[self.ACTION] = 'getminedblocks' 120 | self.url_dict[self.BLOCK_TYPE] = blocktype 121 | self.url_dict[self.PAGE] = str(page) 122 | self.url_dict[self.OFFSET] = str(offset) 123 | self.build_url() 124 | req = self.connect() 125 | return req['result'] 126 | 127 | def get_all_blocks_mined(self, blocktype='blocks', offset=10000) -> list: 128 | self.url_dict[self.ACTION] = 'getminedblocks' 129 | self.url_dict[self.BLOCK_TYPE] = blocktype 130 | self.url_dict[self.PAGE] = str(1) 131 | self.url_dict[self.OFFSET] = str(offset) 132 | blocks_list = [] 133 | while True: 134 | self.build_url() 135 | req = self.connect() 136 | print(req['message']) 137 | if "No transactions found" in req['message']: 138 | print( 139 | "Total number of blocks mined: {}".format( 140 | len(blocks_list))) 141 | return blocks_list 142 | else: 143 | blocks_list += req['result'] 144 | # Find any character block that is a integer of any length 145 | page_number = re.findall(Account.PAGE_NUM_PATTERN, 146 | self.url_dict[self.PAGE]) 147 | print("page {} added".format(page_number[0])) 148 | self.url_dict[self.PAGE] = str(int(page_number[0]) + 1) 149 | 150 | def get_internal_by_hash(self, tx_hash=''): 151 | """ 152 | Currently not implemented 153 | :return: 154 | """ 155 | pass 156 | 157 | def update_transactions(self, address, trans): 158 | """ 159 | Gets last page of transactions (last 10k trans) 160 | and updates current trans book (book) 161 | """ 162 | pass 163 | -------------------------------------------------------------------------------- /bscscan/client.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | import collections 3 | 4 | import requests 5 | 6 | 7 | class ClientException(Exception): 8 | """Unhandled API client exception""" 9 | message = 'unhandled error' 10 | 11 | def __init__(self, message=None): 12 | if message is not None: 13 | self.message = message 14 | 15 | def __unicode__(self): 16 | return u''.format(self) 17 | 18 | __str__ = __unicode__ 19 | 20 | 21 | class ConnectionRefused(ClientException): 22 | """Connection refused by remote host""" 23 | 24 | 25 | class EmptyResponse(ClientException): 26 | """Empty response from API""" 27 | 28 | 29 | class BadRequest(ClientException): 30 | """Invalid request passed""" 31 | 32 | 33 | # Assume user puts his API key in the api_key.json 34 | # file under variable name "key" 35 | class Client(object): 36 | dao_address = '0xbb9bc244d798123fde783fcc1c72d3bb8c189413' 37 | 38 | # Constants 39 | PREFIX = 'https://api.bscscan.com/api?' 40 | MODULE = 'module=' 41 | ACTION = '&action=' 42 | CONTRACT_ADDRESS = '&contractaddress=' 43 | ADDRESS = '&address=' 44 | OFFSET = '&offset=' 45 | PAGE = '&page=' 46 | SORT = '&sort=' 47 | BLOCK_TYPE = '&blocktype=' 48 | TO = '&to=' 49 | VALUE = '&value=' 50 | DATA = '&data=' 51 | POSITION = '&position=' 52 | HEX = '&hex=' 53 | GAS_PRICE = '&gasPrice=' 54 | GAS = '&gas=' 55 | START_BLOCK = '&startblock=' 56 | END_BLOCK = '&endblock=' 57 | BLOCKNO = '&blockno=' 58 | TXHASH = '&txhash=' 59 | TAG = '&tag=' 60 | BOOLEAN = '&boolean=' 61 | INDEX = '&index=' 62 | API_KEY = '&apikey=' 63 | 64 | url_dict = {} 65 | 66 | def __init__(self, address, api_key=''): 67 | self.http = requests.session() 68 | self.url_dict = collections.OrderedDict([ 69 | (self.MODULE, ''), 70 | (self.ADDRESS, ''), 71 | (self.OFFSET, ''), 72 | (self.PAGE, ''), 73 | (self.SORT, ''), 74 | (self.BLOCK_TYPE, ''), 75 | (self.TO, ''), 76 | (self.VALUE, ''), 77 | (self.DATA, ''), 78 | (self.POSITION, ''), 79 | (self.HEX, ''), 80 | (self.GAS_PRICE, ''), 81 | (self.GAS, ''), 82 | (self.START_BLOCK, ''), 83 | (self.END_BLOCK, ''), 84 | (self.BLOCKNO, ''), 85 | (self.TXHASH, ''), 86 | (self.TAG, ''), 87 | (self.BOOLEAN, ''), 88 | (self.INDEX, ''), 89 | (self.API_KEY, api_key)]) 90 | 91 | # Var initialization should take place within init 92 | self.url = None 93 | 94 | self.check_and_get_api() 95 | 96 | if (len(address) > 20) and (type(address) == list): 97 | raise BadRequest("Bscscan only takes 20 addresses at a time") 98 | elif (type(address) == list) and (len(address) <= 20): 99 | self.url_dict[self.ADDRESS] = ','.join(address) 100 | else: 101 | self.url_dict[self.ADDRESS] = address 102 | 103 | def build_url(self): 104 | self.url = self.PREFIX + ''.join( 105 | [param + val if val else '' for param, val in 106 | self.url_dict.items()]) 107 | 108 | def connect(self): 109 | # TODO: deal with "unknown exception" error 110 | try: 111 | req = self.http.get(self.url) 112 | except requests.exceptions.ConnectionError: 113 | raise ConnectionRefused 114 | 115 | if req.status_code == 200: 116 | # Check for empty response 117 | if req.text: 118 | data = req.json() 119 | status = data.get('status') 120 | if status == '1' or self.check_keys_api(data): 121 | return data 122 | else: 123 | raise EmptyResponse(data.get('message', 'no message')) 124 | raise BadRequest( 125 | "Problem with connection, status code: %s" % req.status_code) 126 | 127 | def check_and_get_api(self): 128 | if self.url_dict[self.API_KEY]: # Check if api_key is empty string 129 | pass 130 | else: 131 | self.url_dict[self.API_KEY] = input( 132 | 'Please type your EtherScan.io API key: ') 133 | 134 | @staticmethod 135 | def check_keys_api(data): 136 | return all(k in data for k in ('jsonrpc', 'id', 'result')) 137 | -------------------------------------------------------------------------------- /bscscan/contracts.py: -------------------------------------------------------------------------------- 1 | from .client import Client 2 | 3 | 4 | class Contract(Client): 5 | def __init__(self, address=Client.dao_address, api_key='YourApiKeyToken'): 6 | Client.__init__(self, address=address, api_key=api_key) 7 | self.url_dict[self.MODULE] = 'contract' 8 | 9 | def get_abi(self): 10 | self.url_dict[self.ACTION] = 'getabi' 11 | self.build_url() 12 | req = self.connect() 13 | return req['result'] 14 | 15 | def get_sourcecode(self): 16 | self.url_dict[self.ACTION] = 'getsourcecode' 17 | self.build_url() 18 | req = self.connect() 19 | return req['result'] 20 | -------------------------------------------------------------------------------- /bscscan/stats.py: -------------------------------------------------------------------------------- 1 | from .client import Client 2 | 3 | 4 | class Stats(Client): 5 | def __init__(self, api_key='YourApiKeyToken'): 6 | Client.__init__(self, address='', api_key=api_key) 7 | self.url_dict[self.MODULE] = 'stats' 8 | 9 | def get_total_bnb_supply(self): 10 | self.url_dict[self.ACTION] = 'bnbsupply' 11 | self.build_url() 12 | req = self.connect() 13 | return req['result'] 14 | 15 | def get_validators(self): 16 | self.url_dict[self.ACTION] = 'validators' 17 | self.build_url() 18 | req = self.connect() 19 | return req['result'] 20 | 21 | # NOT YET AVAILABLE IN BSCSCAN APIS 22 | # def get_bnb_last_price(self): 23 | # self.url_dict[self.ACTION] = 'bnbprice' 24 | # self.build_url() 25 | # req = self.connect() 26 | # return req['result'] 27 | -------------------------------------------------------------------------------- /bscscan/tokens.py: -------------------------------------------------------------------------------- 1 | from .client import Client 2 | 3 | 4 | class Tokens(Client): 5 | def __init__(self, contract_address, api_key='YourApiKeyToken'): 6 | Client.__init__(self, address='', api_key=api_key) 7 | # self.url_dict[self.TOKEN_NAME] = tokenname 8 | self.url_dict[self.CONTRACT_ADDRESS] = contract_address 9 | 10 | def get_total_supply(self): 11 | self.url_dict[self.ACTION] = 'tokensupply' 12 | self.url_dict[self.MODULE] = 'stats' 13 | self.build_url() 14 | req = self.connect() 15 | return req['result'] 16 | 17 | def get_circulating_supply(self): 18 | self.url_dict[self.ACTION] = 'tokenCsupply' 19 | self.url_dict[self.MODULE] = 'stats' 20 | self.build_url() 21 | req = self.connect() 22 | return req['result'] 23 | 24 | def get_token_balance(self, address): 25 | self.url_dict[self.ADDRESS] = address 26 | self.url_dict[self.MODULE] = 'account' 27 | self.url_dict[self.ACTION] = 'tokenbalance' 28 | self.build_url() 29 | req = self.connect() 30 | return req['result'] 31 | -------------------------------------------------------------------------------- /examples/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'darkzeb' 2 | -------------------------------------------------------------------------------- /examples/accounts/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'darkzeb' 2 | -------------------------------------------------------------------------------- /examples/accounts/get_all_blocks_mined.py: -------------------------------------------------------------------------------- 1 | from bscscan.accounts import Account 2 | import json 3 | 4 | with open('../../api_key.json', mode='r') as key_file: 5 | key = json.loads(key_file.read())['key'] 6 | 7 | address = '0x2a65aca4d5fc5b5c859090a6c34d164135398226' 8 | 9 | api = Account(address=address, api_key=key) 10 | blocks = api.get_all_blocks_mined(offset=10000, blocktype='uncles') 11 | print(blocks) 12 | -------------------------------------------------------------------------------- /examples/accounts/get_all_transactions.py: -------------------------------------------------------------------------------- 1 | from bscscan.accounts import Account 2 | import json 3 | 4 | with open('../../api_key.json', mode='r') as key_file: 5 | key = json.loads(key_file.read())['key'] 6 | 7 | address = '0x043d9b3af52b623e54a3dF92F1682757eb29F912' 8 | 9 | api = Account(address=address, api_key=key) 10 | transactions = api.get_all_transactions(offset=100, sort='asc', internal=False) 11 | 12 | print(transactions[0]) 13 | -------------------------------------------------------------------------------- /examples/accounts/get_balance.py: -------------------------------------------------------------------------------- 1 | from bscscan.accounts import Account 2 | import json 3 | 4 | with open('../../api_key.json', mode='r') as key_file: 5 | key = json.loads(key_file.read())['key'] 6 | 7 | address = '0x043d9b3af52b623e54a3dF92F1682757eb29F912' 8 | 9 | api = Account(address=address, api_key=key) 10 | balance = api.get_balance() 11 | print(balance) 12 | -------------------------------------------------------------------------------- /examples/accounts/get_balance_multi.py: -------------------------------------------------------------------------------- 1 | from bscscan.accounts import Account 2 | import json 3 | 4 | with open('../../api_key.json', mode='r') as key_file: 5 | key = json.loads(key_file.read())['key'] 6 | 7 | address = ['0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a', 8 | '0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a'] 9 | 10 | api = Account(address=address, api_key=key) 11 | balances = api.get_balance_multiple() 12 | print(balances) 13 | -------------------------------------------------------------------------------- /examples/accounts/get_blocks_mined.py: -------------------------------------------------------------------------------- 1 | from bscscan.accounts import Account 2 | import json 3 | 4 | with open('../../api_key.json', mode='r') as key_file: 5 | key = json.loads(key_file.read())['key'] 6 | 7 | address = '0x2a65aca4d5fc5b5c859090a6c34d164135398226' 8 | 9 | api = Account(address=address, api_key=key) 10 | blocks = api.get_blocks_mined_page(page=1, offset=10000, blocktype='blocks') 11 | print(blocks) 12 | -------------------------------------------------------------------------------- /examples/accounts/get_transaction_page.py: -------------------------------------------------------------------------------- 1 | from bscscan.accounts import Account 2 | import json 3 | 4 | with open('../../api_key.json', mode='r') as key_file: 5 | key = json.loads(key_file.read())['key'] 6 | 7 | address = '0x043d9b3af52b623e54a3dF92F1682757eb29F912' 8 | 9 | api = Account(address=address, api_key=key) 10 | transactions = api.get_transaction_page(page=1, offset=10000, sort='des') 11 | print(transactions) 12 | -------------------------------------------------------------------------------- /examples/accounts/get_transaction_page_erc20.py: -------------------------------------------------------------------------------- 1 | from bscscan.accounts import Account 2 | import json 3 | 4 | with open('../../api_key.json', mode='r') as key_file: 5 | key = json.loads(key_file.read())['key'] 6 | 7 | address = '0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a' 8 | 9 | api = Account(address=address, api_key=key) 10 | transactions = api.get_transaction_page(page=1, offset=10000, sort='des', erc20=True) 11 | print(transactions) 12 | -------------------------------------------------------------------------------- /examples/contracts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkzeb/py-bscscan-api/78b27162ad6cc1aee92909742a7bda819018b5aa/examples/contracts/__init__.py -------------------------------------------------------------------------------- /examples/contracts/get_abi.py: -------------------------------------------------------------------------------- 1 | from bscscan.contracts import Contract 2 | import json 3 | 4 | with open('../../api_key.json', mode='r') as key_file: 5 | key = json.loads(key_file.read())['key'] 6 | 7 | address = '0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359' 8 | 9 | api = Contract(address=address, api_key=key) 10 | abi = api.get_abi() 11 | print(abi) 12 | -------------------------------------------------------------------------------- /examples/contracts/get_sourcecode.py: -------------------------------------------------------------------------------- 1 | from bscscan.contracts import Contract 2 | import json 3 | 4 | with open('../../api_key.json', mode='r') as key_file: 5 | key = json.loads(key_file.read())['key'] 6 | 7 | address = '0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359' 8 | 9 | api = Contract(address=address, api_key=key) 10 | sourcecode = api.get_sourcecode() 11 | # TODO: make this return something pretty 12 | print(sourcecode[0]['SourceCode']) 13 | -------------------------------------------------------------------------------- /examples/stats/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'darkzeb' 2 | -------------------------------------------------------------------------------- /examples/stats/get_bnb_last_price.py: -------------------------------------------------------------------------------- 1 | # from bscscan.stats import Stats 2 | # import json 3 | # 4 | # with open('../../api_key.json', mode='r') as key_file: 5 | # key = json.loads(key_file.read())['key'] 6 | # 7 | # api = Stats(api_key=key) 8 | # last_price = api.get_bnb_last_price() 9 | # print(last_price) 10 | -------------------------------------------------------------------------------- /examples/stats/get_total_bnb_supply.py: -------------------------------------------------------------------------------- 1 | from bscscan.stats import Stats 2 | import json 3 | 4 | with open('../../api_key.json', mode='r') as key_file: 5 | key = json.loads(key_file.read())['key'] 6 | 7 | # call with default address, The DAO 8 | api = Stats(api_key=key) 9 | supply = api.get_total_bnb_supply() 10 | print(supply) 11 | -------------------------------------------------------------------------------- /examples/stats/get_validators.py: -------------------------------------------------------------------------------- 1 | from bscscan.stats import Stats 2 | import json 3 | 4 | with open('../../api_key.json', mode='r') as key_file: 5 | key = json.loads(key_file.read())['key'] 6 | 7 | # call with default address, The DAO 8 | api = Stats(api_key=key) 9 | validators = api.get_validators() 10 | print(validators) 11 | -------------------------------------------------------------------------------- /examples/tokens/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkzeb/py-bscscan-api/78b27162ad6cc1aee92909742a7bda819018b5aa/examples/tokens/__init__.py -------------------------------------------------------------------------------- /examples/tokens/get_token_balance.py: -------------------------------------------------------------------------------- 1 | from bscscan.tokens import Tokens 2 | import json 3 | 4 | with open('../../api_key.json', mode='r') as key_file: 5 | key = json.loads(key_file.read())['key'] 6 | 7 | address = '0x043d9b3af52b623e54a3dF92F1682757eb29F912' 8 | api = Tokens(contract_address='0x0cf2b5aabf844b49480dbf5e6192b873a865fae4', 9 | api_key=key) 10 | balance = api.get_token_balance(address=address) 11 | print(balance) 12 | -------------------------------------------------------------------------------- /examples/tokens/get_total_supply.py: -------------------------------------------------------------------------------- 1 | from bscscan.tokens import Tokens 2 | import json 3 | 4 | with open('../../api_key.json', mode='r') as key_file: 5 | key = json.loads(key_file.read())['key'] 6 | 7 | # tokenname options are: 8 | # DGD 9 | # MKR 10 | # TheDAO 11 | api = Tokens(tokenname='SNT', api_key=key) 12 | supply = api.get_total_supply() 13 | print(supply) 14 | -------------------------------------------------------------------------------- /pip-requirements.txt: -------------------------------------------------------------------------------- 1 | requests>=2.20.0 2 | typing==3.6.4 3 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | setuptools.setup( 4 | name='py_bscscan_api', 5 | version='0.0.1', 6 | packages=['examples', 'examples.stats', 'examples.tokens', 7 | 'examples.accounts', 'bscscan'], 8 | url='https://github.com/darkzeb/py-bscscan-api', 9 | license='MIT', 10 | author='darkzeb', 11 | author_email='bbezkradd@gmail.com', 12 | description='Python Bindings to Bscscan.com API', 13 | install_requires=[ 14 | 'requests>=2.20.0', 15 | ], 16 | classifiers=[ 17 | "Programming Language :: Python :: 3" 18 | ] 19 | ) 20 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkzeb/py-bscscan-api/78b27162ad6cc1aee92909742a7bda819018b5aa/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_accounts.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from bscscan.accounts import Account 4 | 5 | SINGLE_BALANCE = '40807178566070000000000' 6 | SINGLE_ACCOUNT = '0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a' 7 | MULTI_ACCOUNT = [ 8 | '0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a', 9 | '0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a', 10 | ] 11 | MULTI_BALANCE = [ 12 | {'account': '0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a', 13 | 'balance': '40807178566070000000000'}, 14 | {'account': '0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a', 15 | 'balance': '40807178566070000000000'} 16 | ] 17 | API_KEY = 'YourAPIkey' 18 | 19 | 20 | class AccountsTestCase(unittest.TestCase): 21 | 22 | def test_get_balance(self): 23 | api = Account(address=SINGLE_ACCOUNT, api_key=API_KEY) 24 | self.assertEqual(api.get_balance(), SINGLE_BALANCE) 25 | 26 | def test_get_balance_multi(self): 27 | api = Account(address=MULTI_ACCOUNT, api_key=API_KEY) 28 | self.assertEqual(api.get_balance_multiple(), MULTI_BALANCE) 29 | -------------------------------------------------------------------------------- /tests/test_token.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from bscscan.tokens import Tokens 4 | 5 | ELCOIN_TOKEN_SUPPLY = '21265524714464' 6 | ELCOIN_TOKEN_BALANCE = "135499" 7 | CONTRACT_ADDRESS = '0x57d90b64a1a57749b0f932f1a3395792e12e7055' 8 | ADDRESS = '0xe04f27eb70e025b78871a2ad7eabe85e61212761' 9 | API_KEY = 'YourAPIkey' 10 | 11 | 12 | class TokensTestCase(unittest.TestCase): 13 | 14 | def test_get_token_supply(self): 15 | api = Tokens(contract_address=CONTRACT_ADDRESS, api_key=(API_KEY)) 16 | self.assertEqual(api.get_total_supply(), ELCOIN_TOKEN_SUPPLY) 17 | 18 | def test_get_token_balance(self): 19 | api = Tokens(contract_address=CONTRACT_ADDRESS, api_key=API_KEY) 20 | self.assertEqual(api.get_token_balance(ADDRESS), ELCOIN_TOKEN_BALANCE) 21 | --------------------------------------------------------------------------------