def mempool_json(): try: mp_config = current_app.settings['MEMPOOL'] url = mp_config.get('url') from urllib.parse import urlparse parse_object = urlparse(url) scheme = 'http' if parse_object.scheme == '' else parse_object.scheme if parse_object.netloc != '': url = scheme + '://' + parse_object.netloc + '/' if not url.startswith('http'): url = 'http://' + url if url[-1] != '/': url += '/' # Get recommended fees mp_fee = tor_request(url + 'api/v1/fees/recommended').json() mp_blocks = tor_request(url + 'api/blocks').json() return json.dumps({ 'mp_fee': mp_fee, 'mp_blocks': mp_blocks, 'mp_url': url }) except Exception: return json.dumps({ 'mp_fee': '-', 'mp_blocks': '-', 'mp_url': 'Error: Retrying...' })
def check_version(): from dashboard import version current_version = version() with yaspin( text=f"Checking for updates. Running version: {current_version}", color="green") as spinner: url = 'https://raw.githubusercontent.com/pxsocs/warden_terminal/master/version.txt' remote_version = tor_request(url).text if str(remote_version).strip() == str(current_version).strip(): spinner.ok("✅ ") spinner.write(success(" You are running latest version")) else: spinner.fail("💥 ") spinner.write( warning(f" Update available - version: {remote_version}")) import click if click.confirm(warning(' [?] Would you like to upgrade?'), default=False): print(" ---------------------------------------") print(f"Upgrading from GitHub: "), import subprocess subprocess.run("git fetch --all", shell=True) subprocess.run("git reset --hard origin/master", shell=True) print(" ---------------------------------------") print(success(" ✅ Done Upgrading")) print("")
def url_text(url): page = tor_request(url) try: txt = page.text except Exception: txt = None return(txt)
def historical(ticker, fx='USD', parsed=True): ''' Gets historical prices using CryptoCompare Only Cryptocurrencies are accepted Result: { "Response": "Success", "Message": "", "HasWarning": false, "Type": 100, "RateLimit": { }, "Data": { "Aggregated": false, "TimeFrom": 1613606400, "TimeTo": 1614470400, "Data": [ { "time": 1613606400, "high": 52550.6, "low": 50874.81, "open": 52154.91, "volumefrom": 42530.26, "volumeto": 2205232619.94, "close": 51591.61, "conversionType": "direct", "conversionSymbol": "" },... :param str ticker: Ticker or Symbol :param str fx: a string of a single currency :return: Historical price data :raises Exception: if Tor request returns a 403 (not authorized) ''' globalURL = 'https://min-api.cryptocompare.com/data/v2/histoday?fsym=' + ticker globalURL += '&tsym=' + fx globalURL += '&limit=2000' response = tor_request(url=globalURL) if response.status_code == 403: response = requests.get(globalURL) data = response.json()['Data'] if parsed: try: df = pd.DataFrame.from_dict(data['Data']) df = df.rename(columns={'time': 'date'}) df['date'] = pd.to_datetime(df['date'], unit='s') df.set_index('date', inplace=True) df_save = df[['close', 'open', 'high', 'low']] except Exception: df_save = pd.DataFrame() return (df_save) return data
def satoshi_quotes_json(): url = 'https://raw.githubusercontent.com/NakamotoInstitute/nakamotoinstitute.org/0bf08c48cd21655c76e8db06da39d16036a88594/data/quotes.json' try: quotes = tor_request(url).json() except Exception: return (json.dumps(' >> Error contacting server. Retrying... ')) quote = quotes[randrange(len(quotes))] return (quote)
def mempool_json(): url = None try: mp_config = current_app.settings['MEMPOOL'] url = mp_config.get('url') url = url_parser(url) # Get recommended fees try: mp_fee = tor_request(url + 'api/v1/fees/recommended').json() except Exception: mp_fee = tor_request(url + 'api/v1/fees/recommended').text if 'Service Unavailable' in mp_fee: return json.dumps({ 'mp_fee': '-', 'mp_blocks': '-', 'mp_url': url, 'error': 'Mempool.space seems to be unavailable. Maybe node is still synching.' }) mp_blocks = tor_request(url + 'api/blocks').json() return json.dumps({ 'mp_fee': mp_fee, 'mp_blocks': mp_blocks, 'mp_url': url, 'error': None }) except Exception as e: if url is None: url = 'Could not find url' return json.dumps({ 'mp_fee': '-', 'mp_blocks': '-', 'mp_url': url, 'error': f'Error: {e}' })
def mempool_json(): try: mp_config = current_app.settings['MEMPOOL'] url = mp_config.get('url') # Get recommended fees mp_fee = tor_request(url + '/api/v1/fees/recommended').json() mp_blocks = tor_request(url + '/api/blocks').json() return json.dumps({ 'mp_fee': mp_fee, 'mp_blocks': mp_blocks, 'mp_url': url }) except Exception: return json.dumps({ 'mp_fee': '-', 'mp_blocks': '-', 'mp_url': 'Error: Retrying...' })
def gitreleases(): url = 'https://api.github.com/repos/pxsocs/warden/releases' request = tor_request(url) try: data = request.json() except Exception: try: # Try again - some APIs return a json already data = json.loads(request) except Exception: data = json.dumps("Error getting request") return json.dumps(data)
def multiple_price_grab(tickers, fx): # tickers should be in comma sep string format like "BTC,ETH,LTC" and "USD,EUR" baseURL = \ "https://min-api.cryptocompare.com/data/pricemultifull?fsyms="\ + tickers + "&tsyms=" + fx + "&&api_key=9863dbe4217d98738f4ab58137007d24d70da92031584ba31de78137e0576225" try: request = tor_request(baseURL) except requests.exceptions.ConnectionError: return ("ConnectionError") try: data = request.json() except AttributeError: data = "ConnectionError" return (data)
def multiple_price_grab(tickers, fx): # tickers should be in comma sep string format like "BTC,ETH,LTC" baseURL = \ "https://min-api.cryptocompare.com/data/pricemultifull?fsyms="\ + tickers + "&tsyms=" + fx + "&&api_key=" + api try: request = tor_request(baseURL) except requests.exceptions.ConnectionError: return ("ConnectionError") try: data = request.json() except AttributeError: data = "ConnectionError" return (data)
def realtime(ticker, parsed=True): ''' Gets realtime prices using FMP Only Stocks are accepted Result: [ { "symbol": "AAPL", "price": 121.26000000, "volume": 164560045 } ] Limit reached Message: {'Error Message': 'Limit Reach . Please upgrade your plan or visit our documentation for more details at https://financialmodelingprep.com/developer/docs/pricing'} :param str ticker: Ticker or Symbol :return: Realtime price data :raises Exception: if Tor request returns a 403 (not authorized) ''' # Request data globalURL = 'https://financialmodelingprep.com/api/v3/quote-short/' + ticker globalURL += '?apikey=' + api response = tor_request(url=globalURL) if response.status_code == 403: response = requests.get(globalURL) data = response.json() if parsed: try: result = { 'symbol': data[0]['symbol'], 'name': None, 'price': data[0]['price'], 'fx': 'USD', 'time': datetime.utcnow(), 'timezone': 'utc', 'source': 'fmp' } return result except Exception: return None return data
def data_random_satoshi(): from node_warden import load_config config = load_config(quiet=True) url = config['QUOTES'].get('url') try: quotes = tor_request(url).json() except Exception: return (error(' >> Error contacting server. Retrying... ')) quote = quotes[randrange(len(quotes))] return_str = info(f"Satoshi Quotes | Subject: {quote['category']}\n") return_str += muted(f"{quote['date']} on {quote['medium']}\n") return_str += yellow(f"{quote['text']} \n\n") return_str += muted("Source: Nakamoto Institute") return (return_str)
def data_whitepaper(): from node_warden import launch_logger launch_logger() logging.info("Downloading Whitepaper >> bitcoin.pdf") try: from pathlib import Path filename = Path('bitcoin.pdf') url = 'https://bitcoin.org/bitcoin.pdf' response = tor_request(url) filename.write_bytes(response.content) logging.info(success("File bitcoin.pdf saved [Success]")) except Exception as e: logging.error( warning( f" Could not download bitcoin.pdf >> error: {e} [ERROR]"))
def asset_list(term=None): master_list = [] try: url = f'https://financialmodelingprep.com/api/v3/search?query={term}&limit=10&apikey=d44fb36a0c62da8ff9b1b40b47802000' result = tor_request(url).json() for item in result: master_list.append({ 'symbol': item['symbol'], 'name': item['name'], 'provider': 'fp_stock', 'notes': item['exchangeShortName'], 'fx': item['currency'] }) except Exception: pass return (master_list)
def multiple_price_grab(tickers, fx): from node_warden import load_config config = load_config(quiet=True) api_key = config['API'].get('cryptocompare') # tickers should be in comma sep string format like "BTC,ETH,LTC" and "USD,EUR" baseURL = \ "https://min-api.cryptocompare.com/data/pricemultifull?fsyms="\ + tickers + "&tsyms=" + fx + "&&api_key=" + api_key try: request = tor_request(baseURL) except requests.exceptions.ConnectionError: return ("ConnectionError") try: data = request.json() except AttributeError: data = "ConnectionError" return (data)
def asset_list(term=None): master_list = [] try: url = 'https://min-api.cryptocompare.com/data/all/coinlist' result = tor_request(url).json() result = result['Data'] for key, value in result.items(): if term.upper() in value['Symbol'].upper() or term.upper( ) in value['FullName'].upper().upper(): master_list.append({ 'symbol': value['Symbol'], 'name': value['FullName'], 'provider': 'cc_digital' }) except Exception: pass return (master_list)
def realtime(ticker, fxs='USD', parsed=True): ''' Gets realtime prices using CryptoCompare Only Cryptocurrencies are accepted Result: {'BTC': 0.03041, 'USD': 1354.75, 'GBP': 975.18} :param str ticker: Ticker or Symbol :param str fxs: a string of a single currency or comma separated currencies. ex: 'USD' or 'USD,EUR' :return: Realtime price data :raises Exception: if Tor request returns a 403 (not authorized) ''' # Request data globalURL = 'https://min-api.cryptocompare.com/data/price?fsym=' + ticker globalURL += '&tsyms=' + fxs try: response = tor_request(url=globalURL) if response.status_code == 403: response = requests.get(globalURL) except Exception: return None data = response.json() # PARSED DATA only returns the first FX if parsed: try: fx = fxs.split(',')[0] result = { 'symbol': ticker, 'name': None, 'price': data[fx], 'fx': fx, 'time': datetime.utcnow(), 'timezone': 'utc', 'source': 'cryptocompare' } return result except Exception: return None return data
def realtime(ticker, fx='USD', function='CURRENCY_EXCHANGE_RATE', parsed=True): if function == 'CURRENCY_EXCHANGE_RATE': # Request data globalURL = 'https://www.alphavantage.co/query?function=' + function globalURL += '&from_currency=' + ticker globalURL += '&to_currency=' + fx globalURL += '&apikey=' + api # No need for any API calls to return 1 :) if ticker == fx: return ({ 'Realtime Currency Exchange Rate': { '1. From_Currency Code': ticker, '2. From_Currency Name': ticker, '3. To_Currency Code': fx, '4. To_Currency Name': fx, '5. Exchange Rate': '1', '6. Last Refreshed': datetime.utcnow(), '7. Time Zone': 'UTC', '8. Bid Price': '1', '9. Ask Price': '1' } }) # SAMPLE RETURN DATA # {'Realtime Currency Exchange Rate': # {'1. From_Currency Code': 'BTC', # '2. From_Currency Name': 'Bitcoin', # '3. To_Currency Code': 'USD', # '4. To_Currency Name': 'United States Dollar', # '5. Exchange Rate': '44541.42000000', # '6. Last Refreshed': '2021-02-28 13:07:01', # '7. Time Zone': 'UTC', # '8. Bid Price': '44541.42000000', # '9. Ask Price': '44541.43000000'}} if function == 'GLOBAL_QUOTE': globalURL = 'https://www.alphavantage.co/query?function=' + function globalURL += '&symbol=' + ticker globalURL += '&apikey=' + api # SAMPLE RETURN DATA # {'Global Quote': # {'01. symbol': 'GBTC', # '02. open': '43.7000', # '03. high': '45.6000', # '04. low': '40.8000', # '05. price': '43.2000', # '06. volume': '21947497', # '07. latest trading day': '2021-02-26', # '08. previous close': '48.4000', # '09. change': '-5.2000', # '10. change percent': '-10.7438%' # } # } response = tor_request(url=globalURL) try: if response.status_code == 403: response = requests.get(globalURL) except AttributeError: return None data = response.json() # Parse the data so it's in the standard format for realtime data # { # 'symbol': # 'price': # 'fx' : # 'time': # 'timezone': # } if parsed: try: if function == 'CURRENCY_EXCHANGE_RATE': data = data['Realtime Currency Exchange Rate'] result = { 'symbol': ticker, 'name': data['2. From_Currency Name'], 'price': data['5. Exchange Rate'], 'fx': fx, 'time': data['6. Last Refreshed'], 'timezone': data['7. Time Zone'], 'source': 'alphavantage' } return result if function == 'GLOBAL_QUOTE': result = { 'symbol': ticker, 'name': None, 'price': data['Global Quote']['05. price'], 'high': data['Global Quote']['03. high'], 'open': data['Global Quote']['02. open'], 'chg': data['Global Quote']['10. change percent'], 'volume': data['Global Quote']['06. volume'], 'fx': 'USD', 'time': data['Global Quote']['07. latest trading day'], 'timezone': 'US/Eastern', 'source': 'Alphavantage Stocks' } return result except Exception: return None return data
def historical(ticker, function='TIME_SERIES_DAILY_ADJUSTED', fx='USD', parsed=True): if function == 'TIME_SERIES_DAILY_ADJUSTED': globalURL = 'https://www.alphavantage.co/query?function=' + function globalURL += '&symbol=' + ticker globalURL += '&outputsize=full&apikey=' + api # Sample Result # "Meta Data": { # "1. Information": "Daily Prices (open, high, low, close) and Volumes", # "2. Symbol": "IBM", # "3. Last Refreshed": "2021-02-26", # "4. Output Size": "Compact", # "5. Time Zone": "US/Eastern" # }, # "Time Series (Daily)": { # "2021-02-26": { # "1. open": "122.2500", # "2. high": "122.2500", # "3. low": "118.8800", # "4. close": "118.9300", # "5. volume": "8868848" # }, if function == 'DIGITAL_CURRENCY_DAILY': globalURL = 'https://www.alphavantage.co/query?function=' + function globalURL += '&symbol=' + ticker globalURL += '&market=' + fx globalURL += '&apikey=' + api # Sample Result # { # "Meta Data": { # "1. Information": "Daily Prices and Volumes for Digital Currency", # "2. Digital Currency Code": "BTC", # "3. Digital Currency Name": "Bitcoin", # "4. Market Code": "CNY", # "5. Market Name": "Chinese Yuan", # "6. Last Refreshed": "2021-02-28 00:00:00", # "7. Time Zone": "UTC" # }, # "Time Series (Digital Currency Daily)": { # "2021-02-28": { # "1a. open (CNY)": "298429.05591000", # "1b. open (USD)": "46103.67000000", # "2a. high (CNY)": "301526.96898000", # "2b. high (USD)": "46582.26000000", # "3a. low (CNY)": "295091.83603000", # "3b. low (USD)": "45588.11000000", # "4a. close (CNY)": "298880.48293000", # "4b. close (USD)": "46173.41000000", # "5. volume": "2680.54607000", # "6. market cap (USD)": "2680.54607000" if function == 'FX_DAILY': globalURL = 'https://www.alphavantage.co/query?function=' + function globalURL += '&from_symbol=' + ticker globalURL += '&to_symbol=' + fx globalURL += '&market=' + fx globalURL += '&outputsize=full&apikey=' + api # Sample Result # { # "Meta Data": { # "1. Information": "Forex Daily Prices (open, high, low, close)", # "2. From Symbol": "EUR", # "3. To Symbol": "USD", # "4. Output Size": "Full size", # "5. Last Refreshed": "2021-02-26 21:55:00", # "6. Time Zone": "UTC" # }, # "Time Series FX (Daily)": { # "2021-02-26": { # "1. open": "1.2159", # "2. high": "1.2183", # "3. low": "1.2060", # "4. close": "1.2072" # }, response = tor_request(url=globalURL) if response.status_code == 403: response = requests.get(globalURL) data = response.json() if parsed: if function == 'DIGITAL_CURRENCY_DAILY': try: if 'Time Series (Digital Currency Daily)' in data: df = pd.DataFrame.from_dict( data['Time Series (Digital Currency Daily)'], orient="index") if 'Time Series FX (Daily)' in data: df = pd.DataFrame.from_dict(data['Time Series FX (Daily)'], orient="index") # Clean columns for i in range(0, 7): for string in ['a', 'b', 'c', 'd', 'e', 'f']: df.columns = df.columns.str.replace( f'{i}{string}. ', '') df = df.rename( columns={ 'close (USD)': 'close', 'open (USD)': 'open', 'high (USD)': 'high', 'low (USD)': 'low' }) df_save = df[['close', 'open', 'high', 'low']] df_save.index.names = ['date'] except Exception: df_save = pd.DataFrame() return (df_save) if function == 'TIME_SERIES_DAILY_ADJUSTED' or function == 'FX_DAILY': try: if 'Time Series FX (Daily)' in data: df = pd.DataFrame.from_dict(data['Time Series FX (Daily)'], orient="index") if 'Time Series (Daily)' in data: df = pd.DataFrame.from_dict(data['Time Series (Daily)'], orient="index") df = df.rename( columns={ '4. close': 'close', '1. open': 'open', '2. high': 'high', '3. low': 'low' }) df_save = df[['close', 'open', 'high', 'low']] df_save.index.names = ['date'] except Exception: df_save = pd.DataFrame() return (df_save) return data
def check_cryptocompare(): with yaspin(text=f"Testing price grab from Cryptocompare", color="green") as spinner: config = load_config(True) api_key = config['API'].get('cryptocompare') # tickers should be in comma sep string format like "BTC,ETH,LTC" and "USD,EUR" baseURL = ( "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=BTC" + "&tsyms=USD&api_key=" + api_key) try: request = tor_request(baseURL) except requests.exceptions.ConnectionError: spinner.fail("💥 ") spinner.write( warning(" Connection Error - check internet connection")) exit() data = request.json() try: if data['Response'] == 'Error': config_file = os.path.join(basedir, 'config.ini') spinner.fail("💥 ") spinner.write(warning(" CryptoCompare Returned an error")) print(" " + data['Message']) if data['Message'] == 'You are over your rate limit please upgrade your account!': # First try to get a random API KEY if config['API'].getboolean('random') is not True: print( " Looks like you are over the API Limit. Will try to generate a random API." ) size = 16 import binascii random_key = binascii.b2a_hex(os.urandom(size)) config['API']['random'] = 'True' config['API']['cryptocompare'] = str( random_key.decode("utf-8")) with open(config_file, 'w') as configfile: config.write(configfile) check_cryptocompare() return print( ' -----------------------------------------------------------------' ) print( yellow(" Looks like you need to get an API Key. ")) print( yellow(" The WARden comes with a shared key that")) print(yellow(" eventually gets to the call limit.")) print( ' -----------------------------------------------------------------' ) print( blue( ' Go to: https://www.cryptocompare.com/cryptopian/api-keys' )) print(muted(" Current API:")) print(f" {api_key}") new_key = input(' Enter new API key (Q to quit): ') if new_key == 'Q' or new_key == 'q': exit() config['API']['cryptocompare'] = new_key with open(config_file, 'w') as configfile: config.write(configfile) check_cryptocompare() except KeyError: try: btc_price = (data['DISPLAY']['BTC']['USD']['PRICE']) spinner.ok("✅ ") spinner.write(success(f" BTC price is: {btc_price}")) return except Exception: spinner.fail("💥 ") spinner.write( warning(" CryptoCompare Returned an UNKNOWN error")) print(data) return (data)
def specter_auth(): if request.method == 'GET': templateData = { "title": "Login to Specter", "current_app": current_app, "current_user": current_user } return (render_template('warden/specter_auth.html', **templateData)) if request.method == 'POST': from message_handler import Message current_app.message_handler.clean_category('Specter Connection') url = request.form.get('url') url = url_parser(url) # Try to ping this url if 'onion' not in url: try: status_code = requests.head(url).status_code except Exception as e: flash(f'Please check Specter URL. Error: {e}', 'danger') else: try: status_code = tor_request(url).status_code except Exception as e: flash(f'Please check Specter URL. Error: {e}', 'danger') try: if int(status_code) < 400: message = Message( category='Specter Connection', message_txt='Pinging URL', notes= f"{url}<br> ping <span class='text-success'>✅ Success</span>" ) current_app.message_handler.add_message(message) else: flash('Please check Specter URL (unreacheable)', 'danger') return redirect(url_for('warden.specter_auth')) except Exception as e: flash(f'Error Connecting. Error: {e}', 'danger') return redirect(url_for('warden.specter_auth')) # Try to authenticate try: current_app.specter.base_url = url current_app.specter.login_url = url + 'auth/login' current_app.specter.tx_url = url + 'wallets/wallets_overview/txlist' current_app.specter.core_url = url + 'settings/bitcoin_core?' current_app.specter.login_payload = { 'username': request.form.get('username'), 'password': request.form.get('password') } session = current_app.specter.init_session() session.close() except Exception as e: flash(f'Error logging in to Specter: {e}', 'danger') return redirect(url_for('warden.specter_auth')) current_app.downloading = True current_app.settings['SPECTER']['specter_url'] = url current_app.settings['SPECTER']['specter_login'] = request.form.get( 'username') current_app.settings['SPECTER']['specter_password'] = request.form.get( 'password') update_config() current_app.specter = Specter() current_app.specter.refresh_txs(load=False) flash("Success. Connected to Specter Server.", "success") # Now allow download of all txs in background on next run return redirect(url_for('warden.warden_page'))
def init_app(app): from ansi_management import (warning, success, error) from utils import (create_config, runningInDocker) from config import Config from connections import tor_request warnings.filterwarnings('ignore') # Load config.ini into app # -------------------------------------------- # Read Global Variables from warden.config(s) # Can be accessed like a dictionary like: # app.settings['PORTFOLIO']['RENEW_NAV'] # -------------------------------------------- config_file = Config.config_file app.warden_status = {} # Check for internet connection internet_ok = internet_connected() if internet_ok is True: print(success("✅ Internet Connection")) else: print( error( "[!] WARden needs internet connection. Check your connection.") ) print(warning("[!] Exiting")) exit() # Config config_settings = configparser.ConfigParser() if os.path.isfile(config_file): config_settings.read(config_file) app.warden_status['initial_setup'] = False print( success( "✅ Config Loaded from config.ini - edit it for customization" )) else: print( error( " Config File could not be loaded, created a new one with default values..." )) create_config(config_file) config_settings.read(config_file) app.warden_status['initial_setup'] = True table_error = False try: # create empty instance of LoginManager app.login_manager = LoginManager() except sqlite3.OperationalError: table_error = True # Create empty instance of SQLAlchemy app.db = SQLAlchemy() app.db.init_app(app) # Import models so tables are created from models import Trades, User, AccountInfo, TickerInfo, SpecterInfo app.db.create_all() # There was an initial error on getting users # probably because tables were not created yet. # The above create_all should have solved it so try again. if table_error: # create empty instance of LoginManager app.login_manager = LoginManager() # If login required - go to login: app.login_manager.login_view = "warden.login" # To display messages - info class (Bootstrap) app.login_manager.login_message_category = "secondary" app.login_manager.init_app(app) # Create empty instance of messagehandler from message_handler import MessageHandler app.message_handler = MessageHandler() app.message_handler.clean_all() # Get Version print("") try: version_file = Config.version_file with open(version_file, 'r') as file: current_version = file.read().replace('\n', '') except Exception: current_version = 'unknown' with app.app_context(): app.version = current_version # Check if there are any users on database, if not, needs initial setup users = User.query.all() if users == []: app.warden_status['initial_setup'] = True # Check for Cryptocompare API Keys print("") check_cryptocompare() print("") print(f"[i] Running WARden version: {current_version}") app.warden_status['running_version'] = current_version # CHECK FOR UPGRADE repo_url = 'https://api.github.com/repos/pxsocs/warden/releases' try: github_version = tor_request(repo_url).json()[0]['tag_name'] except Exception: github_version = None app.warden_status['github_version'] = github_version if github_version: print(f"[i] Newest WARden version available: {github_version}") parsed_github = version.parse(github_version) parsed_version = version.parse(current_version) app.warden_status['needs_upgrade'] = False if parsed_github > parsed_version: print(warning(" [i] Upgrade Available")) app.warden_status['needs_upgrade'] = True if parsed_github == parsed_version: print(success("✅ You are running the latest version")) else: print(warning("[!] Could not check GitHub for updates")) print("") # Check if config.ini exists with app.app_context(): app.settings = config_settings with app.app_context(): try: from utils import fxsymbol app.fx = fxsymbol(config_settings['PORTFOLIO']['base_fx'], 'all') except KeyError: # Problem with this config, reset print(error(" [!] Config File needs to be rebuilt")) print("") create_config(config_file) # TOR Server through Onion Address -- # USE WITH CAUTION - ONION ADDRESSES CAN BE EXPOSED! # WARden needs to implement authentication (coming soon) if app.settings['SERVER'].getboolean('onion_server'): from stem.control import Controller from urllib.parse import urlparse app.tor_port = app.settings['SERVER'].getint('onion_port') app.port = app.settings['SERVER'].getint('port') from warden_modules import home_path toraddr_file = os.path.join(home_path(), "onion.txt") app.save_tor_address_to = toraddr_file proxy_url = "socks5h://localhost:9050" tor_control_port = "" try: tor_control_address = urlparse(proxy_url).netloc.split(":")[0] if tor_control_address == "localhost": tor_control_address = "127.0.0.1" app.controller = Controller.from_port( address=tor_control_address, port=int(tor_control_port) if tor_control_port else "default", ) except Exception: app.controller = None from tor import start_hidden_service start_hidden_service(app) from routes import warden from errors.handlers import errors from api.routes import api from csv_routes.routes import csv_routes from user_routes.routes import user_routes from simulator.routes import simulator app.register_blueprint(warden) app.register_blueprint(errors) app.register_blueprint(api) app.register_blueprint(csv_routes) app.register_blueprint(user_routes) app.register_blueprint(simulator) # Prepare app to receive Specter Server info # For the first load, just get a saved file if available # The background jobs will update later with app.app_context(): from specter_importer import Specter app.specter = Specter() app.specter.refresh_txs(load=True) app.downloading = False with app.app_context(): app.runningInDocker = runningInDocker() with app.app_context(): app.tor = create_tor() # Check if home folder exists, if not create home = str(Path.home()) home_path = os.path.join(home, 'warden/') try: os.makedirs(os.path.dirname(home_path)) except Exception: pass # Start Schedulers from backgroundjobs import (background_settings_update, background_specter_update, background_scan_network, background_specter_health, background_mempool_seeker) def bk_su(): with app.app_context(): background_specter_update() def bk_stu(): with app.app_context(): background_settings_update() def bk_scan(): with app.app_context(): background_scan_network() def bk_specter_health(): with app.app_context(): background_specter_health() def bk_mempool_health(): with app.app_context(): background_mempool_seeker() app.scheduler = BackgroundScheduler() app.scheduler.add_job(bk_su, 'interval', seconds=1) app.scheduler.add_job(bk_stu, 'interval', seconds=1) app.scheduler.add_job(bk_scan, 'interval', seconds=1) app.scheduler.add_job(bk_specter_health, 'interval', seconds=1) app.scheduler.add_job(bk_mempool_health, 'interval', seconds=1) app.scheduler.start() print(success("✅ Background jobs running")) print("") app.app_context().push() print(success("✅ Application startup is complete")) return app
def autodetect(url): url = url_parser(url) request = tor_request(url)
def data_mempool(): from node_warden import load_config from node_warden import launch_logger launch_logger() config = load_config(quiet=True) mp_config = config['MEMPOOL'] url = mp_config.get('url') tabs = [] # Get recommended fees mp_fee = tor_request(url + '/api/v1/fees/recommended').json() tabs = list(mp_fee.values()) tabs = [[str(x) + ' sats/Vb' for x in tabs]] tabs = tabulate(tabs, headers=["Fastest Fee", "30 min fee", "1 hour fee"], colalign=["center", "center", "center"]) try: block_height = tor_request(url + '/api/blocks/tip/height').json() except Exception: return (error(f' >> Error getting data from {url}. Retrying...')) # Save the latest block height saved_block = pickle_it(action='load', filename='block.pkl') if (saved_block != block_height) and ( config['MEMPOOL'].getboolean('block_found_sound')): # Block found play sound try: engine = pyttsx3.init() engine.setProperty('rate', 270) engine.say(config['MEMPOOL'].get('block_found_txt')) engine.runAndWait() except Exception: pass logging.info( info('[MEMPOOL] ') + success("A new Bitcoin Block was just found. ") + yellow("'Tick. Tock. Next block.'")) pickle_it(action='save', filename='block.pkl', data=block_height) block_txt = success(f' Block Height: {jformat(block_height, 0)}\n\n') tabs = block_txt + info(' Mempool Fee Estimates: \n') + tabs try: mp_blocks = tor_request(url + '/api/blocks').json() except Exception: return (error(" >> Error getting Mempool data. Retrying...")) mp_tabs = [] gradient_color = 0 for block in mp_blocks: mp_tabs.append([ time_ago(block['timestamp']), jformat(block['height'], 0), jformat(block['tx_count'], 0), jformat(block['size'], 2, 1000000) + ' MB' ]) gradient_color += 1 mp_tabs = tabulate(mp_tabs, headers=[" Time", "Height", "Tx Count", "Size"], colalign=["right", "center", "center", "right"]) tabs += info('\n\n Latest Blocks: \n') + mp_tabs tabs += muted(f"\n\n Source: {url} {success('[Tor Request]')}\n") return tabs
def historical(ticker, parsed=True): ''' Gets historical prices using FMP Only Stocks are accepted Result: { "symbol" : "AAPL", "historical" : [ { "date" : "2021-02-26", "open" : 122.589996, "high" : 124.849998, "low" : 121.199997, "close" : 121.260002, "adjClose" : 121.260002, "volume" : 1.6432E8, "unadjustedVolume" : 1.6432E8, "change" : -1.32999, "changePercent" : -1.085, "vwap" : 122.43667, "label" : "February 26, 21", "changeOverTime" : -0.01085 }, {...}, ...], } API Limit result: { "Error Message": "Limit Reach . Please upgrade your plan or visit our documentation for more details at https://financialmodelingprep.com/developer/docs/pricing " } :param str ticker: Ticker or Symbol :return: Historical price data :raises Exception: if Tor request returns a 403 (not authorized) ''' globalURL = 'https://financialmodelingprep.com/api/v3/historical-price-full/' + ticker globalURL += '?apikey=' + api response = tor_request(url=globalURL) if response.status_code == 403: response = requests.get(globalURL) data = response.json() if parsed: try: df = pd.DataFrame.from_records(data['historical']) df = df.rename( columns={ 'close': 'close', 'open': 'open', 'high': 'high', 'low': 'low', 'volume': 'volume' }) df.set_index('date', inplace=True) df_save = df[['close', 'open', 'high', 'low', 'volume']] except Exception: df_save = pd.DataFrame() return (df_save) return data
def data_btc_price(): from node_warden import launch_logger launch_logger() from node_warden import load_config config = load_config(quiet=True) fx_config = config['CURRENCIES'] currencies = ast.literal_eval(fx_config.get('fx_list')) primary_fx = ast.literal_eval(fx_config.get('primary_fx')) price_data = multiple_price_grab('BTC', ','.join(currencies)) # Get prices in different currencies tabs = [] btc_usd_price = 0 for fx in currencies: try: price_str = price_data['DISPLAY']['BTC'][fx]['PRICE'] chg_str = price_data['DISPLAY']['BTC'][fx]['CHANGEPCTDAY'] high = price_data['DISPLAY']['BTC'][fx]['HIGHDAY'] low = price_data['DISPLAY']['BTC'][fx]['LOWDAY'] market = muted(price_data['DISPLAY']['BTC'][fx]['LASTMARKET']) try: chg = float(chg_str) if chg >= 0: chg_str = success('+' + chg_str + '%') elif chg < 0: chg_str = error(chg_str + '%') except Exception: chg_str = muted(chg_str + '%') if fx == 'USD': btc_usd_price = cleanfloat(price_str) if fx == primary_fx: fx = info(fx) tabs.append( [u' ' + fx, price_str, chg_str, low + ' - ' + high, market]) except Exception as e: tabs.append(['error: ' + str(e)]) tabs = tabulate( tabs, headers=['Fiat', 'Price', '% change', '24h Range', 'Source'], colalign=["center", "right", "right", "center", "right"]) # GBTC gbtc_config = config['STOCKS'] try: if gbtc_config.getboolean('GBTC_enabled'): tabs += '\n\n' gbtc_url = 'https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=GBTC&apikey=DDC232JDH' gbtc_data = tor_request(gbtc_url).json()['Global Quote'] gbtc_tabs = [] GBTC_shares = gbtc_config.getfloat('gbtc_shares') fairvalue, premium = (GBTC_premium(float(gbtc_data['05. price']), btc_usd_price, GBTC_shares)) if premium * 1 > 0: premium = success('+' + jformat(premium, 2, 0.01) + '%') elif premium * 1 < 0: premium = error(jformat(premium, 2, 0.01) + '%') fairvalue = jformat(fairvalue, 2) chg_str = gbtc_data['10. change percent'] try: chg = cleanfloat(chg_str) if chg > 0: chg_str = success('+' + jformat(chg, 2) + ' %') elif chg < 0: chg_str = error(jformat(chg, 2) + ' %') except Exception: chg_str = muted(chg_str) gbtc_tabs.append([ 'GBTC', gbtc_data['05. price'], chg_str, gbtc_data['04. low'] + ' - ' + gbtc_data['03. high'], premium, fairvalue, gbtc_data['07. latest trading day'] ]) gbtc_tabs = tabulate(gbtc_tabs, headers=[ 'Ticker', 'Price', '% change', '24h Range', 'Premium', 'Fair Value', 'Last Update' ], colalign=[ "center", "right", "right", "center", "right", "right", "right" ]) tabs += gbtc_tabs except Exception as e: er_st = error(f' Error getting GBTC data: {e}') tabs += er_st tabs += ( f"\n\n Last Refresh on: {info(datetime.now().strftime('%H:%M:%S'))}") return tabs
def data_btc_price(): from node_warden import launch_logger launch_logger() from node_warden import load_config config = load_config(quiet=True) fx_config = config['CURRENCIES'] currencies = ast.literal_eval(fx_config.get('fx_list')) primary_fx = ast.literal_eval(fx_config.get('primary_fx')) price_data = multiple_price_grab('BTC', ','.join(currencies)) # Get prices in different currencies tabs = [] btc_usd_price = 0 for fx in currencies: try: price_str = price_data['DISPLAY']['BTC'][fx]['PRICE'] chg_str = price_data['DISPLAY']['BTC'][fx]['CHANGEPCTDAY'] high = price_data['DISPLAY']['BTC'][fx]['HIGHDAY'] low = price_data['DISPLAY']['BTC'][fx]['LOWDAY'] market = muted(price_data['DISPLAY']['BTC'][fx]['LASTMARKET']) try: chg = float(chg_str) if chg >= 0: chg_str = success('+' + chg_str + '%') elif chg < 0: chg_str = error(chg_str + '%') except Exception: chg_str = muted(chg_str + '%') if fx == 'USD': btc_usd_price = cleanfloat(price_str) if fx == primary_fx: fx = info(fx) tabs.append( [u' ' + fx, price_str, chg_str, low + ' - ' + high, market]) except Exception as e: tabs.append(['error: ' + str(e)]) if tabs == []: return ( error(f' >> Error getting data from CryptoCompare. Retrying...')) try: tabs = tabulate( tabs, headers=['Fiat', 'Price', '% change', '24h Range', 'Source'], colalign=["center", "right", "right", "center", "right"]) except Exception: return ( error(f' >> Error getting data from CryptoCompare. Retrying...')) # GBTC gbtc_config = config['STOCKS'] try: if gbtc_config.getboolean('GBTC_enabled'): tabs += '\n\n' gbtc_url = 'https://finnhub.io/api/v1/quote?symbol=GBTC&token=bvfhuqv48v6rhdtvnks0' gbtc_data = tor_request(gbtc_url).json() gbtc_tabs = [] GBTC_shares = gbtc_config.getfloat('gbtc_shares') fairvalue, premium = (GBTC_premium((gbtc_data['c']), btc_usd_price, GBTC_shares)) if premium * 1 > 0: premium = success('+' + jformat(premium, 2, 0.01) + '%') elif premium * 1 < 0: premium = error(jformat(premium, 2, 0.01) + '%') fairvalue = jformat(fairvalue, 2) chg_str = gbtc_data['c'] / gbtc_data['pc'] try: chg = (chg_str) if chg > 0: chg_str = success('+' + jformat(chg, 2) + ' %') elif chg < 0: chg_str = error(jformat(chg, 2) + ' %') except Exception: chg_str = muted(chg_str) gbtc_tabs.append([ 'GBTC', jformat(gbtc_data['c'], 2), chg_str, jformat(gbtc_data['l'], 2) + ' - ' + jformat(gbtc_data['h'], 2), premium, fairvalue, time_ago(gbtc_data['t']) ]) gbtc_tabs = tabulate(gbtc_tabs, headers=[ 'Ticker', 'Price', '% change', '24h Range', 'Premium', 'Fair Value', 'Last Update' ], colalign=[ "center", "right", "right", "center", "right", "right", "right" ]) tabs += gbtc_tabs except Exception as e: er_st = error(f' Error getting GBTC data: {e}') tabs += er_st tabs += ( f"\n\n Last Refresh on: {info(datetime.now().strftime('%H:%M:%S'))}") return tabs