├── .gitignore ├── LICENSE ├── README.md ├── tron_bot.py ├── tronapi_bot ├── __init__.py ├── constants.py ├── filters.py ├── helpers.py ├── keyboards.py └── views.py └── tronbot.service /.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 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 iEXBase 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Tron Bot 3 |

4 | 5 | ## Requirements 6 | 7 | * Python 3 8 | * pip3 install base58 9 | * pip3 install requests 10 | * pip3 install tronapi 11 | * pip3 install python-telegram-bot 12 | * pip3 install lxml 13 | 14 | ## How to use 15 | 16 | ### Settings 17 | Bot Settings are in the file tronapi_bot/constants.py: 18 | 19 | ```python 20 | BOT_NAME = "" 21 | BOT_TOKEN = "" 22 | ``` 23 | ### Run on local machine 24 | ```bash 25 | > python tron_bot.py 26 | ``` 27 | 28 | ### Run on server 29 | Installing and running the bot on the server 30 | 31 | #### Step 1 32 | Upload all project files to server 33 | Example: /home/iexbase/tron_bot 34 | #### Step 2 35 | Create a Systemd file for TronBot: 36 | ``` 37 | sudo nano /etc/systemd/system/tronbot.service 38 | ``` 39 | #### Step 3 40 | ``` 41 | [Unit] 42 | Description=TronBot service 43 | After=network.target 44 | 45 | [Service] 46 | Type=idle 47 | WorkingDirectory=/home/iexbase/tron_bot 48 | User=root 49 | Group=root 50 | ExecStart=/usr/bin/python3.6 tron_bot.py 51 | 52 | [Install] 53 | WantedBy=multi-user.target 54 | ``` 55 | #### Step 4 56 | ``` 57 | sudo systemctl start tronbot 58 | sudo systemctl enable tronbot 59 | ``` 60 | check run status 61 | ``` 62 | sudo systemctl status tronbot 63 | ``` 64 | 65 | ## Support and Donation 66 | * Star and/or fork this repository 67 | * TRX: TRWBqiqoFZysoAeyR1J35ibuyc8EvhUAoY 68 | -------------------------------------------------------------------------------- /tron_bot.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------- 2 | # Copyright (c) iEXBase. All rights reserved. 3 | # Licensed under the MIT License. 4 | # See License.txt in the project root for license information. 5 | # -------------------------------------------------------------------- 6 | 7 | import logging 8 | from decimal import Decimal 9 | 10 | import requests 11 | import telegram 12 | 13 | from telegram import ( 14 | InlineKeyboardButton, 15 | InlineKeyboardMarkup 16 | ) 17 | from telegram.ext import ( 18 | CommandHandler, 19 | Updater, 20 | MessageHandler, 21 | CallbackQueryHandler, 22 | run_async, 23 | Filters, 24 | ConversationHandler, 25 | RegexHandler 26 | ) 27 | from tronapi import Tron 28 | 29 | from tronapi_bot import ( 30 | constants, 31 | views, 32 | helpers 33 | ) 34 | from tronapi_bot.helpers import ( 35 | text_simple, 36 | get_contract_type, 37 | currency 38 | ) 39 | from tronapi_bot.keyboards import ( 40 | reply_markup_p1 41 | ) 42 | 43 | # initial tron-api-python 44 | tron = Tron( 45 | full_node=constants.TRON_FULL_NODE, 46 | solidity_node=constants.TRON_SOLIDITY_NODE 47 | ) 48 | 49 | # Enabled logging 50 | logging.basicConfig( 51 | level=logging.DEBUG, 52 | format=constants.LOG_FORMATTER 53 | ) 54 | logger = logging.getLogger() 55 | 56 | CHOOSING, TYPING_REPLY, TYPING_CHOICE = range(3) 57 | 58 | 59 | def validate(bot, update, args): 60 | """Check TRON address""" 61 | 62 | address = ' '.join(args) 63 | bot.send_message( 64 | chat_id=update.message.chat_id, 65 | text=tron.isAddress(address) 66 | ) 67 | 68 | 69 | def tx(bot, update, args): 70 | """Get transaction details""" 71 | 72 | tx_id = ''.join(args) 73 | bot.send_message( 74 | chat_id=update.message.chat_id, 75 | parse_mode=telegram.ParseMode.MARKDOWN, 76 | text=_tx_view(tx_id) 77 | ) 78 | 79 | 80 | def price(bot, update): 81 | """Get the latest TRON course from CoinMarketCap""" 82 | 83 | bot.send_message( 84 | chat_id=update.message.chat_id, 85 | parse_mode=telegram.ParseMode.MARKDOWN, 86 | text=_price_view() 87 | ) 88 | 89 | 90 | def accounts(bot, update): 91 | """Top 10 Accounts with large balances""" 92 | 93 | bot.send_message( 94 | chat_id=update.message.chat_id, 95 | parse_mode=telegram.ParseMode.MARKDOWN, 96 | text=_accounts_view() 97 | ) 98 | 99 | 100 | def block(bot, update, args): 101 | """Get information on the block""" 102 | 103 | bot.send_message( 104 | chat_id=update.message.chat_id, 105 | parse_mode=telegram.ParseMode.MARKDOWN, 106 | text=_block_view(' '.join(args)) 107 | ) 108 | 109 | 110 | def balance(bot, update, args): 111 | """Get a balance at""" 112 | 113 | data = ' '.join(args).split(' ') 114 | try: 115 | info = currency(tron.trx.get_balance(data[0], True)) 116 | except Exception as e: 117 | info = str(e) 118 | 119 | bot.send_message( 120 | chat_id=update.message.chat_id, 121 | parse_mode=telegram.ParseMode.MARKDOWN, 122 | text=info 123 | ) 124 | 125 | 126 | def last_transactions(bot, update): 127 | """Get last 10 transactions""" 128 | 129 | data = requests.get( 130 | constants.API_TRONSCAN + '/transaction?sort=-timestamp&count=true&limit=10&start=0' 131 | ).json() 132 | 133 | keyboard = [] 134 | for tx in data['data']: 135 | keyboard.append([ 136 | InlineKeyboardButton(tx['hash'], callback_data=tx['hash']) 137 | ]) 138 | 139 | reply_markup = InlineKeyboardMarkup(keyboard) 140 | update.message.reply_text( 141 | text='Last 10 transactions', 142 | reply_markup=reply_markup 143 | ) 144 | 145 | 146 | def createaccount(bot, update): 147 | """Generate new address""" 148 | 149 | bot.send_message( 150 | chat_id=update.message.chat_id, 151 | parse_mode=telegram.ParseMode.MARKDOWN, 152 | text=_create_account_view() 153 | ) 154 | 155 | 156 | def stats(bot, update): 157 | """Get statistics Blockchain TRON""" 158 | 159 | bot.send_message( 160 | chat_id=update.message.chat_id, 161 | parse_mode=telegram.ParseMode.MARKDOWN, 162 | text=_statistics_view() 163 | ) 164 | 165 | 166 | def dapps(bot, update): 167 | keyboard = [ 168 | [InlineKeyboardButton("TRONAccelerator Winners", callback_data='dapps_0')], 169 | [InlineKeyboardButton("Games", callback_data='dapps_games')], 170 | [InlineKeyboardButton("Exchangers", callback_data='dapps_exchangers')], 171 | [InlineKeyboardButton("Gambling", callback_data='dapps_gambling')], 172 | [InlineKeyboardButton("Collectibles", callback_data='dapps_collectibles')], 173 | [InlineKeyboardButton("Other", callback_data='dapps_other')], 174 | [InlineKeyboardButton("Statistics", callback_data='dapps_stat')] 175 | ] 176 | reply_markup = InlineKeyboardMarkup(keyboard) 177 | 178 | update.message.reply_text( 179 | parse_mode=telegram.ParseMode.MARKDOWN, 180 | text='Select a category', 181 | reply_markup=reply_markup 182 | ) 183 | 184 | 185 | @run_async 186 | def start(bot, update): 187 | """The first launch of the bot""" 188 | 189 | usr_name = update.message.from_user.first_name 190 | if update.message.from_user.last_name: 191 | usr_name += ' ' + update.message.from_user.last_name 192 | 193 | text_response = views.BASE_START_TEXT.format( 194 | user_name=usr_name 195 | ) 196 | 197 | update.message.reply_text( 198 | text_response, 199 | parse_mode="Markdown", 200 | reply_markup=reply_markup_p1 201 | ) 202 | 203 | return CHOOSING 204 | 205 | 206 | def help(bot, update): 207 | """Assistant when working with the bot""" 208 | 209 | bot.send_message( 210 | chat_id=update.message.chat_id, 211 | parse_mode=telegram.ParseMode.MARKDOWN, 212 | text=_manual(), 213 | reply_markup=reply_markup_p1 214 | ) 215 | 216 | 217 | def _manual(): 218 | """Instructions and commands""" 219 | return views.HELP_VIEW 220 | 221 | 222 | def _statistics_view(): 223 | """TRON detailed statistics template""" 224 | 225 | base = requests.get(constants.API_TRONSCAN + '/stats/overview?limit=1').json() 226 | nodes = requests.get(constants.SERVER_TRON_API + '/node/nodemap?total=1').json() 227 | detail = base['data'][-1] 228 | 229 | text = views.STATS_VIEW.format( 230 | nodes=str(nodes['total']), 231 | height=str(detail['totalBlockCount']), 232 | total_tx=str(detail['totalTransaction']), 233 | total_accounts=str(detail['totalAddress']), 234 | new_block_height=str(detail['newBlockSeen']), 235 | new_accounts=str(detail['newAddressSeen']), 236 | new_tx=str(detail['newTransactionSeen']), 237 | time=helpers.date_format(detail['date']) 238 | ) 239 | return text 240 | 241 | 242 | def _create_account_view(): 243 | """Template for creating a new address""" 244 | 245 | result = tron.create_account 246 | text = views.CREATE_ACCOUNT.format( 247 | address=result.address.base58, 248 | privateKey=result.private_key, 249 | publicKey=result.public_key 250 | ) 251 | 252 | return text 253 | 254 | 255 | def _block_view(block_id): 256 | """Template for getting the details of the block 257 | 258 | Args: 259 | block_id (str): Block ID (example: latest, 123444, hash) 260 | 261 | """ 262 | 263 | # If no block number is specified 264 | if not block_id: 265 | block_id = 'latest' 266 | 267 | try: 268 | result = tron.trx.get_block(block_id) 269 | 270 | header = result['block_header']['raw_data'] 271 | text = views.BLOCK_VIEW.format( 272 | id=result['blockID'], 273 | height=str(header['number']), 274 | time=helpers.date_format(header['timestamp']), 275 | count=str(len(result['transactions'])), 276 | parent=header['parentHash'], 277 | version=str(header['version']), 278 | witness=tron.address.from_hex(header['witness_address']).decode("utf-8") 279 | ) 280 | return text 281 | except Exception: 282 | return { 283 | 'text': 'Sorry, block not found', 284 | 'reply_markup': None 285 | } 286 | 287 | 288 | def _accounts_view(): 289 | """Template for getting information about TOP 10 addresses with large balances""" 290 | 291 | data = requests.get( 292 | constants.API_TRONSCAN + '/account/list?sort=-balance&limit=10&start=0' 293 | ).json()['data'] 294 | 295 | text = '' 296 | for account in data: 297 | text += views.ACCOUNTS_VIEW.format( 298 | address=account['address'], 299 | balance=currency(tron.fromSun(account['balance'])) 300 | ) 301 | return text 302 | 303 | 304 | def _price_view(): 305 | """Template for get the current exchange rate and cryptocurrency volumes TRON""" 306 | 307 | data = requests.get(constants.URL_COINMARKET_API_TRON).json()['data'] 308 | data_usd = data['quotes']['USD'] 309 | data_btc = data['quotes']['BTC'] 310 | 311 | return views.PRICE_VIEW.format( 312 | price='{:.3f}'.format(data_usd['price']), 313 | price_btc='{:.8f}'.format(data_btc['price']), 314 | rank=data['rank'], 315 | market_cap=currency(data_usd["market_cap"]), 316 | volume_24h=currency(data_usd["volume_24h"]) 317 | ) 318 | 319 | 320 | def _tx_view(tx_id): 321 | """Template for obtaining transaction details 322 | 323 | Args: 324 | tx_id (str): Transaction ID 325 | 326 | """ 327 | 328 | data = requests.get(constants.API_TRONSCAN + "/transaction-info?hash=" + tx_id).json() 329 | text = "Sorry, the transaction could not be found." 330 | 331 | token = 'TRX' 332 | amount = 0 333 | contract_type = get_contract_type(data['contractType']) 334 | 335 | if data['contractType'] == 1: 336 | amount = tron.fromSun(data['contractData']['amount']) 337 | elif data['contractType'] == 44: 338 | amount = tron.fromSun(data['contractData']['quant']) 339 | elif data['contractType'] == 4: 340 | amount = tron.fromSun(data['contractData']['votes'][0]['vote_count']) 341 | token = 'TP' 342 | elif data['contractType'] == 11: 343 | amount = tron.fromSun(data['contractData']['frozen_balance']) 344 | else: 345 | if 'amount' in data['contractData']: 346 | amount = data['contractData']['amount'] 347 | 348 | if data['contractType'] not in [4, 12, 31]: 349 | if 'token' in data['contractData']: 350 | token = data['contractData']['token'] 351 | 352 | # Статус транзакции 353 | status = "UNCONFIRMED" 354 | if data['confirmed']: 355 | status = "CONFIRMED" 356 | 357 | text = views.TX_VIEW.format( 358 | hash=str(data['hash']), 359 | status=status, 360 | block=str(data['block']), 361 | time=helpers.date_format(data['timestamp']), 362 | owner_address=data['ownerAddress'], 363 | to_address=data['toAddress'], 364 | value=currency(amount), 365 | contract_type=contract_type, 366 | token=token 367 | ) 368 | 369 | return text 370 | 371 | 372 | def callback_data(bot, update): 373 | query = update.callback_query 374 | 375 | if query.data in constants.DAPPS_CAT: 376 | result = requests.get(helpers.dapps_category(query.data)).json() 377 | 378 | text = '' 379 | for item in result['data']['data']: 380 | 381 | text += views.DAPP_PREVIEW.format( 382 | name=helpers.format_html(item['name']), 383 | tagline=helpers.format_html(item['tagline']), 384 | version=str(item['ver']), 385 | developer=helpers.format_html(item['developer']), 386 | total=str(item['totalTransaction']) 387 | ) 388 | 389 | bot.send_message( 390 | text=text, 391 | chat_id=query.message.chat_id, 392 | parse_mode=telegram.ParseMode.MARKDOWN 393 | ) 394 | 395 | if query.data in ['dapps_stat']: 396 | total = requests.get(constants.DAPPS_API + '/statistic/total').json()['data'] 397 | info = requests.get(constants.DAPPS_API + '/statistic/cate/info').json() 398 | 399 | text = views.DAPP_STAT.format( 400 | total=helpers.format_price(total['dappCount']), 401 | dau=helpers.format_price(total['dau']), 402 | transactions=helpers.format_price(total['transactionCount']), 403 | volume=helpers.format_price(total['amount']), 404 | smart_contract=helpers.format_price(total['contractCount']), 405 | ) 406 | 407 | for item in info['data']: 408 | text += views.DAPP_STAT_CAT.format( 409 | category=helpers.get_dapp_categories(item['category']), 410 | dapp_count=helpers.format_price(item['dappCount']), 411 | mau=helpers.format_price(item['mau']), 412 | transactions=helpers.format_price(item['transactionCount']), 413 | smart_contract=helpers.format_price(item['contractCount']), 414 | ) 415 | 416 | bot.send_message( 417 | text=text, 418 | chat_id=query.message.chat_id, 419 | parse_mode=telegram.ParseMode.MARKDOWN 420 | ) 421 | 422 | if len(query.data) == 64: 423 | bot.edit_message_text( 424 | text=_tx_view(query.data), 425 | chat_id=query.message.chat_id, 426 | parse_mode=telegram.ParseMode.MARKDOWN, 427 | message_id=query.message.message_id 428 | ) 429 | 430 | 431 | @run_async 432 | def filter_text_input(bot, update): 433 | usr_msg_text = update.message.text 434 | dict_to_request = text_simple(usr_msg_text) 435 | 436 | # Get transaction information by ID 437 | if dict_to_request == 'transaction': 438 | update.message.reply_text( 439 | parse_mode=telegram.ParseMode.MARKDOWN, 440 | text=_tx_view(usr_msg_text) 441 | ) 442 | # Get top 10 accounts 443 | elif dict_to_request == 'topaccounts': 444 | update.message.reply_text( 445 | parse_mode=telegram.ParseMode.MARKDOWN, 446 | text=_accounts_view() 447 | ) 448 | # Get lasted TRON course 449 | elif dict_to_request == 'price': 450 | update.message.reply_text( 451 | parse_mode=telegram.ParseMode.MARKDOWN, 452 | text=_price_view() 453 | ) 454 | # Create new account 455 | elif dict_to_request == 'createaccount': 456 | update.message.reply_text( 457 | parse_mode=telegram.ParseMode.MARKDOWN, 458 | text=_create_account_view() 459 | ) 460 | # Get stats 461 | elif dict_to_request == 'stats': 462 | update.message.reply_text( 463 | parse_mode=telegram.ParseMode.MARKDOWN, 464 | text=_statistics_view() 465 | ) 466 | else: 467 | update.message.reply_text( 468 | text='You did not fill out all the fields, try again. /help', 469 | reply_markup=None 470 | ) 471 | 472 | return CHOOSING 473 | 474 | 475 | def error(bot, update, error): 476 | """Log Errors caused by Updates.""" 477 | logger.warning('Update "%s" caused error "%s"', update, error) 478 | 479 | 480 | def main(): 481 | # Run the TRON bot 482 | 483 | # We create EventHandler and we transfer a token. 484 | updater = Updater(constants.BOT_TOKEN) 485 | 486 | # Get the dispatcher to register handlers 487 | dp = updater.dispatcher 488 | 489 | # callback query 490 | updater.dispatcher.add_handler(CallbackQueryHandler(callback_data)) 491 | 492 | start_handler = ConversationHandler( 493 | entry_points=[CommandHandler('start', start)], 494 | 495 | states={ 496 | CHOOSING: [ 497 | RegexHandler( 498 | '^(Create Account|Price|Stats|Top Accounts)$', 499 | filter_text_input 500 | ), 501 | 502 | RegexHandler( 503 | '^(Last Transactions)$', 504 | last_transactions 505 | ), 506 | 507 | RegexHandler( 508 | '^[0-9a-zA-Z]{64}$', 509 | filter_text_input 510 | ), 511 | ] 512 | }, 513 | 514 | fallbacks=[ 515 | RegexHandler('^Help', help) 516 | ] 517 | ) 518 | 519 | # commands 520 | dp.add_handler(start_handler) 521 | dp.add_handler(CommandHandler('help', help)) 522 | dp.add_handler(CommandHandler('tx', tx, pass_args=True)) 523 | dp.add_handler(CommandHandler("validate", validate, pass_args=True)) 524 | dp.add_handler(CommandHandler("price", price)) 525 | dp.add_handler(CommandHandler("block", block, pass_args=True)) 526 | dp.add_handler(CommandHandler("balance", balance, pass_args=True)) 527 | dp.add_handler(CommandHandler("accounts", accounts)) 528 | dp.add_handler(CommandHandler("lasttransactions", last_transactions)) 529 | dp.add_handler(CommandHandler("createaccount", createaccount)) 530 | dp.add_handler(CommandHandler("stats", stats)) 531 | dp.add_handler(CommandHandler('dapps', dapps)) 532 | 533 | # messages 534 | # dp.add_handler(MessageHandler(Filters.text, filter_text_input)) 535 | 536 | # log all errors 537 | dp.add_error_handler(error) 538 | 539 | # Run the bot 540 | updater.start_polling() 541 | 542 | # Run the bot until the you presses Ctrl-C or the process receives SIGINT, 543 | # SIGTERM or SIGABRT. This should be used most of the time, since 544 | # start_polling() is non-blocking and will stop the bot gracefully. 545 | updater.idle() 546 | 547 | 548 | if __name__ == '__main__': 549 | main() 550 | -------------------------------------------------------------------------------- /tronapi_bot/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iexbase/tron-bot/dd088bd6dedaca19f1ac6a389ba3bc1013b0bbfc/tronapi_bot/__init__.py -------------------------------------------------------------------------------- /tronapi_bot/constants.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------- 2 | # Copyright (c) iEXBase. All rights reserved. 3 | # Licensed under the MIT License. 4 | # See License.txt in the project root for license information. 5 | # -------------------------------------------------------------------- 6 | 7 | # To work with telegram bot 8 | BOT_NAME = "" 9 | BOT_TOKEN = "" 10 | 11 | # To work with tronapi 12 | TRON_FULL_NODE = "https://api.trongrid.io" 13 | TRON_SOLIDITY_NODE = "https://api.trongrid.io" 14 | 15 | SERVER_TRON_API = 'https://server.tron.network/api/v2' 16 | API_TRONSCAN = 'https://apilist.tronscan.org/api' 17 | 18 | DAPPS_API = 'https://tron.app/dh/dapp/common' 19 | DAPPS_CAT = [ 20 | 'dapps_0', 21 | 'dapps_games', 22 | 'dapps_exchangers', 23 | 'dapps_gambling', 24 | 'dapps_collectibles', 25 | 'dapps_other' 26 | ] 27 | 28 | 29 | # For courses 30 | URL_COINMARKET_API_TRON = "https://api.coinmarketcap.com/v2/ticker/1958?convert=BTC" 31 | 32 | # Logging format 33 | LOG_FORMATTER = "%(asctime)s - %(levelname)s - %(name)s - %(message)s" 34 | -------------------------------------------------------------------------------- /tronapi_bot/filters.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------- 2 | # Copyright (c) iEXBase. All rights reserved. 3 | # Licensed under the MIT License. 4 | # See License.txt in the project root for license information. 5 | # -------------------------------------------------------------------- 6 | 7 | -------------------------------------------------------------------------------- /tronapi_bot/helpers.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------- 2 | # Copyright (c) iEXBase. All rights reserved. 3 | # Licensed under the MIT License. 4 | # See License.txt in the project root for license information. 5 | # -------------------------------------------------------------------- 6 | 7 | import locale 8 | import lxml.html 9 | import lxml.html.clean 10 | from datetime import datetime 11 | 12 | from tronapi_bot.constants import DAPPS_API 13 | 14 | locale.setlocale(locale.LC_ALL, '') 15 | 16 | 17 | def format_price(num): 18 | if num >= 1000000000: 19 | return '{:.5f}'.format(num / 1000000000) + 'k' 20 | elif num >= 1000000: 21 | return '{:.3f}'.format(num / 1000000) + 'k' 22 | elif num >= 1000: 23 | return '{:.2f}'.format(num / 1000) + 'k' 24 | 25 | return num 26 | 27 | 28 | def currency(amount): 29 | return str(locale.currency(amount, grouping=True)).replace('$', '').replace('?', '') 30 | 31 | 32 | def format_html(text): 33 | result = lxml.html.fromstring(text) 34 | cleaner = lxml.html.clean.Cleaner(style=True) 35 | result = cleaner.clean_html(result) 36 | 37 | return result.text_content() 38 | 39 | 40 | def dapps_category(categoty: str): 41 | if categoty == 'dapps_0': 42 | return DAPPS_API + '/list/bonus?category=-1&start=0&limit=10' 43 | elif categoty == 'dapps_games': 44 | return DAPPS_API + '/list?category=1&start=0&limit=10' 45 | elif categoty == 'dapps_exchangers': 46 | return DAPPS_API + '/list?category=2&start=0&limit=10' 47 | elif categoty == 'dapps_gambling': 48 | return DAPPS_API + '/list?category=5&start=0&limit=10' 49 | elif categoty == 'dapps_collectibles': 50 | return DAPPS_API + '/list?category=3&start=0&limit=10' 51 | elif categoty == 'dapps_other': 52 | return DAPPS_API + '/list?category=0&start=0&limit=10' 53 | 54 | 55 | def date_format(timestamp): 56 | return datetime.fromtimestamp(timestamp / 1000).strftime('%d-%m-%Y, %H:%M') 57 | 58 | 59 | def text_simple(usr_msg_text): 60 | if len(usr_msg_text) == 64: 61 | return 'transaction' 62 | 63 | return str(usr_msg_text).replace(' ', '').lower() 64 | 65 | 66 | def get_contract_type(t: int): 67 | if t == 1: 68 | return 'Transfer' 69 | elif t == 2: 70 | return 'Transfer Asset' 71 | elif t == 4: 72 | return 'Vote' 73 | elif t == 6: 74 | return 'Create' 75 | elif t == 9: 76 | return 'Participate' 77 | elif t == 11: 78 | return 'Freeze' 79 | elif t == 12: 80 | return 'Unfreeze' 81 | elif t == 44: 82 | return 'Exchange' 83 | elif t == 31: 84 | return 'Trigger Smart Contract' 85 | else: 86 | return 'Unregistred Name' 87 | 88 | 89 | def get_dapp_categories(i: int): 90 | if i == 0: 91 | return 'Other' 92 | elif i == 1: 93 | return 'Games' 94 | elif i == 2: 95 | return 'Exchanges' 96 | elif i == 3: 97 | return 'Collectibles' 98 | elif i == 5: 99 | return 'Gambling' 100 | -------------------------------------------------------------------------------- /tronapi_bot/keyboards.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------- 2 | # Copyright (c) iEXBase. All rights reserved. 3 | # Licensed under the MIT License. 4 | # See License.txt in the project root for license information. 5 | # -------------------------------------------------------------------- 6 | 7 | from telegram import KeyboardButton, ReplyKeyboardMarkup 8 | 9 | keyboard_p1 = [ 10 | [ 11 | KeyboardButton("Top Accounts"), 12 | KeyboardButton("Price"), 13 | KeyboardButton("Stats") 14 | ], 15 | [KeyboardButton("Create Account")] 16 | ] 17 | reply_markup_p1 = ReplyKeyboardMarkup(keyboard_p1, True, False) 18 | -------------------------------------------------------------------------------- /tronapi_bot/views.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------- 2 | # Copyright (c) iEXBase. All rights reserved. 3 | # Licensed under the MIT License. 4 | # See License.txt in the project root for license information. 5 | # -------------------------------------------------------------------- 6 | 7 | BASE_START_TEXT = (""" 8 | Hello {user_name}!. Welcome to TronBot 9 | 10 | /help - Assistant to work with the bot 11 | """) 12 | 13 | 14 | HELP_VIEW = (""" 15 | @iEXTronBot - Telegram bot that helps you with send, find data in Blockchain TRON 16 | 17 | *Commands*: 18 | /start - Start Bot 19 | /createaccount - Generate new TRON address 20 | /stats - Substrate statistics 21 | /dapps - Dapps projects 22 | /lasttransactions - Last 10 transactions 23 | /price - Actual course 24 | /accounts - TOP 10 Accounts 25 | /validate {address} - Validate address 26 | /block {id|hash} - Get information about the block 27 | /tx {hash} - Get information about the transaction 28 | /balance {address} - Getting balance at 29 | 30 | *Supports* 31 | - TRX: TRWBqiqoFZysoAeyR1J35ibuyc8EvhUAoY' 32 | 33 | """) 34 | 35 | PRICE_VIEW = (""" 36 | *Price:* {price} 37 | *Price BTC: * {price_btc} 38 | *Global Rank:* {rank} 39 | *Market Cap:* {market_cap} 40 | *24h Volume:* {volume_24h} 41 | """) 42 | 43 | 44 | ACCOUNTS_VIEW = (""" 45 | *Address* {address} 46 | *Balance TRX* {balance} 47 | --------------------- 48 | """) 49 | 50 | 51 | BLOCK_VIEW = (""" 52 | *Hash:* {id} 53 | ----------------------------- 54 | *Height:* {height} 55 | *Time:* {time} 56 | *Transactions:* {count} txs 57 | *Parent Hash:* {parent} 58 | *Version*: {version} 59 | *Witness address*: {witness} 60 | 61 | 62 | """) 63 | 64 | STATS_VIEW = (""" 65 | *Online Nodes:* {nodes} 66 | *Block Height:* {height} 67 | *Total Transactions:* {total_tx} 68 | *Total Accounts:* {total_accounts} 69 | 70 | *New Blocks height:* {new_block_height} 71 | *New Accounts:* {new_accounts} 72 | *New Transactions:* {new_tx} 73 | ------------ 74 | *Current time:* {time} 75 | 76 | """) 77 | 78 | TX_VIEW = (""" 79 | *Hash:* {hash} 80 | *Status:* {status} 81 | *Block:* {block} 82 | *Time:* {time} 83 | *Contract Type*: {contract_type} 84 | 85 | 86 | *Owner Address:* {owner_address} 87 | *Contract Address:* {to_address} 88 | *Value:* {value} {token} 89 | 90 | """) 91 | 92 | CREATE_ACCOUNT = (""" 93 | 94 | *Address:* {address} 95 | -------------- 96 | *Private key:* {privateKey} 97 | -------------- 98 | *Public key:* {publicKey} 99 | """) 100 | 101 | 102 | DAPP_PREVIEW = (""" 103 | *Name:* {name} 104 | *Tagline:* {tagline} 105 | *Version:* {version} 106 | *Developer:* {developer} 107 | *Total transaction* {total} 108 | ------------------------- 109 | """) 110 | 111 | 112 | DAPP_STAT = (""" 113 | *Dapp statistics* 114 | Stats are updated daily. Check back often to see the progress and development of the DApp ecosystem. 115 | 116 | *Total DApps:* {total} 117 | *Daily active users:*: {dau} 118 | *24 hr transactions:* {transactions} 119 | *24 hr volume (TRX):* {volume} 120 | *Smart contracts:* {smart_contract} 121 | 122 | *Statistics by category:* 123 | """) 124 | 125 | 126 | DAPP_STAT_CAT = (""" 127 | *Category:* {category} 128 | *Total DApps:* {dapp_count} 129 | *Daily active users:* {mau} 130 | *24 hr transactions:* {transactions} 131 | *Smart contract:* {smart_contract} 132 | --------------------------------- 133 | """) 134 | -------------------------------------------------------------------------------- /tronbot.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=TronBot service 3 | After=network.target 4 | 5 | [Service] 6 | Type=idle 7 | WorkingDirectory=/home/iexbase/tron_bot 8 | User=root 9 | Group=root 10 | ExecStart=/usr/bin/python3.6 tron_bot.py 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | --------------------------------------------------------------------------------