1
0

exchange_rate: some clean-up and fixes

- generation of currencies.json was broken
- removed some dead exchanges
This commit is contained in:
SomberNight
2019-02-27 21:48:33 +01:00
parent a2047e2c68
commit 4b3a285871
3 changed files with 53 additions and 76 deletions

View File

@@ -8,10 +8,11 @@ import time
import csv
import decimal
from decimal import Decimal
import concurrent.futures
import traceback
from typing import Sequence
from aiorpcx.curio import timeout_after, TaskTimeout, TaskGroup
from .bitcoin import COIN
from .i18n import _
from .util import (PrintError, ThreadJob, make_dir, log_exceptions,
@@ -40,14 +41,18 @@ class ExchangeBase(PrintError):
async def get_raw(self, site, get_string):
# APIs must have https
url = ''.join(['https://', site, get_string])
async with make_aiohttp_session(Network.get_instance().proxy) as session:
network = Network.get_instance()
proxy = network.proxy if network else None
async with make_aiohttp_session(proxy) as session:
async with session.get(url) as response:
return await response.text()
async def get_json(self, site, get_string):
# APIs must have https
url = ''.join(['https://', site, get_string])
async with make_aiohttp_session(Network.get_instance().proxy) as session:
network = Network.get_instance()
proxy = network.proxy if network else None
async with make_aiohttp_session(proxy) as session:
async with session.get(url) as response:
# set content_type to None to disable checking MIME type
return await response.json(content_type=None)
@@ -60,7 +65,6 @@ class ExchangeBase(PrintError):
def name(self):
return self.__class__.__name__
@log_exceptions
async def update_safe(self, ccy):
try:
self.print_error("getting fx quotes for", ccy)
@@ -71,9 +75,6 @@ class ExchangeBase(PrintError):
self.quotes = {}
self.on_quotes()
def update(self, ccy):
asyncio.get_event_loop().create_task(self.update_safe(ccy))
def read_historical_rates(self, ccy, cache_dir):
filename = os.path.join(cache_dir, self.name() + '_'+ ccy)
if os.path.exists(filename):
@@ -123,8 +124,8 @@ class ExchangeBase(PrintError):
def historical_rate(self, ccy, d_t):
return self.history.get(ccy, {}).get(d_t.strftime('%Y-%m-%d'), 'NaN')
def get_currencies(self):
rates = self.get_rates('')
async def get_currencies(self):
rates = await self.get_rates('')
return sorted([str(a) for (a, b) in rates.items() if b is not None and len(a)==3])
class BitcoinAverage(ExchangeBase):
@@ -229,20 +230,6 @@ class BlockchainInfo(ExchangeBase):
return dict([(r, Decimal(json[r]['15m'])) for r in json])
class BTCChina(ExchangeBase):
async def get_rates(self, ccy):
json = await self.get_json('data.btcchina.com', '/data/ticker')
return {'CNY': Decimal(json['ticker']['last'])}
class BTCParalelo(ExchangeBase):
async def get_rates(self, ccy):
json = await self.get_json('btcparalelo.com', '/api/price')
return {'VEF': Decimal(json['price'])}
class Coinbase(ExchangeBase):
async def get_rates(self, ccy):
@@ -280,20 +267,6 @@ class CoinDesk(ExchangeBase):
return json['bpi']
class Coinsecure(ExchangeBase):
async def get_rates(self, ccy):
json = await self.get_json('api.coinsecure.in', '/v0/noauth/newticker')
return {'INR': Decimal(json['lastprice'] / 100.0 )}
class Foxbit(ExchangeBase):
async def get_rates(self,ccy):
json = await self.get_json('api.bitvalor.com', '/v1/ticker.json')
return {'BRL': Decimal(json['ticker_1h']['exchanges']['FOX']['last'])}
class itBit(ExchangeBase):
async def get_rates(self, ccy):
@@ -344,23 +317,6 @@ class TheRockTrading(ExchangeBase):
'/v1/funds/BTCEUR/ticker')
return {'EUR': Decimal(json['last'])}
class Unocoin(ExchangeBase):
async def get_rates(self, ccy):
json = await self.get_json('www.unocoin.com', 'trade?buy')
return {'INR': Decimal(json)}
class WEX(ExchangeBase):
async def get_rates(self, ccy):
json_eur = await self.get_json('wex.nz', '/api/3/ticker/btc_eur')
json_rub = await self.get_json('wex.nz', '/api/3/ticker/btc_rur')
json_usd = await self.get_json('wex.nz', '/api/3/ticker/btc_usd')
return {'EUR': Decimal(json_eur['btc_eur']['last']),
'RUB': Decimal(json_rub['btc_rur']['last']),
'USD': Decimal(json_usd['btc_usd']['last'])}
class Winkdex(ExchangeBase):
@@ -394,25 +350,39 @@ def dictinvert(d):
return inv
def get_exchanges_and_currencies():
# load currencies.json from disk
path = resource_path('currencies.json')
try:
with open(path, 'r', encoding='utf-8') as f:
return json.loads(f.read())
except:
pass
# or if not present, generate it now.
print("cannot find currencies.json. will regenerate it now.")
d = {}
is_exchange = lambda obj: (inspect.isclass(obj)
and issubclass(obj, ExchangeBase)
and obj != ExchangeBase)
exchanges = dict(inspect.getmembers(sys.modules[__name__], is_exchange))
for name, klass in exchanges.items():
exchange = klass(None, None)
async def get_currencies_safe(name, exchange):
try:
d[name] = exchange.get_currencies()
d[name] = await exchange.get_currencies()
print(name, "ok")
except:
print(name, "error")
continue
async def query_all_exchanges_for_their_ccys_over_network():
async with timeout_after(10):
async with TaskGroup() as group:
for name, klass in exchanges.items():
exchange = klass(None, None)
await group.spawn(get_currencies_safe(name, exchange))
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(query_all_exchanges_for_their_ccys_over_network())
except Exception as e:
pass
with open(path, 'w', encoding='utf-8') as f:
f.write(json.dumps(d, indent=4, sort_keys=True))
return d
@@ -478,17 +448,18 @@ class FxThread(ThreadJob):
async def run(self):
while True:
# approx. every 2.5 minutes, refresh spot price
try:
await asyncio.wait_for(self._trigger.wait(), 150)
except concurrent.futures.TimeoutError:
async with timeout_after(150):
await self._trigger.wait()
self._trigger.clear()
# we were manually triggered, so get historical rates
if self.is_enabled() and self.show_history():
self.exchange.get_historical_rates(self.ccy, self.cache_dir)
except TaskTimeout:
pass
else:
self._trigger.clear()
if self.is_enabled():
if self.show_history():
self.exchange.get_historical_rates(self.ccy, self.cache_dir)
if self.is_enabled():
self.exchange.update(self.ccy)
await self.exchange.update_safe(self.ccy)
def is_enabled(self):
return bool(self.config.get('use_exchange_rate'))