|
|
@ -2,109 +2,240 @@ |
|
|
|
|
|
|
|
'''Module exchange_rate: |
|
|
|
|
|
|
|
This module is responsible for getting the conversion rates between different |
|
|
|
currencies. |
|
|
|
This module is responsible for getting the conversion rates from different |
|
|
|
bitcoin exchanges. |
|
|
|
''' |
|
|
|
|
|
|
|
from kivy.network.urlrequest import UrlRequest |
|
|
|
#kivy.event import EventDispatcher |
|
|
|
from kivy.event import EventDispatcher |
|
|
|
from kivy.properties import (OptionProperty, StringProperty, AliasProperty, |
|
|
|
ListProperty) |
|
|
|
from kivy.clock import Clock |
|
|
|
import decimal |
|
|
|
import json |
|
|
|
|
|
|
|
class Exchanger(object): |
|
|
|
''' |
|
|
|
EXCHANGES = ["BitcoinAverage", |
|
|
|
"BitcoinVenezuela", |
|
|
|
"BitPay", |
|
|
|
"Blockchain", |
|
|
|
"BTCChina", |
|
|
|
"CaVirtEx", |
|
|
|
"Coinbase", |
|
|
|
"CoinDesk", |
|
|
|
"LocalBitcoins", |
|
|
|
"Winkdex"] |
|
|
|
|
|
|
|
|
|
|
|
class Exchanger(EventDispatcher): |
|
|
|
''' Provide exchanges rate between crypto and different national |
|
|
|
currencies. See Module Documentation for details. |
|
|
|
''' |
|
|
|
|
|
|
|
symbols = {'ALL': 'Lek', 'AED': 'د.إ', 'AFN':'؋', 'ARS': '$', 'AMD': '֏', |
|
|
|
'AWG': 'ƒ', 'ANG': 'ƒ', 'AOA': 'Kz', 'BDT': '৳', 'BHD': 'BD', |
|
|
|
'BIF': 'FBu', 'BTC': 'BTC', 'BTN': 'Nu', |
|
|
|
'AUD': '$', 'AZN': 'ман', 'BSD': '$', 'BBD': '$', 'BYR': 'p', |
|
|
|
'BIF': 'FBu', 'BTC': 'BTC', 'BTN': 'Nu', 'CDF': 'FC', 'CHF': 'CHF', |
|
|
|
'CLF': 'UF', 'CLP':'$', 'CVE': '$', 'DJF':'Fdj', 'DZD': 'دج', |
|
|
|
'AUD': '$', 'AZN': 'ман', 'BSD': '$', 'BBD': '$', 'BYR': 'p', 'CRC': '₡', |
|
|
|
'BZD': 'BZ$', 'BMD': '$', 'BOB': '$b', 'BAM': 'KM', 'BWP': 'P', |
|
|
|
'BGN': 'лв', 'BRL': 'R$', 'BND': '$', 'KHR': '៛', 'CAD': '$', |
|
|
|
'KYD': '$', 'USD': '$', 'CLP': '$', 'CNY': '¥', 'COP': '$', 'CRC': '₡', |
|
|
|
'ERN': 'Nfk', 'ETB': 'Br', 'KYD': '$', 'USD': '$', 'CLP': '$', |
|
|
|
'HRK': 'kn', 'CUP':'₱', 'CZK': 'Kč', 'DKK': 'kr', 'DOP': 'RD$', |
|
|
|
'XCD': '$', 'EGP': '£', 'SVC': '$' , 'EEK': 'kr', 'EUR': '€', |
|
|
|
'FKP': '£', 'FJD': '$', 'GHC': '¢', 'GIP': '£', 'GTQ': 'Q', 'GBP': '£', |
|
|
|
'GYD': '$', 'HNL': 'L', 'HKD': '$', 'HUF': 'Ft', 'ISK': 'kr', |
|
|
|
'INR': '₹', 'IDR': 'Rp', 'IRR': '﷼', 'IMP': '£', 'ILS': '₪', |
|
|
|
'INR': '₹', 'IDR': 'Rp', 'IRR': '﷼', 'IMP': '£', 'ILS': '₪', 'COP': '$', |
|
|
|
'JMD': 'J$', 'JPY': '¥', 'JEP': '£', 'KZT': 'лв', 'KPW': '₩', |
|
|
|
'KRW': '₩', 'KGS': 'лв', 'LAK': '₭', 'LVL': 'Ls'} |
|
|
|
'KRW': '₩', 'KGS': 'лв', 'LAK': '₭', 'LVL': 'Ls', 'CNY': '¥'} |
|
|
|
|
|
|
|
_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): |
|
|
|
exchanger = self.exchanger |
|
|
|
if self.use_exchange == 'CoinDesk': |
|
|
|
self._update_cd_currency(self.currency) |
|
|
|
return |
|
|
|
try: |
|
|
|
self._currency = value |
|
|
|
self.electrum_cinfig.set_key('currency', value, True) |
|
|
|
except AttributeError: |
|
|
|
self._currency = 'EUR' |
|
|
|
|
|
|
|
def _get_currency(self): |
|
|
|
try: |
|
|
|
self._currency = self.electrum_config.get('currency', 'EUR') |
|
|
|
except AttributeError: |
|
|
|
pass |
|
|
|
finally: |
|
|
|
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 = ('BlockChain', 'Coinbase', 'CoinDesk') |
|
|
|
try: |
|
|
|
self.use_exchange = parent.electrum_config.get('use_exchange', |
|
|
|
'BlockChain') |
|
|
|
except AttributeError: |
|
|
|
self.use_exchange = 'BlockChain' |
|
|
|
self.currencies = self.symbols.keys() |
|
|
|
self.exchanges = EXCHANGES |
|
|
|
|
|
|
|
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 |
|
|
|
if self.use_exchange == "CoinDesk": |
|
|
|
try: |
|
|
|
connection = httplib.HTTPSConnection('api.coindesk.com') |
|
|
|
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: |
|
|
|
return |
|
|
|
return btc_amount * decimal.Decimal(str(resp_rate["bpi"][str(quote_currency)]["rate_float"])) |
|
|
|
|
|
|
|
return btc_amount * decimal.Decimal(quote_currencies[quote_currency]) |
|
|
|
|
|
|
|
def check_rates(self, dt): |
|
|
|
if self.use_exchange == 'BlockChain': |
|
|
|
self.check_blockchain() |
|
|
|
elif self.use_exchange == 'CoinDesk': |
|
|
|
self.check_coindesk() |
|
|
|
elif self.use_exchange == 'Coinbase': |
|
|
|
self.check_coinbase() |
|
|
|
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. |
|
|
|
''' |
|
|
|
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 check_coindesk(self): |
|
|
|
def update_wd(self): |
|
|
|
|
|
|
|
def _lookup_rate(response, quote_id): |
|
|
|
return decimal.Decimal(str(response[str(quote_id)]["15m"])) |
|
|
|
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: |
|
|
|
for r in response: |
|
|
|
quote_currencies[r] = _lookup_rate(response, r) |
|
|
|
quote_currencies["CAD"] = decimal.Decimal(cadprice) |
|
|
|
self.quote_currencies = quote_currencies |
|
|
|
except KeyError: |
|
|
|
pass |
|
|
|
self.parent.set_currencies(quote_currencies) |
|
|
|
|
|
|
|
def on_failure(*args): |
|
|
|
pass |
|
|
|
req = UrlRequest(url='https://www.cavirtex.com/api/CAD/ticker.json', |
|
|
|
on_success=on_success, |
|
|
|
timeout=5) |
|
|
|
|
|
|
|
def on_error(*args): |
|
|
|
pass |
|
|
|
def update_CNY(self): |
|
|
|
|
|
|
|
def on_redirect(*args): |
|
|
|
pass |
|
|
|
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://api.coindesk.com/v1/bpi/supported-currencies.json', |
|
|
|
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, |
|
|
|
on_failure=on_failure, |
|
|
|
on_error=on_error, |
|
|
|
on_redirect=on_redirect, |
|
|
|
timeout=5) |
|
|
|
|
|
|
|
def check_coinbase(self): |
|
|
|
def update_cb(self): |
|
|
|
|
|
|
|
def _lookup_rate(response, quote_id): |
|
|
|
return decimal.Decimal(str(response[str(quote_id)])) |
|
|
@ -121,24 +252,12 @@ class Exchanger(object): |
|
|
|
pass |
|
|
|
self.parent.set_currencies(quote_currencies) |
|
|
|
|
|
|
|
def on_failure(*args): |
|
|
|
pass |
|
|
|
|
|
|
|
def on_error(*args): |
|
|
|
pass |
|
|
|
|
|
|
|
def on_redirect(*args): |
|
|
|
pass |
|
|
|
|
|
|
|
req = UrlRequest( |
|
|
|
url='https://coinbase.com/api/v1/currencies/exchange_rates', |
|
|
|
on_success=on_success, |
|
|
|
on_failure=on_failure, |
|
|
|
on_error=on_error, |
|
|
|
on_redirect=on_redirect, |
|
|
|
timeout=5) |
|
|
|
|
|
|
|
def check_blockchain(self): |
|
|
|
def update_bc(self): |
|
|
|
|
|
|
|
def _lookup_rate(response, quote_id): |
|
|
|
return decimal.Decimal(str(response[str(quote_id)]["15m"])) |
|
|
@ -153,27 +272,69 @@ class Exchanger(object): |
|
|
|
pass |
|
|
|
self.parent.set_currencies(quote_currencies) |
|
|
|
|
|
|
|
def on_failure(*args): |
|
|
|
pass |
|
|
|
req = UrlRequest(url='https://blockchain.info/ticker', |
|
|
|
on_success=on_success, |
|
|
|
timeout=5) |
|
|
|
|
|
|
|
def on_error(*args): |
|
|
|
pass |
|
|
|
def update_lb(self): |
|
|
|
def _lookup_rate(response, quote_id): |
|
|
|
return decimal.Decimal(response[str(quote_id)]["rates"]["last"]) |
|
|
|
|
|
|
|
def on_redirect(*args): |
|
|
|
pass |
|
|
|
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://blockchain.info/ticker', |
|
|
|
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, |
|
|
|
on_failure=on_failure, |
|
|
|
on_error=on_error, |
|
|
|
on_redirect=on_redirect, |
|
|
|
timeout=5) |
|
|
|
|
|
|
|
def start(self): |
|
|
|
# check every 5 seconds |
|
|
|
self.check_rates(0) |
|
|
|
Clock.schedule_interval(self.check_rates, 5) |
|
|
|
# check rates every few seconds |
|
|
|
self.update_rate(0) |
|
|
|
# check every few seconds |
|
|
|
Clock.unschedule(self.update_rate) |
|
|
|
Clock.schedule_interval(self.update_rate, 20) |
|
|
|
|
|
|
|
def stop(self): |
|
|
|
Clock.unschedule(self.check_rates) |
|
|
|
Clock.unschedule(self.update_rate) |
|
|
|
|
|
|
|