kivy: use plugins
This commit is contained in:
parent
c803a8ecab
commit
a5e94ef0e8
8
electrum
8
electrum
|
@ -444,7 +444,7 @@ if __name__ == '__main__':
|
|||
'verbose': True,
|
||||
'cmd': 'gui',
|
||||
'gui': 'kivy' if is_kivy else 'android',
|
||||
'auto_connect': True,
|
||||
#'auto_connect': True,
|
||||
}
|
||||
else:
|
||||
config_options = args.__dict__
|
||||
|
@ -474,10 +474,8 @@ if __name__ == '__main__':
|
|||
cmd_name = config.get('cmd')
|
||||
|
||||
# initialize plugins.
|
||||
plugins = None
|
||||
if not is_android:
|
||||
gui_name = config.get('gui', 'qt') if cmd_name == 'gui' else 'cmdline'
|
||||
plugins = Plugins(config, is_bundle or is_local or is_android, gui_name)
|
||||
gui_name = config.get('gui', 'qt') if cmd_name == 'gui' else 'cmdline'
|
||||
plugins = Plugins(config, is_bundle or is_local or is_android, gui_name)
|
||||
|
||||
# get password if needed
|
||||
if cmd_name not in ['gui', 'daemon']:
|
||||
|
|
|
@ -61,10 +61,11 @@ from main_window import ElectrumWindow
|
|||
|
||||
class ElectrumGui:
|
||||
|
||||
def __init__(self, config, network, app=None):
|
||||
def __init__(self, config, network, plugins, app=None):
|
||||
Logger.debug('ElectrumGUI: initialising')
|
||||
self.network = network
|
||||
self.config = config
|
||||
self.plugins = plugins
|
||||
|
||||
#:TODO
|
||||
# implement kivy plugin mechanism that needs to be more extensible
|
||||
|
@ -85,5 +86,6 @@ class ElectrumGui:
|
|||
|
||||
self.main_window = w = ElectrumWindow(config=self.config,
|
||||
network=self.network,
|
||||
plugins = self.plugins,
|
||||
gui_object=self)
|
||||
w.run()
|
||||
|
|
|
@ -451,13 +451,17 @@ BoxLayout:
|
|||
on_press: ao._dropdown.dismiss()
|
||||
on_release: app.popup_dialog('network')
|
||||
ActionButton:
|
||||
text: _('Wallet')
|
||||
text: _('Settings')
|
||||
on_press: ao._dropdown.dismiss()
|
||||
on_release: app.popup_dialog('settings')
|
||||
ActionButton:
|
||||
text: _('Wallets')
|
||||
on_press: ao._dropdown.dismiss()
|
||||
on_release: app.popup_dialog('wallet')
|
||||
ActionButton:
|
||||
text: _('Preferences')
|
||||
text: _('Plugins')
|
||||
on_press: ao._dropdown.dismiss()
|
||||
on_release: app.popup_dialog('settings')
|
||||
on_release: app.popup_dialog('plugins')
|
||||
|
||||
ScreenManager:
|
||||
id: manager
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import re
|
||||
import sys
|
||||
import time
|
||||
import datetime
|
||||
import traceback
|
||||
from decimal import Decimal
|
||||
|
||||
from electrum import WalletStorage, Wallet
|
||||
from electrum.i18n import _, set_language
|
||||
from electrum.contacts import Contacts
|
||||
from electrum.util import profiler
|
||||
from electrum.plugins import run_hook
|
||||
|
||||
from kivy.app import App
|
||||
from kivy.core.window import Window
|
||||
|
@ -18,6 +21,7 @@ from kivy.cache import Cache
|
|||
from kivy.clock import Clock
|
||||
from kivy.factory import Factory
|
||||
from kivy.metrics import inch, metrics
|
||||
from kivy.lang import Builder
|
||||
|
||||
# lazy imports for factory so that widgets can be used in kv
|
||||
Factory.register('InstallWizard',
|
||||
|
@ -27,11 +31,9 @@ Factory.register('ELTextInput', module='electrum_gui.kivy.uix.screens')
|
|||
|
||||
|
||||
# delayed imports: for startup speed on android
|
||||
notification = app = ref = format_satoshis = Builder = None
|
||||
notification = app = ref = format_satoshis = None
|
||||
util = False
|
||||
|
||||
from decimal import Decimal
|
||||
import re
|
||||
|
||||
# register widget cache for keeping memory down timeout to forever to cache
|
||||
# the data
|
||||
|
@ -39,7 +41,8 @@ Cache.register('electrum_widgets', timeout=0)
|
|||
|
||||
from kivy.uix.screenmanager import Screen
|
||||
from kivy.uix.tabbedpanel import TabbedPanel
|
||||
|
||||
from kivy.uix.label import Label
|
||||
from kivy.uix.checkbox import CheckBox
|
||||
|
||||
Factory.register('TabbedCarousel', module='electrum_gui.kivy.uix.screens')
|
||||
|
||||
|
@ -176,7 +179,6 @@ class ElectrumWindow(App):
|
|||
def __init__(self, **kwargs):
|
||||
# initialize variables
|
||||
self._clipboard = None
|
||||
self.exchanger = None
|
||||
self.info_bubble = None
|
||||
self.qrscanner = None
|
||||
self.nfcscanner = None
|
||||
|
@ -185,8 +187,10 @@ class ElectrumWindow(App):
|
|||
super(ElectrumWindow, self).__init__(**kwargs)
|
||||
|
||||
title = _('Electrum App')
|
||||
self.network = network = kwargs.get('network', None)
|
||||
self.electrum_config = config = kwargs.get('config', None)
|
||||
self.network = network = kwargs.get('network', None)
|
||||
self.plugins = kwargs.get('plugins', [])
|
||||
|
||||
self.gui_object = kwargs.get('gui_object', None)
|
||||
|
||||
#self.config = self.gui_object.config
|
||||
|
@ -206,6 +210,8 @@ class ElectrumWindow(App):
|
|||
self._trigger_notify_transactions = \
|
||||
Clock.create_trigger(self.notify_transactions, 5)
|
||||
|
||||
|
||||
|
||||
def set_url(self, instance, url):
|
||||
self.gui_object.set_url(url)
|
||||
|
||||
|
@ -226,12 +232,23 @@ class ElectrumWindow(App):
|
|||
activity.bind(on_activity_result=on_qr_result)
|
||||
PythonActivity.mActivity.startActivityForResult(intent, 0)
|
||||
|
||||
def show_plugins(self, plugins_list):
|
||||
def on_checkbox_active(cb, value):
|
||||
self.plugins.toggle_enabled(self.electrum_config, cb.name)
|
||||
for item in self.plugins.descriptions:
|
||||
if 'kivy' not in item.get('available_for', []):
|
||||
continue
|
||||
name = item.get('name')
|
||||
label = Label(text=item.get('fullname'))
|
||||
plugins_list.add_widget(label)
|
||||
cb = CheckBox()
|
||||
cb.name = name
|
||||
p = self.plugins.get(name)
|
||||
cb.active = (p is not None) and p.is_enabled()
|
||||
cb.bind(active=on_checkbox_active)
|
||||
plugins_list.add_widget(cb)
|
||||
|
||||
def build(self):
|
||||
global Builder
|
||||
if not Builder:
|
||||
from kivy.lang import Builder
|
||||
|
||||
|
||||
return Builder.load_file('gui/kivy/main.kv')
|
||||
|
||||
def _pause(self):
|
||||
|
@ -403,52 +420,11 @@ class ElectrumWindow(App):
|
|||
self.wallet = None
|
||||
|
||||
|
||||
def create_quote_text(self, btc_balance, mode='normal'):
|
||||
'''
|
||||
'''
|
||||
if not self.exchanger:
|
||||
return
|
||||
quote_currency = self.exchanger.currency
|
||||
quote_balance = self.exchanger.exchange(btc_balance, quote_currency)
|
||||
|
||||
if quote_currency and mode == 'symbol':
|
||||
quote_currency = self.exchanger.symbols.get(quote_currency,
|
||||
quote_currency)
|
||||
|
||||
if quote_balance is None:
|
||||
quote_text = u"..."
|
||||
else:
|
||||
quote_text = u"%s%.2f" % (quote_currency,
|
||||
quote_balance)
|
||||
return quote_text
|
||||
|
||||
def set_currencies(self, quote_currencies):
|
||||
self.currencies = sorted(quote_currencies.keys())
|
||||
self._trigger_update_status()
|
||||
|
||||
def get_history_rate(self, item, btc_balance, mintime):
|
||||
'''Historical rates: currently only using coindesk by default.
|
||||
'''
|
||||
maxtime = datetime.datetime.now().strftime('%Y-%m-%d')
|
||||
rate = self.exchanger.get_history_rate(item, btc_balance, mintime,
|
||||
maxtime)
|
||||
|
||||
return self.set_history_rate(item, rate)
|
||||
|
||||
|
||||
def set_history_rate(self, item, rate):
|
||||
'''
|
||||
'''
|
||||
#TODO: fix me allow other currencies to be used for history rates
|
||||
quote_currency = self.exchanger.symbols.get('USD', 'USD')
|
||||
if rate is None:
|
||||
quote_text = "..."
|
||||
else:
|
||||
quote_text = "{0}{1:.3}".format(quote_currency, rate)
|
||||
item = item()
|
||||
if item:
|
||||
item.quote_text = quote_text
|
||||
return quote_text
|
||||
|
||||
|
||||
@profiler
|
||||
|
@ -485,7 +461,7 @@ class ElectrumWindow(App):
|
|||
unconfirmed = " [%s unconfirmed]" %( self.format_amount(u, True).strip())
|
||||
if x:
|
||||
unmatured = " [%s unmatured]"%(self.format_amount(x, True).strip())
|
||||
quote_text = self.create_quote_text(Decimal(c+u+x)/100000000, mode='symbol') or ''
|
||||
#quote_text = self.create_quote_text(Decimal(c+u+x)/100000000, mode='symbol') or ''
|
||||
self.status = text.strip() + ' ' + self.base_unit
|
||||
else:
|
||||
self.status = _("Not connected")
|
||||
|
@ -510,13 +486,6 @@ class ElectrumWindow(App):
|
|||
|
||||
@profiler
|
||||
def update_wallet(self, *dt):
|
||||
'''
|
||||
'''
|
||||
if not self.exchanger:
|
||||
from electrum_gui.kivy.plugins.exchange_rate import Exchanger
|
||||
self.exchanger = Exchanger(self)
|
||||
self.exchanger.start()
|
||||
return
|
||||
self._trigger_update_status()
|
||||
if self.wallet.up_to_date or not self.network or not self.network.is_connected():
|
||||
self.update_history_tab()
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,376 +0,0 @@
|
|||
# -*- encoding: utf8 -*-
|
||||
|
||||
'''Module exchange_rate:
|
||||
|
||||
This module is responsible for getting the conversion rates from different
|
||||
bitcoin exchanges.
|
||||
'''
|
||||
|
||||
import decimal
|
||||
import json
|
||||
|
||||
from kivy.network.urlrequest import UrlRequest
|
||||
from kivy.event import EventDispatcher
|
||||
from kivy.properties import (OptionProperty, StringProperty, AliasProperty,
|
||||
ListProperty)
|
||||
from kivy.clock import Clock
|
||||
from kivy.cache import Cache
|
||||
|
||||
# Register local cache
|
||||
Cache.register('history_rate', timeout=220)
|
||||
|
||||
EXCHANGES = ["BitcoinAverage",
|
||||
"BitcoinVenezuela",
|
||||
"BitPay",
|
||||
"Blockchain",
|
||||
"BTCChina",
|
||||
"CaVirtEx",
|
||||
"Coinbase",
|
||||
"CoinDesk",
|
||||
"LocalBitcoins",
|
||||
"Winkdex"]
|
||||
|
||||
HISTORY_EXCHNAGES = ['Coindesk',
|
||||
'Winkdex',
|
||||
'BitcoinVenezuela']
|
||||
|
||||
|
||||
class Exchanger(EventDispatcher):
|
||||
''' Provide exchanges rate between crypto and different national
|
||||
currencies. See Module Documentation for details.
|
||||
'''
|
||||
|
||||
symbols = {'ALL': u'Lek', 'AED': u'د.إ', 'AFN':u'؋', 'ARS': u'$',
|
||||
'AMD': u'֏', 'AWG': u'ƒ', 'ANG': u'ƒ', 'AOA': u'Kz', 'BDT': u'৳',
|
||||
'BHD': u'BD', 'BIF': u'FBu', 'BTC': u'BTC', 'BTN': u'Nu', 'CDF': u'FC',
|
||||
'CHF': u'CHF', 'CLF': u'UF', 'CLP':u'$', 'CVE': u'$', 'DJF':u'Fdj',
|
||||
'DZD': u'دج', 'AUD': u'$', 'AZN': u'ман', 'BSD': u'$', 'BBD': u'$',
|
||||
'BYR': u'p', 'CRC': u'₡', 'BZD': u'BZ$', 'BMD': u'$', 'BOB': u'$b',
|
||||
'BAM': u'KM', 'BWP': u'P', 'BGN': 'uлв', 'BRL': u'R$', 'BND': u'$',
|
||||
'KHR': u'៛', 'CAD': u'$', 'ERN': u'Nfk', 'ETB': u'Br', 'KYD': u'$',
|
||||
'USD': u'$', 'CLP': u'$', 'HRK': u'kn', 'CUP': u'₱', 'CZK': u'Kč',
|
||||
'DKK': u'kr', 'DOP': u'RD$', 'XCD': u'$', 'EGP': u'£', 'SVC': u'$' ,
|
||||
'EEK': u'kr', 'EUR': u'€', u'FKP': u'£', 'FJD': u'$', 'GHC': u'¢',
|
||||
'GIP': u'£', 'GTQ': u'Q', 'GBP': u'£', 'GYD': u'$', 'HNL': u'L',
|
||||
'HKD': u'$', 'HUF': u'Ft', 'ISK': u'kr', 'INR': u'₹', 'IDR': u'Rp',
|
||||
'IRR': u'﷼', 'IMP': '£', 'ILS': '₪', 'COP': '$', 'JMD': u'J$',
|
||||
'JPY': u'¥', 'JEP': u'£', 'KZT': u'лв', 'KPW': u'₩', 'KRW': u'₩',
|
||||
'KGS': u'лв', 'LAK': u'₭', 'LVL': u'Ls', 'CNY': u'¥'}
|
||||
|
||||
_use_exchange = OptionProperty('Blockchain', options=EXCHANGES)
|
||||
'''This is the exchange to be used for getting the currency exchange rates
|
||||
'''
|
||||
|
||||
_currency = StringProperty('EUR')
|
||||
'''internal use only
|
||||
'''
|
||||
|
||||
def _set_currency(self, value):
|
||||
value = str(value)
|
||||
if self.use_exchange == 'CoinDesk':
|
||||
self._update_cd_currency(self.currency)
|
||||
return
|
||||
self._currency = value
|
||||
self.parent.electrum_config.set_key('currency', value, True)
|
||||
|
||||
def _get_currency(self):
|
||||
self._currency = self.parent.electrum_config.get('currency', 'EUR')
|
||||
return self._currency
|
||||
|
||||
currency = AliasProperty(_get_currency, _set_currency, bind=('_currency',))
|
||||
|
||||
currencies = ListProperty(['EUR', 'GBP', 'USD'])
|
||||
'''List of currencies supported by the current exchanger plugin.
|
||||
|
||||
:attr:`currencies` is a `ListProperty` default to ['Eur', 'GBP'. 'USD'].
|
||||
'''
|
||||
|
||||
def _get_useex(self):
|
||||
if not self.parent:
|
||||
return self._use_exchange
|
||||
|
||||
self._use_exchange = self.parent.electrum_config.get('use_exchange',
|
||||
'Blockchain')
|
||||
return self._use_exchange
|
||||
|
||||
def _set_useex(self, value):
|
||||
if not self.parent:
|
||||
return self._use_exchange
|
||||
self.parent.electrum_config.set_key('use_exchange', value, True)
|
||||
self._use_exchange = value
|
||||
|
||||
use_exchange = AliasProperty(_get_useex, _set_useex,
|
||||
bind=('_use_exchange', ))
|
||||
|
||||
def __init__(self, parent):
|
||||
super(Exchanger, self).__init__()
|
||||
self.parent = parent
|
||||
self.quote_currencies = None
|
||||
self.exchanges = EXCHANGES
|
||||
self.history_exchanges = HISTORY_EXCHNAGES
|
||||
|
||||
def exchange(self, btc_amount, quote_currency):
|
||||
if self.quote_currencies is None:
|
||||
return None
|
||||
|
||||
quote_currencies = self.quote_currencies.copy()
|
||||
if quote_currency not in quote_currencies:
|
||||
return None
|
||||
|
||||
return btc_amount * decimal.Decimal(quote_currencies[quote_currency])
|
||||
|
||||
def get_history_rate(self, item, btc_amt, mintime, maxtime):
|
||||
def on_success(request, response):
|
||||
response = json.loads(response)
|
||||
|
||||
try:
|
||||
hrate = response['bpi'][mintime]
|
||||
hrate = abs(btc_amt) * decimal.Decimal(hrate)
|
||||
Cache.append('history_rate', uid, hrate)
|
||||
except KeyError:
|
||||
hrate = 'not found'
|
||||
|
||||
self.parent.set_history_rate(item, hrate)
|
||||
|
||||
# Check local cache before getting data from remote
|
||||
exchange = 'coindesk'
|
||||
uid = '{}:{}'.format(exchange, mintime)
|
||||
hrate = Cache.get('history_rate', uid)
|
||||
|
||||
if hrate:
|
||||
return hrate
|
||||
|
||||
req = UrlRequest(url='https://api.coindesk.com/v1/bpi/historical'
|
||||
'/close.json?start={}&end={}'
|
||||
.format(mintime, maxtime)
|
||||
,on_success=on_success, timeout=15)
|
||||
return None
|
||||
|
||||
def update_rate(self, dt):
|
||||
''' This is called from :method:`start` every X seconds; to update the
|
||||
rates for currencies for the currently selected exchange.
|
||||
'''
|
||||
if not self.parent.network or not self.parent.network.is_connected():
|
||||
return
|
||||
|
||||
# temporarily disabled
|
||||
return
|
||||
|
||||
update_rates = {
|
||||
"BitcoinAverage": self.update_ba,
|
||||
"BitcoinVenezuela": self.update_bv,
|
||||
"BitPay": self.update_bp,
|
||||
"Blockchain": self.update_bc,
|
||||
"BTCChina": self.update_CNY,
|
||||
"CaVirtEx": self.update_cv,
|
||||
"CoinDesk": self.update_cd,
|
||||
"Coinbase": self.update_cb,
|
||||
"LocalBitcoins": self.update_lb,
|
||||
"Winkdex": self.update_wd,
|
||||
}
|
||||
try:
|
||||
update_rates[self.use_exchange]()
|
||||
except KeyError:
|
||||
return
|
||||
|
||||
def update_wd(self):
|
||||
|
||||
def on_success(request, response):
|
||||
response = json.loads(response)
|
||||
quote_currencies = {'USD': 0.0}
|
||||
lenprices = len(response["prices"])
|
||||
usdprice = response['prices'][lenprices-1]['y']
|
||||
|
||||
try:
|
||||
quote_currencies["USD"] = decimal.Decimal(usdprice)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
self.quote_currencies = quote_currencies
|
||||
self.parent.set_currencies(quote_currencies)
|
||||
|
||||
req = UrlRequest(
|
||||
url='https://winkdex.com/static/data/0_600_288.json',
|
||||
on_success=on_success,
|
||||
timeout=5)
|
||||
|
||||
def update_cd_currency(self, currency):
|
||||
|
||||
def on_success(request, response):
|
||||
response = json.loads(response)
|
||||
quote_currencies = self.quote_currencies
|
||||
quote_currencies[currency] =\
|
||||
str(response['bpi'][str(currency)]['rate_float'])
|
||||
self.parent.set_currencies(quote_currencies)
|
||||
|
||||
req = UrlRequest(
|
||||
url='https://api.coindesk.com/v1/bpi/currentprice/'\
|
||||
+ str(currency) + '.json',on_success=on_success, timeout=5)
|
||||
|
||||
def update_cd(self):
|
||||
|
||||
def on_success(request, response):
|
||||
quote_currencies = {}
|
||||
response = json.loads(response)
|
||||
|
||||
for cur in response:
|
||||
quote_currencies[str(cur["currency"])] = 0.0
|
||||
|
||||
self.quote_currencies = quote_currencies
|
||||
self.update_cd_currency(self.currency)
|
||||
|
||||
req = UrlRequest(
|
||||
url='https://api.coindesk.com/v1/bpi/supported-currencies.json',
|
||||
on_success=on_success,
|
||||
timeout=5)
|
||||
|
||||
def update_cv(self):
|
||||
def on_success(request, response):
|
||||
response = json.loads(response)
|
||||
quote_currencies = {"CAD": 0.0}
|
||||
cadprice = response["last"]
|
||||
try:
|
||||
quote_currencies["CAD"] = decimal.Decimal(cadprice)
|
||||
self.quote_currencies = quote_currencies
|
||||
except KeyError:
|
||||
pass
|
||||
self.parent.set_currencies(quote_currencies)
|
||||
|
||||
req = UrlRequest(url='https://www.cavirtex.com/api/CAD/ticker.json',
|
||||
on_success=on_success,
|
||||
timeout=5)
|
||||
|
||||
def update_CNY(self):
|
||||
|
||||
def on_success(request, response):
|
||||
quote_currencies = {"CNY": 0.0}
|
||||
cnyprice = response["ticker"]["last"]
|
||||
try:
|
||||
quote_currencies["CNY"] = decimal.Decimal(cnyprice)
|
||||
self.quote_currencies = quote_currencies
|
||||
except KeyError:
|
||||
pass
|
||||
self.parent.set_currencies(quote_currencies)
|
||||
|
||||
req = UrlRequest(url='https://data.btcchina.com/data/ticker',
|
||||
on_success=on_success,
|
||||
timeout=5)
|
||||
|
||||
def update_bp(self):
|
||||
|
||||
def on_success(request, response):
|
||||
quote_currencies = {}
|
||||
try:
|
||||
for r in response:
|
||||
quote_currencies[str(r['code'])] = decimal.Decimal(r['rate'])
|
||||
self.quote_currencies = quote_currencies
|
||||
except KeyError:
|
||||
pass
|
||||
self.parent.set_currencies(quote_currencies)
|
||||
|
||||
req = UrlRequest(url='https://bitpay.com/api/rates',
|
||||
on_success=on_success,
|
||||
timeout=5)
|
||||
|
||||
def update_cb(self):
|
||||
|
||||
def _lookup_rate(response, quote_id):
|
||||
return decimal.Decimal(str(response[str(quote_id)]))
|
||||
|
||||
def on_success(request, response):
|
||||
quote_currencies = {}
|
||||
try:
|
||||
for r in response:
|
||||
if r[:7] == "btc_to_":
|
||||
quote_currencies[r[7:].upper()] =\
|
||||
_lookup_rate(response, r)
|
||||
self.quote_currencies = quote_currencies
|
||||
except KeyError:
|
||||
pass
|
||||
self.parent.set_currencies(quote_currencies)
|
||||
|
||||
req = UrlRequest(
|
||||
url='https://coinbase.com/api/v1/currencies/exchange_rates',
|
||||
on_success=on_success,
|
||||
timeout=5)
|
||||
|
||||
def update_bc(self):
|
||||
|
||||
def _lookup_rate(response, quote_id):
|
||||
return decimal.Decimal(str(response[str(quote_id)]["15m"]))
|
||||
|
||||
def on_success(request, response):
|
||||
quote_currencies = {}
|
||||
try:
|
||||
for r in response:
|
||||
quote_currencies[r] = _lookup_rate(response, r)
|
||||
self.quote_currencies = quote_currencies
|
||||
except KeyError, TypeError:
|
||||
pass
|
||||
self.parent.set_currencies(quote_currencies)
|
||||
|
||||
req = UrlRequest(url='https://blockchain.info/ticker',
|
||||
on_success=on_success,
|
||||
timeout=5)
|
||||
|
||||
def update_lb(self):
|
||||
def _lookup_rate(response, quote_id):
|
||||
return decimal.Decimal(response[str(quote_id)]["rates"]["last"])
|
||||
|
||||
def on_success(request, response):
|
||||
quote_currencies = {}
|
||||
try:
|
||||
for r in response:
|
||||
quote_currencies[r] = _lookup_rate(response, r)
|
||||
self.quote_currencies = quote_currencies
|
||||
except KeyError:
|
||||
pass
|
||||
self.parent.set_currencies(quote_currencies)
|
||||
|
||||
req = UrlRequest(
|
||||
url='https://localbitcoins.com/bitcoinaverage/ticker-all-currencies/',
|
||||
on_success=on_success,
|
||||
timeout=5)
|
||||
|
||||
|
||||
def update_ba(self):
|
||||
|
||||
def on_success(request, response):
|
||||
quote_currencies = {}
|
||||
try:
|
||||
for r in response:
|
||||
quote_currencies[r] = decimal.Decimal(response[r][u'last'])
|
||||
self.quote_currencies = quote_currencies
|
||||
except TypeError:
|
||||
pass
|
||||
self.parent.set_currencies(quote_currencies)
|
||||
|
||||
req = UrlRequest(url='https://api.bitcoinaverage.com/ticker/global/all',
|
||||
on_success=on_success,
|
||||
timeout=5)
|
||||
|
||||
def update_bv(self):
|
||||
|
||||
def on_success(request, response):
|
||||
quote_currencies = {}
|
||||
try:
|
||||
for r in response["BTC"]:
|
||||
quote_currencies[r] = decimal.Decimal(response['BTC'][r])
|
||||
self.quote_currencies = quote_currencies
|
||||
except KeyError:
|
||||
pass
|
||||
self.parent.set_currencies(quote_currencies)
|
||||
|
||||
req = UrlRequest(url='https://api.bitcoinvenezuela.com/',
|
||||
on_success=on_success,
|
||||
timeout=5)
|
||||
|
||||
def start(self):
|
||||
self.update_rate(0)
|
||||
# check every 20 seconds
|
||||
Clock.unschedule(self.update_rate)
|
||||
Clock.schedule_interval(self.update_rate, 20)
|
||||
|
||||
def stop(self):
|
||||
Clock.unschedule(self.update_rate)
|
||||
|
|
@ -15,6 +15,8 @@ from kivy.factory import Factory
|
|||
from electrum.i18n import _
|
||||
from electrum.util import profiler
|
||||
from electrum import bitcoin
|
||||
from electrum.util import timestamp_to_datetime
|
||||
from electrum.plugins import run_hook
|
||||
|
||||
class CScreen(Factory.Screen):
|
||||
|
||||
|
@ -84,6 +86,10 @@ class HistoryScreen(CScreen):
|
|||
ra_dialog.item = item
|
||||
ra_dialog.open()
|
||||
|
||||
def get_history_rate(self, btc_balance, timestamp):
|
||||
date = timestamp_to_datetime(timestamp)
|
||||
return run_hook('historical_value_str', btc_balance, date)
|
||||
|
||||
def parse_history(self, items):
|
||||
for item in items:
|
||||
tx_hash, conf, value, timestamp, balance = item
|
||||
|
@ -121,7 +127,11 @@ class HistoryScreen(CScreen):
|
|||
label = _('Pruned transaction outputs')
|
||||
is_default_label = False
|
||||
|
||||
yield (conf, icon, time_str, label, v_str, balance_str, tx_hash)
|
||||
quote_currency = 'USD'
|
||||
rate = self.get_history_rate(value, timestamp)
|
||||
quote_text = "..." if rate is None else "{0:.3} {1}".format(rate, quote_currency)
|
||||
|
||||
yield (conf, icon, time_str, label, v_str, balance_str, tx_hash, quote_text)
|
||||
|
||||
def update(self, see_all=False):
|
||||
|
||||
|
@ -134,20 +144,17 @@ class HistoryScreen(CScreen):
|
|||
history_add = history_card.ids.content.add_widget
|
||||
history_add(last_widget)
|
||||
RecentActivityItem = Factory.RecentActivityItem
|
||||
get_history_rate = self.app.get_history_rate
|
||||
count = 0
|
||||
for item in history:
|
||||
count += 1
|
||||
conf, icon, date_time, address, amount, balance, tx = item
|
||||
conf, icon, date_time, address, amount, balance, tx, quote_text = item
|
||||
ri = RecentActivityItem()
|
||||
ri.icon = icon
|
||||
ri.date = date_time
|
||||
mintimestr = date_time.split()[0]
|
||||
ri.address = address
|
||||
ri.amount = amount
|
||||
ri.quote_text = get_history_rate(ref(ri),
|
||||
Decimal(amount),
|
||||
mintimestr)
|
||||
ri.quote_text = quote_text
|
||||
ri.balance = balance
|
||||
ri.confirmations = conf
|
||||
ri.tx_hash = tx
|
||||
|
|
|
@ -9,6 +9,7 @@ Popup:
|
|||
app.network.set_parameters(host.text, nd.port, nd.protocol, nd.proxy, auto_connect.active)
|
||||
|
||||
BoxLayout:
|
||||
|
||||
orientation: 'vertical'
|
||||
|
||||
GridLayout:
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
Popup:
|
||||
title: _('Plugins')
|
||||
id: popup
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
GridLayout:
|
||||
size_hint_y: None
|
||||
cols: 2
|
||||
id: plugins_list
|
||||
on_parent:
|
||||
app.show_plugins(plugins_list)
|
||||
Button:
|
||||
size_hint_y: None
|
||||
height: '48dp'
|
||||
text: _('Close')
|
||||
on_release: popup.dismiss()
|
|
@ -1,27 +1,26 @@
|
|||
Popup:
|
||||
id: settings
|
||||
title: _('Settings')
|
||||
|
||||
BoxLayout:
|
||||
|
||||
Button:
|
||||
size_hint_y: None
|
||||
height: '48dp'
|
||||
text: 'Button normal'
|
||||
|
||||
Button:
|
||||
size_hint_y: None
|
||||
height: '48dp'
|
||||
text: 'Button down'
|
||||
state: 'down'
|
||||
orientation: 'vertical'
|
||||
size_hint_y: None
|
||||
|
||||
Button:
|
||||
size_hint_y: None
|
||||
height: '48dp'
|
||||
text: 'Button disabled'
|
||||
disabled: True
|
||||
GridLayout:
|
||||
cols: 2
|
||||
Label:
|
||||
text: _('Base unit')
|
||||
height: '48dp'
|
||||
Spinner:
|
||||
text: 'BTC'
|
||||
values: ('BTC', 'mBTC')
|
||||
height: '48dp'
|
||||
|
||||
Button:
|
||||
size_hint_y: None
|
||||
#size_hint_y: None
|
||||
height: '48dp'
|
||||
text: 'close'
|
||||
text: _('Close')
|
||||
on_release: settings.dismiss()
|
||||
#Widget:
|
||||
# size_hint_y: None
|
||||
|
|
|
@ -57,7 +57,7 @@ descriptions = [
|
|||
'name': 'exchange_rate',
|
||||
'fullname': _("Exchange rates"),
|
||||
'description': _("Exchange rates and currency conversion tools."),
|
||||
'available_for': ['qt'],
|
||||
'available_for': ['qt','kivy'],
|
||||
},
|
||||
{
|
||||
'name': 'greenaddress_instant',
|
||||
|
@ -78,10 +78,10 @@ descriptions = [
|
|||
'name': 'labels',
|
||||
'fullname': _('LabelSync'),
|
||||
'description': '\n'.join([
|
||||
_("The new and improved LabelSync plugin. This can sync your labels across multiple Electrum installs by using a remote database to save your data. Labels, transactions ids and addresses are encrypted before they are sent to the remote server."),
|
||||
_("Synchronize your labels across multiple Electrum installs by using a remote database to save your data. Labels, transactions ids and addresses are encrypted before they are sent to the remote server."),
|
||||
_("The label sync's server software is open-source as well and can be found on github.com/maran/electrum-sync-server")
|
||||
]),
|
||||
'available_for': ['qt']
|
||||
'available_for': ['qt','kivy']
|
||||
},
|
||||
{
|
||||
'name': 'plot',
|
||||
|
|
|
@ -423,6 +423,7 @@ class Plugin(BasePlugin, ThreadJob):
|
|||
return "%s" % (self.ccy_amount_str(value, True))
|
||||
return _("No data")
|
||||
|
||||
@hook
|
||||
def historical_value_str(self, satoshis, d_t):
|
||||
rate = self.exchange.historical_rate(self.ccy, d_t)
|
||||
# Frequently there is no rate for today, until tomorrow :)
|
||||
|
|
Loading…
Reference in New Issue