diff --git a/lbrynet/core/LBRYcrdWallet.py b/lbrynet/core/LBRYcrdWallet.py index 3c3f69c41..7711e393b 100644 --- a/lbrynet/core/LBRYcrdWallet.py +++ b/lbrynet/core/LBRYcrdWallet.py @@ -149,11 +149,11 @@ class LBRYcrdWallet(object): d = threads.deferToThread(self._get_wallet_balance) return d - def reserve_points(self, peer, amount): + def reserve_points(self, identifier, amount): """ Ensure a certain amount of points are available to be sent as payment, before the service is rendered - @param peer: The peer to which the payment will ultimately be sent + @param identifier: The peer to which the payment will ultimately be sent @param amount: The amount of points to reserve @@ -163,7 +163,7 @@ class LBRYcrdWallet(object): #if peer in self.peer_addresses: if self.wallet_balance >= self.total_reserved_points + rounded_amount: self.total_reserved_points += rounded_amount - return ReservedPoints(peer, rounded_amount) + return ReservedPoints(identifier, rounded_amount) return None def cancel_point_reservation(self, reserved_points): @@ -199,6 +199,26 @@ class LBRYcrdWallet(object): peer.update_stats('points_sent', amount) return defer.succeed(True) + def send_points_to_address(self, reserved_points, amount): + """ + Schedule a payment to be sent to an address + + @param reserved_points: ReservedPoints object previously returned by reserve_points + + @param amount: amount of points to actually send. must be less than or equal to the + amount reselved in reserved_points + + @return: Deferred which fires when the payment has been scheduled + """ + rounded_amount = Decimal(str(round(amount, 8))) + address = reserved_points.identifier + assert(rounded_amount <= reserved_points.amount) + self.queued_payments[address] += rounded_amount + self.total_reserved_points -= (reserved_points.amount - rounded_amount) + log.info("Ordering that %s points be sent to %s", str(rounded_amount), + str(address)) + return defer.succeed(True) + def add_expected_payment(self, peer, amount): """Increase the number of points expected to be paid by a peer""" rounded_amount = Decimal(str(round(amount, 8))) @@ -232,12 +252,10 @@ class LBRYcrdWallet(object): value_dict = json.loads(value) except ValueError: return Failure(InvalidStreamInfoError(name)) - if 'stream_hash' in value_dict: - r_dict['stream_hash'] = value_dict['stream_hash'] - if 'name' in value_dict: - r_dict['name'] = value_dict['name'] - if 'description' in value_dict: - r_dict['description'] = value_dict['description'] + known_fields = ['stream_hash', 'name', 'description', 'key_fee', 'key_fee_address'] + for field in known_fields: + if field in value_dict: + r_dict[field] = value_dict[field] return r_dict return Failure(UnknownNameError(name)) diff --git a/lbrynet/lbrynet_console/ControlHandlers.py b/lbrynet/lbrynet_console/ControlHandlers.py index 32a2dd249..6c17e162d 100644 --- a/lbrynet/lbrynet_console/ControlHandlers.py +++ b/lbrynet/lbrynet_console/ControlHandlers.py @@ -8,6 +8,7 @@ from lbrynet.lbryfile.StreamDescriptor import get_sd_info from lbrynet.lbrynet_console.interfaces import IControlHandler, IControlHandlerFactory from lbrynet.core.StreamDescriptor import download_sd_blob, BlobStreamDescriptorReader from lbrynet.core.Error import UnknownNameError, InvalidBlobHashError, InsufficientFundsError +from lbrynet.core.Error import InvalidStreamInfoError from twisted.internet import defer, threads import os @@ -505,9 +506,13 @@ class AddStreamFromLBRYcrdName(AddStreamFromHash): prompt_description = "Add a stream from a short name" line_prompt = "Short name:" - def __init__(self, sd_identifier, session, name_resolver): + def __init__(self, sd_identifier, session, wallet): AddStreamFromHash.__init__(self, sd_identifier, session) - self.name_resolver = name_resolver + self.wallet = wallet + self.resolved_nome = None + self.description = None + self.key_fee = None + self.key_fee_address = None def _load_metadata(self, name): d = self._resolve_name(name) @@ -516,8 +521,18 @@ class AddStreamFromLBRYcrdName(AddStreamFromHash): def _resolve_name(self, name): def get_name_from_info(stream_info): + if 'stream_hash' not in stream_info: + raise InvalidStreamInfoError(name) + self.resolved_name = stream_info.get('name', None) + self.description = stream_info.get('description', None) + try: + if 'key_fee' in stream_info: + self.key_fee = float(stream_info['key_fee']) + except ValueError: + self.key_fee = None + self.key_fee_address = stream_info.get('key_fee_address', None) return stream_info['stream_hash'] - d = self.name_resolver.get_stream_info_for_name(name) + d = self.wallet.get_stream_info_for_name(name) d.addCallback(get_name_from_info) return d @@ -531,6 +546,19 @@ class AddStreamFromLBRYcrdName(AddStreamFromHash): "Press enter to continue") return AddStreamFromHash._handle_load_failed(self, err) + def _start_download(self): + d = self._pay_key_fee() + d.addCallback(lambda _: AddStream._start_download(self)) + return d + + def _pay_key_fee(self): + if self.key_fee is not None and self.key_fee_address is not None: + reserved_points = self.wallet.reserve_points(self.key_fee_address, self.key_fee) + if reserved_points is None: + return defer.fail(InsufficientFundsError()) + return self.wallet.send_points_to_address(reserved_points, self.key_fee) + return defer.succeed(True) + class AddStreamFromLBRYcrdNameFactory(ControlHandlerFactory): control_handler_class = AddStreamFromLBRYcrdName