2016-07-25 07:40:26 +02:00
|
|
|
import requests
|
2016-07-15 20:09:43 +02:00
|
|
|
import json
|
2016-07-26 03:45:42 +02:00
|
|
|
import time
|
2016-07-15 20:09:43 +02:00
|
|
|
|
2016-07-26 23:20:51 +02:00
|
|
|
from copy import deepcopy
|
2016-07-25 07:40:26 +02:00
|
|
|
from googlefinance import getQuotes
|
|
|
|
from lbrynet.conf import CURRENCIES
|
2016-07-26 03:45:42 +02:00
|
|
|
import logging
|
2016-07-25 07:40:26 +02:00
|
|
|
|
2016-07-26 03:45:42 +02:00
|
|
|
log = logging.getLogger(__name__)
|
2016-07-26 23:20:51 +02:00
|
|
|
log.setLevel(logging.INFO)
|
2016-07-26 03:45:42 +02:00
|
|
|
|
|
|
|
BITTREX_FEE = 0.0025
|
2016-07-25 07:40:26 +02:00
|
|
|
|
2016-07-26 03:45:42 +02:00
|
|
|
SOURCE_TYPES = ['lbry_sd_hash', 'url', 'btih']
|
2016-07-25 07:40:26 +02:00
|
|
|
BASE_METADATA_FIELDS = ['title', 'description', 'author', 'language', 'license', 'content-type', 'sources']
|
2016-07-15 20:09:43 +02:00
|
|
|
OPTIONAL_METADATA_FIELDS = ['thumbnail', 'preview', 'fee', 'contact', 'pubkey']
|
|
|
|
|
|
|
|
#v0.0.1 metadata
|
|
|
|
METADATA_REVISIONS = {'0.0.1': {'required': BASE_METADATA_FIELDS, 'optional': OPTIONAL_METADATA_FIELDS}}
|
|
|
|
#v0.0.2 metadata additions
|
2016-07-26 05:42:03 +02:00
|
|
|
METADATA_REVISIONS['0.0.2'] = {'required': ['nsfw', 'ver'], 'optional': ['license_url']}
|
2016-07-25 07:40:26 +02:00
|
|
|
CURRENT_METADATA_VERSION = '0.0.2'
|
|
|
|
|
2016-07-26 03:45:42 +02:00
|
|
|
|
|
|
|
#v0.0.1 fee
|
|
|
|
FEE_REVISIONS = {'0.0.1': {'required': ['amount', 'address'], 'optional': []}}
|
|
|
|
CURRENT_FEE_REVISION = '0.0.1'
|
|
|
|
|
|
|
|
|
2016-07-26 23:20:51 +02:00
|
|
|
class LBRYFeeFormat(dict):
|
|
|
|
def __init__(self, fee_dict):
|
|
|
|
dict.__init__(self)
|
|
|
|
self.fee_version = None
|
|
|
|
f = deepcopy(fee_dict)
|
|
|
|
assert len(fee_dict) == 1
|
|
|
|
for currency in fee_dict:
|
|
|
|
assert currency in CURRENCIES, "Unsupported currency: %s" % str(currency)
|
2016-07-26 03:45:42 +02:00
|
|
|
self.currency_symbol = currency
|
2016-07-26 23:20:51 +02:00
|
|
|
self.update({currency: {}})
|
|
|
|
for version in FEE_REVISIONS:
|
|
|
|
for k in FEE_REVISIONS[version]['required']:
|
|
|
|
assert k in fee_dict[currency], "Missing required fee field: %s" % k
|
|
|
|
self[currency].update({k: f[currency].pop(k)})
|
|
|
|
for k in FEE_REVISIONS[version]['optional']:
|
|
|
|
if k in fee_dict[currency]:
|
|
|
|
self[currency].update({k: f[currency].pop(k)})
|
|
|
|
if not len(f):
|
|
|
|
self.fee_version = version
|
|
|
|
break
|
|
|
|
assert f[currency] == {}, "Unknown fee keys: %s" % json.dumps(f.keys())
|
|
|
|
|
|
|
|
self.amount = self[self.currency_symbol]['amount'] if isinstance(self[self.currency_symbol]['amount'], float) else float(self[self.currency_symbol]['amount'])
|
|
|
|
self.address = self[self.currency_symbol]['address']
|
2016-07-26 03:45:42 +02:00
|
|
|
|
2016-07-26 23:20:51 +02:00
|
|
|
|
|
|
|
class LBRYFee(LBRYFeeFormat):
|
|
|
|
def __init__(self, fee_dict, rate_dict):
|
|
|
|
LBRYFeeFormat.__init__(self, fee_dict)
|
|
|
|
rates = deepcopy(rate_dict)
|
|
|
|
|
|
|
|
assert 'BTCLBC' in rates and 'USDBTC' in rates
|
2016-07-26 03:45:42 +02:00
|
|
|
for fx in rate_dict:
|
2016-07-26 23:20:51 +02:00
|
|
|
assert int(time.time()) - int(rates[fx]['ts']) < 3600, "%s quote is out of date" % fx
|
|
|
|
self._USDBTC = {'spot': rates['USDBTC']['spot'], 'ts': rates['USDBTC']['ts']}
|
|
|
|
self._BTCLBC = {'spot': rates['BTCLBC']['spot'], 'ts': rates['BTCLBC']['ts']}
|
2016-07-26 03:45:42 +02:00
|
|
|
|
|
|
|
def to_lbc(self):
|
|
|
|
r = None
|
2016-07-25 07:40:26 +02:00
|
|
|
if self.currency_symbol == "LBC":
|
|
|
|
r = round(float(self.amount), 5)
|
|
|
|
elif self.currency_symbol == "BTC":
|
2016-07-26 03:45:42 +02:00
|
|
|
r = round(float(self._btc_to_lbc(self.amount)), 5)
|
2016-07-25 07:40:26 +02:00
|
|
|
elif self.currency_symbol == "USD":
|
2016-07-26 03:45:42 +02:00
|
|
|
r = round(float(self._btc_to_lbc(self._usd_to_btc(self.amount))), 5)
|
|
|
|
assert r is not None
|
|
|
|
return r
|
2016-07-25 07:40:26 +02:00
|
|
|
|
2016-07-26 03:45:42 +02:00
|
|
|
def to_usd(self):
|
|
|
|
r = None
|
|
|
|
if self.currency_symbol == "USD":
|
|
|
|
r = round(float(self.amount), 5)
|
|
|
|
elif self.currency_symbol == "BTC":
|
|
|
|
r = round(float(self._btc_to_usd(self.amount)), 5)
|
|
|
|
elif self.currency_symbol == "LBC":
|
|
|
|
r = round(float(self._btc_to_usd(self._lbc_to_btc(self.amount))), 5)
|
|
|
|
assert r is not None
|
2016-07-25 07:40:26 +02:00
|
|
|
return r
|
|
|
|
|
2016-07-26 03:45:42 +02:00
|
|
|
def _usd_to_btc(self, usd):
|
2016-07-26 23:20:51 +02:00
|
|
|
# log.error("usd to btc: " + str(usd))
|
|
|
|
# log.error("%f * %f = %f" % (self._USDBTC['spot'], float(usd), self._USDBTC['spot'] * float(usd)))
|
2016-07-26 03:45:42 +02:00
|
|
|
return self._USDBTC['spot'] * float(usd)
|
|
|
|
|
|
|
|
def _btc_to_usd(self, btc):
|
2016-07-26 23:20:51 +02:00
|
|
|
# log.error("btc to usd: " + str(btc))
|
|
|
|
# log.error("%f / %f = %f" % (float(btc), self._USDBTC['spot'], float(btc) / self._USDBTC['spot']))
|
2016-07-26 03:45:42 +02:00
|
|
|
return float(btc) / self._USDBTC['spot']
|
2016-07-25 07:40:26 +02:00
|
|
|
|
2016-07-26 03:45:42 +02:00
|
|
|
def _btc_to_lbc(self, btc):
|
2016-07-26 23:20:51 +02:00
|
|
|
# log.error("btc to lbc: " + str(btc))
|
|
|
|
# log.error("%f * %f = %f" % (float(btc), self._BTCLBC['spot'], float(btc) * self._BTCLBC['spot'] / (1.0 - BITTREX_FEE)))
|
2016-07-26 05:41:26 +02:00
|
|
|
return float(btc) * self._BTCLBC['spot'] / (1.0 - BITTREX_FEE)
|
2016-07-25 07:40:26 +02:00
|
|
|
|
2016-07-26 03:45:42 +02:00
|
|
|
def _lbc_to_btc(self, lbc):
|
2016-07-26 23:20:51 +02:00
|
|
|
# log.error("lbc to btc: " + str(lbc))
|
|
|
|
# log.error("%f / %f = %f" % (self._BTCLBC['spot'], float(lbc), self._BTCLBC['spot'] / float(lbc)))
|
2016-07-26 05:41:26 +02:00
|
|
|
return self._BTCLBC['spot'] / float(lbc)
|
2016-07-26 03:45:42 +02:00
|
|
|
|
|
|
|
|
2016-07-15 20:09:43 +02:00
|
|
|
class Metadata(dict):
|
|
|
|
def __init__(self, metadata):
|
|
|
|
dict.__init__(self)
|
|
|
|
self.metaversion = None
|
2016-07-26 23:20:51 +02:00
|
|
|
m = deepcopy(metadata)
|
2016-07-25 07:40:26 +02:00
|
|
|
|
|
|
|
assert "sources" in metadata, "No sources given"
|
|
|
|
for source in metadata['sources']:
|
|
|
|
assert source in SOURCE_TYPES, "Unknown source type"
|
|
|
|
|
2016-07-15 20:09:43 +02:00
|
|
|
for version in METADATA_REVISIONS:
|
|
|
|
for k in METADATA_REVISIONS[version]['required']:
|
|
|
|
assert k in metadata, "Missing required metadata field: %s" % k
|
|
|
|
self.update({k: m.pop(k)})
|
|
|
|
for k in METADATA_REVISIONS[version]['optional']:
|
2016-07-26 03:45:42 +02:00
|
|
|
if k == 'fee':
|
|
|
|
pass
|
|
|
|
elif k in metadata:
|
2016-07-15 20:09:43 +02:00
|
|
|
self.update({k: m.pop(k)})
|
2016-07-26 03:45:42 +02:00
|
|
|
if not len(m) or m.keys() == ['fee']:
|
2016-07-15 20:09:43 +02:00
|
|
|
self.metaversion = version
|
|
|
|
break
|
2016-07-26 03:45:42 +02:00
|
|
|
if 'fee' in m:
|
2016-07-26 05:46:18 +02:00
|
|
|
self['fee'] = LBRYFeeFormat(m.pop('fee'))
|
2016-07-25 07:40:26 +02:00
|
|
|
assert m == {}, "Unknown metadata keys: %s" % json.dumps(m.keys())
|