@ -13,6 +13,17 @@ from electrum.i18n import _
from electrum_gui . qt . util import *
from electrum_gui . qt . util import *
EXCHANGES = [ " BitcoinAverage " ,
" BitPay " ,
" Blockchain " ,
" BTCChina " ,
" CaVirtEx " ,
" Coinbase " ,
" CoinDesk " ,
" LocalBitcoins " ,
" Winkdex " ]
class Exchanger ( threading . Thread ) :
class Exchanger ( threading . Thread ) :
def __init__ ( self , parent ) :
def __init__ ( self , parent ) :
@ -22,12 +33,28 @@ class Exchanger(threading.Thread):
self . quote_currencies = None
self . quote_currencies = None
self . lock = threading . Lock ( )
self . lock = threading . Lock ( )
self . use_exchange = self . parent . config . get ( ' use_exchange ' , " Blockchain " )
self . use_exchange = self . parent . config . get ( ' use_exchange ' , " Blockchain " )
self . parent . exchanges = [ " Blockchain " , " Coinbase " , " CoinDesk " ]
self . parent . exchanges = EXCHANGES
self . parent . currencies = [ " EUR " , " GBP " , " USD " ]
self . parent . currencies = [ " EUR " , " GBP " , " USD " ]
self . parent . win . emit ( SIGNAL ( " refresh_exchanges_combo() " ) )
self . parent . win . emit ( SIGNAL ( " refresh_exchanges_combo() " ) )
self . parent . win . emit ( SIGNAL ( " refresh_currencies_combo() " ) )
self . parent . win . emit ( SIGNAL ( " refresh_currencies_combo() " ) )
self . is_running = False
self . is_running = False
def get_json ( self , site , get_string ) :
try :
connection = httplib . HTTPSConnection ( site )
connection . request ( " GET " , get_string )
except Exception :
raise
resp = connection . getresponse ( )
if resp . reason == httplib . responses [ httplib . NOT_FOUND ] :
raise
try :
json_resp = json . loads ( resp . read ( ) )
except Exception :
raise
return json_resp
def exchange ( self , btc_amount , quote_currency ) :
def exchange ( self , btc_amount , quote_currency ) :
with self . lock :
with self . lock :
if self . quote_currencies is None :
if self . quote_currencies is None :
@ -37,15 +64,7 @@ class Exchanger(threading.Thread):
return None
return None
if self . use_exchange == " CoinDesk " :
if self . use_exchange == " CoinDesk " :
try :
try :
connection = httplib . HTTPSConnection ( ' api.coindesk.com ' )
resp_rate = self . get_json ( ' api.coindesk.com ' , " /v1/bpi/currentprice/ " + str ( quote_currency ) + " .json " )
connection . request ( " GET " , " /v1/bpi/currentprice/ " + str ( quote_currency ) + " .json " )
except Exception :
return
resp = connection . getresponse ( )
if resp . reason == httplib . responses [ httplib . NOT_FOUND ] :
return
try :
resp_rate = json . loads ( resp . read ( ) )
except Exception :
except Exception :
return
return
return btc_amount * decimal . Decimal ( str ( resp_rate [ " bpi " ] [ str ( quote_currency ) ] [ " rate_float " ] ) )
return btc_amount * decimal . Decimal ( str ( resp_rate [ " bpi " ] [ str ( quote_currency ) ] [ " rate_float " ] ) )
@ -54,30 +73,34 @@ class Exchanger(threading.Thread):
def stop ( self ) :
def stop ( self ) :
self . is_running = False
self . is_running = False
def update_rate ( self ) :
self . use_exchange = self . parent . config . get ( ' use_exchange ' , " Blockchain " )
update_rates = {
" BitcoinAverage " : self . update_ba ,
" 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 run ( self ) :
def run ( self ) :
self . is_running = True
self . is_running = True
while self . is_running :
while self . is_running :
self . use_exchange = self . parent . config . get ( ' use_exchange ' , " Blockchain " )
self . update_rate ( )
if self . use_exchange == " Blockchain " :
self . update_bc ( )
elif self . use_exchange == " CoinDesk " :
self . update_cd ( )
elif self . use_exchange == " Coinbase " :
self . update_cb ( )
time . sleep ( 150 )
time . sleep ( 150 )
def update_cd ( self ) :
def update_cd ( self ) :
try :
try :
connection = httplib . HTTPSConnection ( ' api.coindesk.com ' )
resp_currencies = self . get_json ( ' api.coindesk.com ' , " /v1/bpi/supported-currencies.json " )
connection . request ( " GET " , " /v1/bpi/supported-currencies.json " )
except Exception :
return
response = connection . getresponse ( )
if response . reason == httplib . responses [ httplib . NOT_FOUND ] :
return
try :
resp_currencies = json . loads ( response . read ( ) )
except Exception :
except Exception :
return
return
@ -87,27 +110,81 @@ class Exchanger(threading.Thread):
with self . lock :
with self . lock :
self . quote_currencies = quote_currencies
self . quote_currencies = quote_currencies
self . parent . set_currencies ( quote_currencies )
self . parent . set_currencies ( quote_currencies )
def update_wd ( self ) :
try :
winkresp = self . get_json ( ' winkdex.com ' , " /static/data/0_600_288.json " )
####could need nonce value in GET, no Docs available
except Exception :
return
quote_currencies = { " USD " : 0.0 }
####get y of highest x in "prices"
lenprices = len ( winkresp [ " prices " ] )
usdprice = winkresp [ " prices " ] [ lenprices - 1 ] [ " y " ]
try :
quote_currencies [ " USD " ] = decimal . Decimal ( usdprice )
with self . lock :
self . quote_currencies = quote_currencies
except KeyError :
pass
self . parent . set_currencies ( quote_currencies )
def update_cv ( self ) :
try :
jsonresp = self . get_json ( ' www.cavirtex.com ' , " /api/CAD/ticker.json " )
except Exception :
return
quote_currencies = { " CAD " : 0.0 }
cadprice = jsonresp [ " last " ]
try :
quote_currencies [ " CAD " ] = decimal . Decimal ( cadprice )
with self . lock :
self . quote_currencies = quote_currencies
except KeyError :
pass
self . parent . set_currencies ( quote_currencies )
def update_cb ( self ) :
def update_CNY ( self ) :
try :
try :
connection = httplib . HTTPSConnection ( ' coinbase.com ' )
jsonresp = self . get_json ( ' data.btcchina.com ' , " /data/ticker " )
connection . request ( " GET " , " /api/v1/currencies/exchange_rates " )
except Exception :
except Exception :
return
return
response = connection . getresponse ( )
quote_currencies = { " CNY " : 0.0 }
if response . reason == httplib . responses [ httplib . NOT_FOUND ] :
cnyprice = jsonresp [ " ticker " ] [ " last " ]
try :
quote_currencies [ " CNY " ] = decimal . Decimal ( cnyprice )
with self . lock :
self . quote_currencies = quote_currencies
except KeyError :
pass
self . parent . set_currencies ( quote_currencies )
def update_bp ( self ) :
try :
jsonresp = self . get_json ( ' bitpay.com ' , " /api/rates " )
except Exception :
return
return
quote_currencies = { }
try :
for r in jsonresp :
quote_currencies [ str ( r [ " code " ] ) ] = decimal . Decimal ( r [ " rate " ] )
with self . lock :
self . quote_currencies = quote_currencies
except KeyError :
pass
self . parent . set_currencies ( quote_currencies )
def update_cb ( self ) :
try :
try :
response = json . loads ( response . read ( ) )
jsonresp = self . get_json ( ' coinbase.com ' , " /api/v1/currencies/exchange_rates " )
except Exception :
except Exception :
return
return
quote_currencies = { }
quote_currencies = { }
try :
try :
for r in response :
for r in json resp:
if r [ : 7 ] == " btc_to_ " :
if r [ : 7 ] == " btc_to_ " :
quote_currencies [ r [ 7 : ] . upper ( ) ] = self . _lookup_rate_cb ( response , r )
quote_currencies [ r [ 7 : ] . upper ( ) ] = self . _lookup_rate_cb ( json resp, r )
with self . lock :
with self . lock :
self . quote_currencies = quote_currencies
self . quote_currencies = quote_currencies
except KeyError :
except KeyError :
@ -117,29 +194,53 @@ class Exchanger(threading.Thread):
def update_bc ( self ) :
def update_bc ( self ) :
try :
try :
connection = httplib . HTTPSConnection ( ' blockchain.info ' )
jsonresp = self . get_json ( ' blockchain.info ' , " /ticker " )
connection . request ( " GET " , " /ticker " )
except Exception :
except Exception :
return
return
response = connection . getresponse ( )
quote_currencies = { }
if response . reason == httplib . responses [ httplib . NOT_FOUND ] :
try :
for r in jsonresp :
quote_currencies [ r ] = self . _lookup_rate ( jsonresp , r )
with self . lock :
self . quote_currencies = quote_currencies
except KeyError :
pass
self . parent . set_currencies ( quote_currencies )
# print "updating exchange rate", self.quote_currencies["USD"]
def update_lb ( self ) :
try :
jsonresp = self . get_json ( ' localbitcoins.com ' , " /bitcoinaverage/ticker-all-currencies/ " )
except Exception :
return
return
quote_currencies = { }
try :
try :
response = json . loads ( response . read ( ) )
for r in jsonresp :
quote_currencies [ r ] = self . _lookup_rate_lb ( jsonresp , r )
with self . lock :
self . quote_currencies = quote_currencies
except KeyError :
pass
self . parent . set_currencies ( quote_currencies )
def update_ba ( self ) :
try :
jsonresp = self . get_json ( ' api.bitcoinaverage.com ' , " /ticker/global/all " )
except Exception :
except Exception :
return
return
quote_currencies = { }
quote_currencies = { }
try :
try :
for r in response :
for r in jsonresp :
quote_currencies [ r ] = self . _lookup_rate ( response , r )
if not r == " timestamp " :
quote_currencies [ r ] = self . _lookup_rate_ba ( jsonresp , r )
with self . lock :
with self . lock :
self . quote_currencies = quote_currencies
self . quote_currencies = quote_currencies
except KeyError :
except KeyError :
pass
pass
self . parent . set_currencies ( quote_currencies )
self . parent . set_currencies ( quote_currencies )
# print "updating exchange rate", self.quote_currencies["USD"]
def get_currencies ( self ) :
def get_currencies ( self ) :
return [ ] if self . quote_currencies == None else sorted ( self . quote_currencies . keys ( ) )
return [ ] if self . quote_currencies == None else sorted ( self . quote_currencies . keys ( ) )
@ -147,7 +248,10 @@ class Exchanger(threading.Thread):
return decimal . Decimal ( str ( response [ str ( quote_id ) ] [ " 15m " ] ) )
return decimal . Decimal ( str ( response [ str ( quote_id ) ] [ " 15m " ] ) )
def _lookup_rate_cb ( self , response , quote_id ) :
def _lookup_rate_cb ( self , response , quote_id ) :
return decimal . Decimal ( str ( response [ str ( quote_id ) ] ) )
return decimal . Decimal ( str ( response [ str ( quote_id ) ] ) )
def _lookup_rate_ba ( self , response , quote_id ) :
return decimal . Decimal ( response [ str ( quote_id ) ] [ " last " ] )
def _lookup_rate_lb ( self , response , quote_id ) :
return decimal . Decimal ( response [ str ( quote_id ) ] [ " rates " ] [ " last " ] )
class Plugin ( BasePlugin ) :
class Plugin ( BasePlugin ) :
@ -221,15 +325,7 @@ class Plugin(BasePlugin):
mintimestr = datetime . datetime . fromtimestamp ( int ( min ( tx_list . items ( ) , key = lambda x : x [ 1 ] [ ' timestamp ' ] ) [ 1 ] [ ' timestamp ' ] ) ) . strftime ( ' % Y- % m- %d ' )
mintimestr = datetime . datetime . fromtimestamp ( int ( min ( tx_list . items ( ) , key = lambda x : x [ 1 ] [ ' timestamp ' ] ) [ 1 ] [ ' timestamp ' ] ) ) . strftime ( ' % Y- % m- %d ' )
maxtimestr = datetime . datetime . now ( ) . strftime ( ' % Y- % m- %d ' )
maxtimestr = datetime . datetime . now ( ) . strftime ( ' % Y- % m- %d ' )
try :
try :
connection = httplib . HTTPSConnection ( ' api.coindesk.com ' )
resp_hist = self . exchanger . get_json ( ' api.coindesk.com ' , " /v1/bpi/historical/close.json?start= " + mintimestr + " &end= " + maxtimestr )
connection . request ( " GET " , " /v1/bpi/historical/close.json?start= " + mintimestr + " &end= " + maxtimestr )
except Exception :
return
resp = connection . getresponse ( )
if resp . reason == httplib . responses [ httplib . NOT_FOUND ] :
return
try :
resp_hist = json . loads ( resp . read ( ) )
except Exception :
except Exception :
return
return
@ -252,9 +348,10 @@ class Plugin(BasePlugin):
tx_time_str = datetime . datetime . fromtimestamp ( tx_time ) . strftime ( ' % Y- % m- %d ' )
tx_time_str = datetime . datetime . fromtimestamp ( tx_time ) . strftime ( ' % Y- % m- %d ' )
tx_USD_val = " %.2f %s " % ( Decimal ( tx_info [ ' value ' ] ) / 100000000 * Decimal ( resp_hist [ ' bpi ' ] [ tx_time_str ] ) , " USD " )
tx_USD_val = " %.2f %s " % ( Decimal ( tx_info [ ' value ' ] ) / 100000000 * Decimal ( resp_hist [ ' bpi ' ] [ tx_time_str ] ) , " USD " )
item . setText ( 5 , tx_USD_val )
item . setText ( 5 , tx_USD_val )
if Decimal ( tx_info [ ' value ' ] ) < 0 :
item . setForeground ( 5 , QBrush ( QColor ( " #BC1E1E " ) ) )
for i , width in enumerate ( self . gui . main_window . column_widths [ ' history ' ] ) :
for i , width in enumerate ( self . gui . main_window . column_widths [ ' history ' ] ) :
self . gui . main_window . history_list . setColumnWidth ( i , width )
self . gui . main_window . history_list . setColumnWidth ( i , width )
self . gui . main_window . history_list . setColumnWidth ( 4 , 140 )
self . gui . main_window . history_list . setColumnWidth ( 4 , 140 )
@ -292,25 +389,22 @@ class Plugin(BasePlugin):
hist_checkbox . setEnabled ( False )
hist_checkbox . setEnabled ( False )
self . win . update_status ( )
self . win . update_status ( )
def disable_check ( ) :
hist_checkbox . setChecked ( False )
hist_checkbox . setEnabled ( False )
def on_change_ex ( x ) :
def on_change_ex ( x ) :
cur_request = str ( self . exchanges [ x ] )
cur_request = str ( self . exchanges [ x ] )
if cur_request != self . config . get ( ' use_exchange ' , " Blockchain " ) :
if cur_request != self . config . get ( ' use_exchange ' , " Blockchain " ) :
self . config . set_key ( ' use_exchange ' , cur_request , True )
self . config . set_key ( ' use_exchange ' , cur_request , True )
if cur_request == " Blockchain " :
self . exchanger . update_rate ( )
self . exchanger . update_bc ( )
if cur_request == " CoinDesk " :
hist_checkbox . setChecked ( False )
hist_checkbox . setEnabled ( False )
elif cur_request == " CoinDesk " :
self . exchanger . update_cd ( )
if self . config . get ( ' currency ' , " EUR " ) == " USD " :
if self . config . get ( ' currency ' , " EUR " ) == " USD " :
hist_checkbox . setEnabled ( True )
hist_checkbox . setEnabled ( True )
else :
else :
hist_checkbox . setChecked ( False )
disable_check ( )
hist_checkbox . setEnabled ( False )
else :
elif cur_request == " Coinbase " :
disable_check ( )
self . exchanger . update_cb ( )
hist_checkbox . setChecked ( False )
hist_checkbox . setEnabled ( False )
set_currencies ( combo )
set_currencies ( combo )
self . win . update_status ( )
self . win . update_status ( )