Skip to content

Instantly share code, notes, and snippets.

@m0nochr0me
Last active August 28, 2021 08:24
Show Gist options
  • Save m0nochr0me/080b224f2805db889931c1b4ad1d04c8 to your computer and use it in GitHub Desktop.
Save m0nochr0me/080b224f2805db889931c1b4ad1d04c8 to your computer and use it in GitHub Desktop.
Crypto Monitor App
title=Crypto Monitor
author=m0nochr0me
orientation=landscape
[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
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()
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