fix key payment problems

This commit is contained in:
Jack 2016-07-26 17:20:51 -04:00
parent 491d431ea5
commit 0811ebb52d
3 changed files with 67 additions and 58 deletions

View file

@ -2,11 +2,13 @@ import requests
import json import json
import time import time
from copy import deepcopy
from googlefinance import getQuotes from googlefinance import getQuotes
from lbrynet.conf import CURRENCIES from lbrynet.conf import CURRENCIES
import logging import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
log.setLevel(logging.INFO)
BITTREX_FEE = 0.0025 BITTREX_FEE = 0.0025
@ -26,23 +28,42 @@ FEE_REVISIONS = {'0.0.1': {'required': ['amount', 'address'], 'optional': []}}
CURRENT_FEE_REVISION = '0.0.1' CURRENT_FEE_REVISION = '0.0.1'
class LBRYFee(object): class LBRYFeeFormat(dict):
def __init__(self, fee_dict, rate_dict): def __init__(self, fee_dict):
fee = LBRYFeeFormat(fee_dict) dict.__init__(self)
self.fee_version = None
for currency in fee: f = deepcopy(fee_dict)
self.address = fee[currency]['address'] assert len(fee_dict) == 1
if not isinstance(fee[currency]['amount'], float): for currency in fee_dict:
self.amount = float(fee[currency]['amount']) assert currency in CURRENCIES, "Unsupported currency: %s" % str(currency)
else:
self.amount = fee[currency]['amount']
self.currency_symbol = currency self.currency_symbol = currency
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())
assert 'BTCLBC' in rate_dict and 'USDBTC' in rate_dict 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']
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
for fx in rate_dict: for fx in rate_dict:
assert int(time.time()) - int(rate_dict[fx]['ts']) < 3600, "%s quote is out of date" % fx assert int(time.time()) - int(rates[fx]['ts']) < 3600, "%s quote is out of date" % fx
self._USDBTC = {'spot': rate_dict['USDBTC']['spot'], 'ts': rate_dict['USDBTC']['ts']} self._USDBTC = {'spot': rates['USDBTC']['spot'], 'ts': rates['USDBTC']['ts']}
self._BTCLBC = {'spot': rate_dict['BTCLBC']['spot'], 'ts': rate_dict['BTCLBC']['ts']} self._BTCLBC = {'spot': rates['BTCLBC']['spot'], 'ts': rates['BTCLBC']['ts']}
def to_lbc(self): def to_lbc(self):
r = None r = None
@ -67,45 +88,31 @@ class LBRYFee(object):
return r return r
def _usd_to_btc(self, usd): def _usd_to_btc(self, usd):
# log.error("usd to btc: " + str(usd))
# log.error("%f * %f = %f" % (self._USDBTC['spot'], float(usd), self._USDBTC['spot'] * float(usd)))
return self._USDBTC['spot'] * float(usd) return self._USDBTC['spot'] * float(usd)
def _btc_to_usd(self, btc): def _btc_to_usd(self, btc):
# log.error("btc to usd: " + str(btc))
# log.error("%f / %f = %f" % (float(btc), self._USDBTC['spot'], float(btc) / self._USDBTC['spot']))
return float(btc) / self._USDBTC['spot'] return float(btc) / self._USDBTC['spot']
def _btc_to_lbc(self, btc): def _btc_to_lbc(self, btc):
# 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)))
return float(btc) * self._BTCLBC['spot'] / (1.0 - BITTREX_FEE) return float(btc) * self._BTCLBC['spot'] / (1.0 - BITTREX_FEE)
def _lbc_to_btc(self, lbc): def _lbc_to_btc(self, lbc):
# log.error("lbc to btc: " + str(lbc))
# log.error("%f / %f = %f" % (self._BTCLBC['spot'], float(lbc), self._BTCLBC['spot'] / float(lbc)))
return self._BTCLBC['spot'] / float(lbc) return self._BTCLBC['spot'] / float(lbc)
class LBRYFeeFormat(dict):
def __init__(self, fee_dict):
dict.__init__(self)
self.fee_version = None
f = fee_dict.copy()
assert len(fee_dict) == 1
for currency in fee_dict:
assert currency in CURRENCIES, "Unsupported currency: %s" % str(currency)
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())
class Metadata(dict): class Metadata(dict):
def __init__(self, metadata): def __init__(self, metadata):
dict.__init__(self) dict.__init__(self)
self.metaversion = None self.metaversion = None
m = metadata.copy() m = deepcopy(metadata)
assert "sources" in metadata, "No sources given" assert "sources" in metadata, "No sources given"
for source in metadata['sources']: for source in metadata['sources']:

View file

@ -1899,20 +1899,19 @@ class LBRYDaemon(jsonrpc.JSONRPC):
file_path = p['file_path'] file_path = p['file_path']
metadata = p['metadata'] metadata = p['metadata']
def _set_address(address): d = defer.succeed(None)
metadata['fee']['address'] = address
def _set_address(address, currency):
metadata['fee'][currency]['address'] = address
return defer.succeed(None) return defer.succeed(None)
if 'fee' in p: if 'fee' in p:
metadata['fee'] = p['fee'] metadata['fee'] = p['fee']
if 'address' not in metadata['fee']: assert len(metadata['fee']) == 1, "Too many fees"
d = self.session.wallet.get_new_address() for c in metadata['fee']:
d.addCallback(_set_address) if 'address' not in metadata['fee'][c]:
else: d = self.session.wallet.get_new_address()
d = defer.succeed(None) d.addCallback(lambda addr: _set_address(addr, c))
else:
d = defer.succeed(None)
pub = Publisher(self.session, self.lbry_file_manager, self.session.wallet) pub = Publisher(self.session, self.lbry_file_manager, self.session.wallet)

View file

@ -3,6 +3,7 @@ import logging
import os import os
import sys import sys
from copy import deepcopy
from appdirs import user_data_dir from appdirs import user_data_dir
from datetime import datetime from datetime import datetime
from twisted.internet import defer from twisted.internet import defer
@ -58,7 +59,7 @@ class GetStream(object):
self.sd_identifier = sd_identifier self.sd_identifier = sd_identifier
self.stream_hash = None self.stream_hash = None
self.max_key_fee = max_key_fee self.max_key_fee = max_key_fee
self.metadata = None self.stream_info = None
self.stream_info_manager = None self.stream_info_manager = None
self.d = defer.Deferred(None) self.d = defer.Deferred(None)
self.timeout = timeout self.timeout = timeout
@ -86,20 +87,23 @@ class GetStream(object):
def start(self, stream_info, name): def start(self, stream_info, name):
self.resolved_name = name self.resolved_name = name
self.metadata = stream_info self.stream_info = deepcopy(stream_info)
self.stream_hash = self.metadata['sources']['lbry_sd_hash'] self.description = self.stream_info['description']
self.stream_hash = self.stream_info['sources']['lbry_sd_hash']
if 'fee' in self.metadata: if 'fee' in self.stream_info:
self.fee = LBRYFee(self.metadata['fee'], {'USDBTC': self.wallet._USDBTC, 'BTCLBC': self.wallet._BTCLBC}) self.fee = LBRYFee(self.stream_info['fee'], {'USDBTC': self.wallet._USDBTC, 'BTCLBC': self.wallet._BTCLBC})
if isinstance(self.max_key_fee, float): if isinstance(self.max_key_fee, float):
if self.fee.to_lbc() > self.max_key_fee: if self.fee.to_lbc() > self.max_key_fee:
log.info("Key fee %f above limit of %f didn't download lbry://%s" % (self.fee.to_lbc(), self.max_key_fee, self.resolved_name)) log.info("Key fee %f above limit of %f didn't download lbry://%s" % (self.fee.to_lbc(), self.max_key_fee, self.resolved_name))
return defer.fail(KeyFeeAboveMaxAllowed()) return defer.fail(KeyFeeAboveMaxAllowed())
log.info("Key fee %f below limit of %f, downloading lbry://%s" % (self.fee.to_lbc(), self.max_key_fee, self.resolved_name))
elif isinstance(self.max_key_fee, dict): elif isinstance(self.max_key_fee, dict):
max_key = LBRYFee(self.max_key_fee, {'USDBTC': self.wallet._USDBTC, 'BTCLBC': self.wallet._BTCLBC}) max_key = LBRYFee(deepcopy(self.max_key_fee), {'USDBTC': self.wallet._USDBTC, 'BTCLBC': self.wallet._BTCLBC})
if self.fee.to_lbc() > max_key.to_lbc(): if self.fee.to_lbc() > max_key.to_lbc():
log.info("Key fee %f above limit of %f didn't download lbry://%s" % (self.fee.to_lbc(), max_key.to_lbc(), self.resolved_name)) log.info("Key fee %f above limit of %f didn't download lbry://%s" % (self.fee.to_lbc(), max_key.to_lbc(), self.resolved_name))
return defer.fail(KeyFeeAboveMaxAllowed()) return defer.fail(KeyFeeAboveMaxAllowed())
log.info("Key fee %f below limit of %f, downloading lbry://%s" % (self.fee.to_lbc(), max_key.to_lbc(), self.resolved_name))
def _cause_timeout(): def _cause_timeout():
self.timeout_counter = self.timeout * 2 self.timeout_counter = self.timeout * 2
@ -130,20 +134,19 @@ class GetStream(object):
def _start_download(self, downloader): def _start_download(self, downloader):
def _pay_key_fee(): def _pay_key_fee():
if self.fee is not None: if self.fee is not None:
fee_lbc = self.fee.to_lbc() fee_lbc = float(self.fee.to_lbc())
reserved_points = self.wallet.reserve_points(self.fee.address, fee_lbc) reserved_points = self.wallet.reserve_points(self.fee.address, fee_lbc)
if reserved_points is None: if reserved_points is None:
return defer.fail(InsufficientFundsError()) return defer.fail(InsufficientFundsError())
log.info("Key fee: %f --> %s" % (fee_lbc, self.fee.address)) return self.wallet.send_points_to_address(reserved_points, fee_lbc)
d = self.wallet.send_points_to_address(reserved_points, self.fee.address)
return d
return defer.succeed(None) return defer.succeed(None)
d = _pay_key_fee()
self.downloader = downloader self.downloader = downloader
self.download_path = os.path.join(downloader.download_directory, downloader.file_name) self.download_path = os.path.join(downloader.download_directory, downloader.file_name)
d = _pay_key_fee()
d.addCallback(lambda _: log.info("Downloading %s --> %s", self.stream_hash, self.downloader.file_name)) d.addCallback(lambda _: log.info("Downloading %s --> %s", self.stream_hash, self.downloader.file_name))
d.addCallback(lambda _: self.downloader.start()) d.addCallback(lambda _: self.downloader.start())