From 25d1b8b9e5a35ba7f9b3a2924a93544fbfa041fb Mon Sep 17 00:00:00 2001 From: Jack Date: Thu, 21 Jul 2016 16:11:14 -0400 Subject: [PATCH] move towards better fees and metadata --- lbrynet/conf.py | 9 +++-- lbrynet/core/LBRYFee.py | 39 +++++++++++++++++++ lbrynet/core/LBRYWallet.py | 7 ---- lbrynet/lbrynet_daemon/LBRYDaemon.py | 23 +++++++++-- lbrynet/lbrynet_daemon/LBRYDownloader.py | 10 ++--- .../daemon_scripts/Autofetcher.py | 22 +++++++++++ 6 files changed, 89 insertions(+), 21 deletions(-) create mode 100644 lbrynet/core/LBRYFee.py diff --git a/lbrynet/conf.py b/lbrynet/conf.py index 9ead15f4d..59150a085 100644 --- a/lbrynet/conf.py +++ b/lbrynet/conf.py @@ -42,11 +42,14 @@ DEFAULT_WALLET = "lbryum" WALLET_TYPES = ["lbryum", "lbrycrd"] DEFAULT_TIMEOUT = 30 DEFAULT_MAX_SEARCH_RESULTS = 25 -DEFAULT_MAX_KEY_FEE = 100.0 +DEFAULT_MAX_KEY_FEE = {'BTC': {'amount': 0.025}} DEFAULT_SEARCH_TIMEOUT = 3.0 DEFAULT_CACHE_TIME = 3600 DEFAULT_UI_BRANCH = "master" SOURCE_TYPES = ['lbry_sd_hash', 'url', 'btih'] -BASE_METADATA_FIELDS = ['title', 'description', 'author', 'language', 'license', 'content-type'] -OPTIONAL_METADATA_FIELDS = ['thumbnail', 'preview', 'fee', 'contact', 'pubkey'] \ No newline at end of file + +CURRENCIES = [ + {'BTC': {'type': 'crypto'}}, + {'LBC': {'type': 'crypto'}}, +] \ No newline at end of file diff --git a/lbrynet/core/LBRYFee.py b/lbrynet/core/LBRYFee.py new file mode 100644 index 000000000..09b7dbd39 --- /dev/null +++ b/lbrynet/core/LBRYFee.py @@ -0,0 +1,39 @@ +import requests +import json + +from lbrynet.conf import CURRENCIES + + +class LBRYFee(object): + def __init__(self, currency, amount, address=None): + assert currency in [c.keys()[0] for c in CURRENCIES], "Unsupported currency: %s" % str(currency) + self.address = address + self.currency_symbol = currency + self.currency = [c for c in CURRENCIES if self.currency_symbol in c][0] + if not isinstance(amount, float): + self.amount = float(amount) + else: + self.amount = amount + + def convert_to(self, to_currency, rate_dict={}): + if to_currency is self.currency_symbol: + return self.as_dict() + if self.currency[self.currency_symbol]['type'] is 'fiat': + raise NotImplemented + else: + if to_currency not in rate_dict: + params = {'market': '%s-%s' % (self.currency_symbol, to_currency)} + r = requests.get("https://bittrex.com/api/v1.1/public/getticker", params) + last = json.loads(r.text)['result']['Last'] + converted = self.amount / float(last) + else: + converted = self.amount / float(rate_dict[to_currency]['last']) + + return LBRYFee(to_currency, converted, self.address).as_dict() + + def as_dict(self): + return {self.currency_symbol: {'amount': self.amount, 'address': self.address}} + + def from_dict(self, fee_dict): + s = fee_dict.keys()[0] + return LBRYFee(s, fee_dict[s]['amount'], fee_dict[s]['address']) \ No newline at end of file diff --git a/lbrynet/core/LBRYWallet.py b/lbrynet/core/LBRYWallet.py index 0bf99f7a5..0e9e3a360 100644 --- a/lbrynet/core/LBRYWallet.py +++ b/lbrynet/core/LBRYWallet.py @@ -349,13 +349,6 @@ class LBRYWallet(object): value['sources'][k] = sources[k] if value['sources'] == {}: return defer.fail("No source given") - for k in BASE_METADATA_FIELDS: - if k not in metadata: - return defer.fail("Missing required field '%s'" % k) - value[k] = metadata[k] - for k in metadata: - if k not in BASE_METADATA_FIELDS: - value[k] = metadata[k] if fee is not None: if "LBC" in fee: value['fee'] = {'LBC': {'amount': fee['LBC']['amount'], 'address': fee['LBC']['address']}} diff --git a/lbrynet/lbrynet_daemon/LBRYDaemon.py b/lbrynet/lbrynet_daemon/LBRYDaemon.py index 8e2c98cc5..75aaa0096 100644 --- a/lbrynet/lbrynet_daemon/LBRYDaemon.py +++ b/lbrynet/lbrynet_daemon/LBRYDaemon.py @@ -32,6 +32,8 @@ from lbrynet.core.server.BlobAvailabilityHandler import BlobAvailabilityHandlerF from lbrynet.core.server.BlobRequestHandler import BlobRequestHandlerFactory from lbrynet.core.server.ServerProtocol import ServerProtocolFactory from lbrynet.core.Error import UnknownNameError, InsufficientFundsError +from lbrynet.core.LBRYFee import LBRYFee +from lbrynet.core.LBRYMetadata import Metadata from lbrynet.lbryfile.StreamDescriptor import LBRYFileStreamType from lbrynet.lbryfile.client.LBRYFileDownloader import LBRYFileSaverFactory, LBRYFileOpenerFactory from lbrynet.lbryfile.client.LBRYFileOptions import add_lbry_file_to_sd_identifier @@ -41,8 +43,7 @@ from lbrynet.lbrynet_daemon.LBRYPublisher import Publisher from lbrynet.core.utils import generate_id from lbrynet.lbrynet_console.LBRYSettings import LBRYSettings from lbrynet.conf import MIN_BLOB_DATA_PAYMENT_RATE, DEFAULT_MAX_SEARCH_RESULTS, KNOWN_DHT_NODES, DEFAULT_MAX_KEY_FEE, \ - DEFAULT_WALLET, DEFAULT_SEARCH_TIMEOUT, DEFAULT_CACHE_TIME, DEFAULT_UI_BRANCH, LOG_POST_URL, LOG_FILE_NAME, \ - BASE_METADATA_FIELDS, OPTIONAL_METADATA_FIELDS, SOURCE_TYPES + DEFAULT_WALLET, DEFAULT_SEARCH_TIMEOUT, DEFAULT_CACHE_TIME, DEFAULT_UI_BRANCH, LOG_POST_URL, LOG_FILE_NAME, SOURCE_TYPES from lbrynet.conf import DEFAULT_TIMEOUT, WALLET_TYPES from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier, download_sd_blob from lbrynet.core.Session import LBRYSession @@ -169,6 +170,7 @@ class LBRYDaemon(jsonrpc.JSONRPC): self.streams = {} self.known_dht_nodes = KNOWN_DHT_NODES self.first_run_after_update = False + self.last_traded_rate = None if os.name == "nt": from lbrynet.winhelpers.knownpaths import get_path, FOLDERID, UserHandle @@ -249,6 +251,8 @@ class LBRYDaemon(jsonrpc.JSONRPC): self.session_settings['last_version'] = self.default_settings['last_version'] self.first_run_after_update = True log.info("First run after update") + log.info("lbrynet %s --> %s" % (self.session_settings['last_version']['lbrynet'], self.default_settings['last_version']['lbrynet'])) + log.info("lbryum %s --> %s" % (self.session_settings['last_version']['lbryum'], self.default_settings['last_version']['lbryum'])) f = open(self.daemon_conf, "w") f.write(json.dumps(self.session_settings)) @@ -337,6 +341,7 @@ class LBRYDaemon(jsonrpc.JSONRPC): self.internet_connection_checker = LoopingCall(self._check_network_connection) self.version_checker = LoopingCall(self._check_remote_versions) self.connection_problem_checker = LoopingCall(self._check_connection_problems) + self.price_checker = LoopingCall(self._update_exchange) # self.lbrynet_connection_checker = LoopingCall(self._check_lbrynet_connection) self.sd_identifier = StreamDescriptorIdentifier() @@ -470,6 +475,7 @@ class LBRYDaemon(jsonrpc.JSONRPC): self.internet_connection_checker.start(3600) self.version_checker.start(3600 * 12) self.connection_problem_checker.start(1) + self.price_checker.start(600) if host_ui: self.lbry_ui_manager.update_checker.start(1800, now=False) @@ -590,6 +596,13 @@ class LBRYDaemon(jsonrpc.JSONRPC): if not self.connected_to_internet: self.connection_problem = CONNECTION_PROBLEM_CODES[1] + def _update_exchange(self): + try: + r = requests.get("https://bittrex.com/api/v1.1/public/getticker", {'market': 'BTC-LBC'}) + self.last_traded_rate = float(json.loads(r.text)['result']['Last']) + except: + self.last_traded_rate = None + def _start_server(self): if self.peer_port is not None: @@ -701,6 +714,8 @@ class LBRYDaemon(jsonrpc.JSONRPC): self.connection_problem_checker.stop() if self.lbry_ui_manager.update_checker.running: self.lbry_ui_manager.update_checker.stop() + if self.price_checker.running: + self.price_checker.stop() d = self._upload_log(log_type="close", exclude_previous=False if self.first_run else True) d.addCallback(lambda _: self._stop_server()) @@ -1868,9 +1883,9 @@ class LBRYDaemon(jsonrpc.JSONRPC): name = p['name'] bid = p['bid'] file_path = p['file_path'] - metadata = p['metadata'] + metadata = Metadata(p['metadata']) if 'fee' in p: - fee = p['fee'] + fee = LBRYFee.from_dict(p['fee']) else: fee = None diff --git a/lbrynet/lbrynet_daemon/LBRYDownloader.py b/lbrynet/lbrynet_daemon/LBRYDownloader.py index c72444c70..9cfbf07c1 100644 --- a/lbrynet/lbrynet_daemon/LBRYDownloader.py +++ b/lbrynet/lbrynet_daemon/LBRYDownloader.py @@ -11,6 +11,7 @@ from twisted.internet.task import LoopingCall from lbrynet.core.Error import InvalidStreamInfoError, InsufficientFundsError from lbrynet.core.PaymentRateManager import PaymentRateManager from lbrynet.core.StreamDescriptor import download_sd_blob +from lbrynet.core.LBRYFee import LBRYFee from lbrynet.lbryfilemanager.LBRYFileDownloader import ManagedLBRYFileDownloaderFactory from lbrynet.conf import DEFAULT_TIMEOUT, LOG_FILE_NAME @@ -94,14 +95,9 @@ class GetStream(object): if 'description' in self.stream_info: self.description = self.stream_info['description'] if 'fee' in self.stream_info: - if 'LBC' in self.stream_info['fee']: - self.key_fee = float(self.stream_info['fee']['LBC']['amount']) - self.key_fee_address = self.stream_info['fee']['LBC']['address'] - else: - self.key_fee_address = None + self.fee = LBRYFee.from_dict(stream_info['fee']) else: - self.key_fee = None - self.key_fee_address = None + self.fee = None if self.key_fee > self.max_key_fee: log.info("Key fee %f above limit of %f didn't download lbry://%s" % (self.key_fee, self.max_key_fee, self.resolved_name)) return defer.fail(None) diff --git a/lbrynet/lbrynet_daemon/daemon_scripts/Autofetcher.py b/lbrynet/lbrynet_daemon/daemon_scripts/Autofetcher.py index cd7ed02cb..92ea9f9f1 100644 --- a/lbrynet/lbrynet_daemon/daemon_scripts/Autofetcher.py +++ b/lbrynet/lbrynet_daemon/daemon_scripts/Autofetcher.py @@ -2,10 +2,13 @@ import json import logging.handlers import sys import os +import requests +from datetime import datetime from appdirs import user_data_dir from twisted.internet.task import LoopingCall from twisted.internet import reactor +from twisted.internet.threads import deferToThread if sys.platform != "darwin": @@ -39,11 +42,15 @@ class Autofetcher(object): def __init__(self, api): self._api = api self._checker = LoopingCall(self._check_for_new_claims) + self._price_checker = LoopingCall(self._update_price) self.best_block = None + self.last_price = None + self.price_updated = None def start(self): reactor.addSystemEventTrigger('before', 'shutdown', self.stop) self._checker.start(5) + self._price_checker.start(30) def stop(self): log.info("Stopping autofetcher") @@ -59,9 +66,24 @@ class Autofetcher(object): c = self._api.get_claims_for_tx({'txid': t}) if len(c): for i in c: + if 'fee' in json.loads(i['value']): + log.info("Downloading stream for claim txid: %s" % t) self._api.get({'name': t, 'stream_info': json.loads(i['value'])}) + def _update_price(self): + def _check_bittrex(): + try: + r = requests.get("https://bittrex.com/api/v1.1/public/getticker", {'market': 'BTC-LBC'}) + self.last_price = json.loads(r.text)['result']['Last'] + self.price_updated = datetime.now() + log.info("Updated exchange rate, last BTC-LBC trade: %f" % self.last_price) + except: + log.info("Failed to update exchange rate") + self.last_price = None + self.price_updated = datetime.now() + return deferToThread(_check_bittrex) + def run(api): fetcher = Autofetcher(api)