Last active
August 28, 2021 08:24
-
-
Save m0nochr0me/080b224f2805db889931c1b4ad1d04c8 to your computer and use it in GitHub Desktop.
Crypto Monitor App
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
title=Crypto Monitor | |
author=m0nochr0me | |
orientation=landscape |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[app] | |
title = Crypto Monitor | |
package.name = cryptomonitor | |
package.domain = org.test | |
source.dir = . | |
source.include_exts = py,png,jpg,kv,atlas | |
version = 0.0.2 | |
requirements = python3, pillow, plyer, kivy==master, git+https://github.com/HeaTTheatR/KivyMD.git, sdl2_ttf==2.0.15 | |
orientation = landscape | |
osx.python_version = 3 | |
osx.kivy_version = 1.9.1 | |
fullscreen = 1 | |
android.permissions = INTERNET | |
android.skip_update = False | |
android.accept_sdk_license = True | |
android.arch = armeabi-v7a | |
p4a.branch = develop | |
ios.kivy_ios_url = https://github.com/kivy/kivy-ios | |
ios.kivy_ios_branch = master | |
ios.ios_deploy_url = https://github.com/phonegap/ios-deploy | |
ios.ios_deploy_branch = 1.7.0 | |
[buildozer] | |
log_level = 2 | |
warn_on_root = 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from time import strftime | |
from kivy.lang import Builder | |
from kivy.properties import NumericProperty, StringProperty, BooleanProperty, ColorProperty | |
from kivy.clock import Clock | |
from kivy.network.urlrequest import UrlRequest | |
from kivymd.app import MDApp | |
from kivy.uix.boxlayout import BoxLayout | |
import plyer | |
import json | |
KV = ''' | |
MDScreen: | |
BoxLayout: | |
orientation: "vertical" | |
MDToolbar: | |
title: "Crypto Monitor" | |
left_action_items: [['menu', lambda x: nav_drawer.set_state()], ['refresh', lambda x: app.update()]] | |
MDIcon: | |
halign: "right" | |
icon: app.btc_fng_icon | |
theme_text_color: "Custom" | |
size_hint_x: 0.125 | |
text_color: app.btc_fng_color | |
MDLabel: | |
font_style: "Caption" | |
theme_text_color: "Secondary" | |
halign: "right" | |
font_size: self.width/20 | |
text: "Last Update: " + app.last_update | |
MDToolbar: | |
height: '16sp' | |
md_bg_color: app.theme_cls.accent_color | |
MDLabel: | |
font_style: "Overline" | |
theme_text_color: "Secondary" | |
font_size: "14sp" | |
halign: "right" | |
size_hint_x: 0.5 | |
text: "BTC: ${:.2f}".format(app.btc_usd) | |
MDLabel: | |
font_style: "Overline" | |
theme_text_color: "Secondary" | |
font_size: "14sp" | |
halign: "right" | |
size_hint_x: 0.5 | |
text: "ETH: ${:.2f}".format(app.eth_usd) | |
MDGridLayout: | |
rows: 2 | |
padding: 6 | |
spacing: 6 | |
MDCard: | |
orientation: "vertical" | |
padding: 8 | |
size_hint: 1, 1 | |
MDBoxLayout: | |
size_hint_y: 0.025 | |
MDLabel: | |
font_style: "Caption" | |
theme_text_color: "Secondary" | |
size_hint_y: None | |
halign: "center" | |
height: self.texture_size[1] | |
text: "Slushpool Stats" | |
MDSpinner: | |
size_hint: .0025, .0025 | |
pos_hint: {'center_x': .5, 'center_y': .5} | |
active: app.slushpool_spinner | |
MDSeparator: | |
height: "1dp" | |
MDLabel: | |
halign: "center" | |
font_style: "Button" | |
font_size: self.width/8 | |
size_hint: 1, 0.3 | |
text: "{:.3f} TH/s".format(app.slushpool_hashrate) | |
MDLabel: | |
halign: "center" | |
font_style: "Caption" | |
font_size: self.width/24 | |
size_hint: 1, 0.1 | |
theme_text_color: "Secondary" | |
text: "Workers: {}".format(app.btc_ok_workers) | |
MDCard: | |
orientation: "vertical" | |
padding: 8 | |
size_hint: 1, 1 | |
MDBoxLayout: | |
size_hint_y: 0.025 | |
MDLabel: | |
font_style: "Caption" | |
theme_text_color: "Secondary" | |
size_hint_y: None | |
halign: "center" | |
valign: "center" | |
height: self.texture_size[1] | |
text: "Slushpool reward" | |
MDSpinner: | |
size_hint: .0025, .0025 | |
pos_hint: {'center_x': .5, 'center_y': .5} | |
active: app.slushpool_spinner | |
MDSeparator: | |
height: "1dp" | |
MDGridLayout: | |
rows: 2 | |
cols: 1 | |
padding: 2 | |
size_hint: 1, .3 | |
MDCard: | |
orientation: "vertical" | |
padding: 1 | |
size_hint: 1, 1 | |
elevation: 0 | |
MDLabel: | |
text: "confirmed:" | |
font_style: "Overline" | |
theme_text_color: "Secondary" | |
size_hint_y: 0.025 | |
MDLabel: | |
halign: "center" | |
font_style: "Button" | |
font_size: self.width/8 | |
size_hint: 1, 0.1 | |
markup: | |
text: "{:.8f}".format(app.slushpool_reward_confirmed) | |
MDCard: | |
orientation: "vertical" | |
padding: 1 | |
size_hint: 1, 1 | |
elevation: 0 | |
MDLabel: | |
text: "unconfirmed:" | |
font_style: "Overline" | |
theme_text_color: "Secondary" | |
size_hint_y: 0.025 | |
MDLabel: | |
halign: "center" | |
font_style: "Button" | |
font_size: self.width/8 | |
size_hint: 1, 0.1 | |
text: "{:.8f}".format(app.slushpool_reward) | |
MDCard: | |
orientation: "vertical" | |
padding: 8 | |
size_hint: 1, 1 | |
MDBoxLayout: | |
size_hint_y: 0.025 | |
MDLabel: | |
font_style: "Caption" | |
theme_text_color: "Secondary" | |
size_hint_y: None | |
halign: "center" | |
height: self.texture_size[1] | |
text: "BTC Balance" | |
MDSpinner: | |
size_hint: .0025, .0025 | |
pos_hint: {'center_x': .5, 'center_y': .5} | |
active: app.blockchain_spinner | |
MDSeparator: | |
height: "1dp" | |
MDLabel: | |
halign: "center" | |
font_style: "Button" | |
font_size: self.width/8 | |
size_hint: 1, 0.3 | |
text: "{:.8f}".format(app.btc_balance) | |
MDLabel: | |
halign: "center" | |
font_style: "Caption" | |
font_size: self.width/16 | |
theme_text_color: "Secondary" | |
size_hint: 1, 0.1 | |
text: "${:.2f}".format(app.usd_btc_balance) | |
MDCard: | |
orientation: "vertical" | |
padding: 8 | |
size_hint: 1, 1 | |
MDBoxLayout: | |
size_hint_y: 0.025 | |
MDLabel: | |
font_style: "Caption" | |
theme_text_color: "Secondary" | |
size_hint_y: None | |
halign: "center" | |
height: self.texture_size[1] | |
text: "ETH Balance" | |
MDSpinner: | |
size_hint: .0025, .0025 | |
pos_hint: {'center_x': .5, 'center_y': .5} | |
active: app.etherscan_spinner | |
MDSeparator: | |
height: "1dp" | |
MDLabel: | |
halign: "center" | |
font_style: "Button" | |
font_size: self.width/8 | |
size_hint: 1, 0.3 | |
text: "{:.8f}".format(app.eth_balance) | |
MDLabel: | |
halign: "center" | |
font_style: "Caption" | |
font_size: self.width/16 | |
theme_text_color: "Secondary" | |
size_hint: 1, 0.1 | |
text: "${:.2f}".format(app.usd_eth_balance) | |
MDNavigationDrawer: | |
id: nav_drawer | |
padding: 6 | |
MDBoxLayout: | |
orientation: "vertical" | |
spacing: 3 | |
MDTextField: | |
id: in_slushpool_api_key | |
font_size: self.width/24 | |
size_hint: 1, 1 | |
hint_text: "Slushpool API KEY" | |
MDTextField: | |
id: in_es_api_key | |
font_size: self.width/32 | |
size_hint: 1, 1 | |
hint_text: "Etherscan API KEY" | |
MDTextField: | |
id: in_btc_addr | |
font_size: self.width/32 | |
size_hint: 1, 1 | |
hint_text: "BTC Address" | |
MDTextField: | |
id: in_eth_addr | |
font_size: self.width/32 | |
size_hint: 1, 1 | |
hint_text: "ETH Address" | |
MDTextField: | |
id: in_update_interval | |
font_size: self.width/24 | |
size_hint: 1, 1 | |
hint_text: "Update interval (seconds)" | |
MDFlatButton: | |
text: "SAVE" | |
size_hint_x: 1 | |
on_press: app.save_config() | |
''' | |
class CryptoMonitor(MDApp): | |
slushpool_api_key = StringProperty('') | |
es_api_key = StringProperty('') | |
btc_addr = StringProperty('') | |
eth_addr = StringProperty('') | |
slushpool_hashrate = NumericProperty(0) | |
slushpool_reward = NumericProperty(0) | |
slushpool_reward_confirmed = NumericProperty(0) | |
eth_balance = NumericProperty(0) | |
usd_eth_balance = NumericProperty(0) | |
btc_balance = NumericProperty(0) | |
usd_btc_balance = NumericProperty(0) | |
btc_usd = NumericProperty(0) | |
eth_usd = NumericProperty(0) | |
btc_fng_icon = StringProperty('emoticon-neutral') | |
btc_fng_color = ColorProperty('#848484') | |
btc_ok_workers = NumericProperty(0) | |
slushpool_spinner = BooleanProperty(False) | |
etherscan_spinner = BooleanProperty(False) | |
blockchain_spinner = BooleanProperty(False) | |
update_interval = 60 | |
counter = update_interval | |
last_update = StringProperty('') | |
def build_config(self, config): | |
config.setdefaults('main', { | |
'slushpool_api_key': '', | |
'es_api_key': '', | |
'eth_addr': '', | |
'btc_addr': '', | |
'update_interval': 60 | |
}) | |
def build(self): | |
config = self.config | |
root = Builder.load_string(KV) | |
slushpool_api_key_field = root.ids.in_slushpool_api_key | |
self.slushpool_api_key = slushpool_api_key_field.text = config.get('main', 'slushpool_api_key') | |
es_api_key_field = root.ids.in_es_api_key | |
self.es_api_key = es_api_key_field.text = config.get('main', 'es_api_key') | |
btc_addr_field = root.ids.in_btc_addr | |
self.btc_addr = btc_addr_field.text = config.get('main', 'btc_addr') | |
eth_addr_field = root.ids.in_eth_addr | |
self.eth_addr = eth_addr_field.text = config.get('main', 'eth_addr') | |
update_interval_field = root.ids.in_update_interval | |
self.update_interval = update_interval_field.text = config.get('main', 'update_interval') | |
Clock.schedule_interval(self.update_counter, 1) | |
self.theme_cls.theme_style = "Dark" | |
self.theme_cls.primary_palette ="Purple" | |
self.theme_cls.primary_hue = "200" | |
config.orientation = 2 | |
return root | |
def save_config(self): | |
config = self.config | |
slushpool_api_key_field = self.root.ids.in_slushpool_api_key | |
self.slushpool_api_key = slushpool_api_key_field.text | |
config.set('main', 'slushpool_api_key', self.slushpool_api_key) | |
es_api_key_field = self.root.ids.in_es_api_key | |
self.es_api_key = es_api_key_field.text | |
config.set('main', 'es_api_key', self.es_api_key) | |
btc_addr_field = self.root.ids.in_btc_addr | |
self.btc_addr = btc_addr_field.text | |
config.set('main', 'btc_addr', self.btc_addr) | |
eth_addr_field = self.root.ids.in_eth_addr | |
self.eth_addr = eth_addr_field.text | |
config.set('main', 'eth_addr', self.eth_addr) | |
update_interval_field = self.root.ids.in_update_interval | |
self.update_interval = update_interval_field.text | |
config.set('main', 'update_interval', self.update_interval) | |
config.write() | |
def update_counter(self, *args): | |
self.counter += 1 | |
if self.counter < int(self.update_interval) + 5: | |
return | |
self.counter = 0 | |
self.update() | |
def update(self, *args): | |
self.counter = 0 | |
self.last_update = strftime("%D %H:%M") | |
self.slushpool_spinner = True | |
UrlRequest( | |
'https://slushpool.com/accounts/profile/json/btc/', | |
on_success=self.update_slushpool_cards, req_headers={"SlushPool-Auth-Token": self.slushpool_api_key}) | |
self.etherscan_spinner = True | |
UrlRequest( | |
'https://api.etherscan.io/api?module=account&action=balance&address=' + self.eth_addr + '&tag=latest&apikey=' + self.es_api_key, | |
on_success=self.update_etherscan_cards) | |
self.blockchain_spinner = True | |
UrlRequest( | |
'https://blockchain.info/balance?active=' + self.btc_addr, | |
on_success=self.update_blockchain_cards) | |
UrlRequest( | |
'https://api.coingate.com/v2/rates/merchant/BTC/USD', | |
on_success=self.update_coingate_btcusd) | |
UrlRequest( | |
'https://api.coingate.com/v2/rates/merchant/ETH/USD', | |
on_success=self.update_coingate_ethusd) | |
UrlRequest( | |
'https://api.alternative.me/fng/', | |
on_success=self.update_fng) | |
def update_fng(self, request, result): | |
try: | |
fng = int(result['data'][0]['value']) | |
print(fng) | |
if fng < 50: | |
self.btc_fng_color = '#FF5D5D' | |
self.btc_fng_icon = 'emoticon-dead' | |
elif fng == 50: | |
self.btc_fng_color = '#FFF35D' | |
self.btc_fng_icon = 'emoticon-neutral' | |
else: | |
self.btc_fng_color = '#7EFF5D' | |
self.btc_fng_icon = 'emoticon' | |
except: | |
print('Update FNG error') | |
def update_coingate_btcusd(self, request, result): | |
try: | |
self.btc_usd = float(result) | |
except: | |
print('Update coingate error') | |
def update_coingate_ethusd(self, request, result): | |
try: | |
self.eth_usd = float(result) | |
except: | |
print('Update coingate error') | |
def update_slushpool_cards(self, request, result): | |
try: | |
self.slushpool_hashrate = result['btc']['hash_rate_scoring'] / 1000 | |
self.slushpool_reward = float(result['btc']['unconfirmed_reward']) | |
self.slushpool_reward_confirmed = float(result['btc']['confirmed_reward']) | |
self.slushpool_spinner = False | |
off_workers = result['btc']['off_workers'] | |
low_workers = result['btc']['low_workers'] | |
self.btc_ok_workers = result['btc']['ok_workers'] | |
if off_workers > 0: | |
plyer.vibrator.vibrate(1.5) | |
if low_workers > 0: | |
plyer.vibrator.vibrate(.25) | |
except: | |
print('Update slushpool error') | |
def update_etherscan_cards(self, request, result): | |
try: | |
self.eth_balance = round(int(result['result']) / 1e18, 8) | |
self.usd_eth_balance = self.eth_usd * self.eth_balance | |
self.etherscan_spinner = False | |
except: | |
print('Update etherscan error') | |
def update_blockchain_cards(self, request, result): | |
try: | |
self.btc_balance = round(result[self.btc_addr]['final_balance'] / 1e8, 8) | |
self.usd_btc_balance = self.btc_usd * self.btc_balance | |
self.blockchain_spinner = False | |
except: | |
print('Update blockchain error') | |
if __name__ == "__main__": | |
CryptoMonitor().run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
certifi==2021.5.30 | |
chardet==4.0.0 | |
docutils==0.17.1 | |
idna==2.10 | |
Kivy==2.0.0 | |
Kivy-examples==2.0.0 | |
Kivy-Garden==0.1.4 | |
kivymd @ https://github.com/kivymd/KivyMD/archive/master.zip | |
Pillow==8.3.1 | |
Pygments==2.9.0 | |
requests==2.25.1 | |
urllib3==1.26.6 | |
plyer==2.0.0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment