forked from LBRYCommunity/lbry-sdk
changes from jacks review
This commit is contained in:
parent
e6fd8cc0f2
commit
3686b1d970
10 changed files with 201 additions and 1685 deletions
|
@ -1,4 +1,16 @@
|
||||||
import sys
|
import sys
|
||||||
|
from twisted.internet import asyncioreactor
|
||||||
|
if 'twisted.internet.reactor' not in sys.modules:
|
||||||
|
asyncioreactor.install()
|
||||||
|
else:
|
||||||
|
from twisted.internet import reactor
|
||||||
|
if not isinstance(reactor, asyncioreactor.AsyncioSelectorReactor):
|
||||||
|
# pyinstaller hooks install the default reactor before
|
||||||
|
# any of our code runs, see kivy for similar problem:
|
||||||
|
# https://github.com/kivy/kivy/issues/4182
|
||||||
|
del sys.modules['twisted.internet.reactor']
|
||||||
|
asyncioreactor.install()
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import asyncio
|
import asyncio
|
||||||
from aiohttp.client_exceptions import ClientConnectorError
|
from aiohttp.client_exceptions import ClientConnectorError
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -73,7 +73,7 @@ class ClientProtocol(Protocol, TimeoutMixin):
|
||||||
log.debug("Connection lost to %s: %s", self.peer, reason)
|
log.debug("Connection lost to %s: %s", self.peer, reason)
|
||||||
self.setTimeout(None)
|
self.setTimeout(None)
|
||||||
self.connection_closed = True
|
self.connection_closed = True
|
||||||
if reason.check(error.ConnectionDone) or reason is None:
|
if reason is None or reason.check(error.ConnectionDone):
|
||||||
err = failure.Failure(ConnectionClosedBeforeResponseError())
|
err = failure.Failure(ConnectionClosedBeforeResponseError())
|
||||||
else:
|
else:
|
||||||
err = reason
|
err = reason
|
||||||
|
|
|
@ -6,19 +6,7 @@ import urllib
|
||||||
import json
|
import json
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
#import sys
|
from operator import itemgetter
|
||||||
#from twisted.internet import asyncioreactor
|
|
||||||
#if 'twisted.internet.reactor' not in sys.modules:
|
|
||||||
# asyncioreactor.install()
|
|
||||||
#else:
|
|
||||||
# from twisted.internet import reactor
|
|
||||||
# if not isinstance(reactor, asyncioreactor.AsyncioSelectorReactor):
|
|
||||||
# # pyinstaller hooks install the default reactor before
|
|
||||||
# # any of our code runs, see kivy for similar problem:
|
|
||||||
# # https://github.com/kivy/kivy/issues/4182
|
|
||||||
# del sys.modules['twisted.internet.reactor']
|
|
||||||
# asyncioreactor.install()
|
|
||||||
|
|
||||||
from binascii import hexlify, unhexlify
|
from binascii import hexlify, unhexlify
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from decimal import Decimal, InvalidOperation
|
from decimal import Decimal, InvalidOperation
|
||||||
|
@ -92,6 +80,7 @@ DIRECTION_ASCENDING = 'asc'
|
||||||
DIRECTION_DESCENDING = 'desc'
|
DIRECTION_DESCENDING = 'desc'
|
||||||
DIRECTIONS = DIRECTION_ASCENDING, DIRECTION_DESCENDING
|
DIRECTIONS = DIRECTION_ASCENDING, DIRECTION_DESCENDING
|
||||||
|
|
||||||
|
|
||||||
class IterableContainer:
|
class IterableContainer:
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
for attr in dir(self):
|
for attr in dir(self):
|
||||||
|
@ -251,7 +240,10 @@ class Daemon(AuthJSONRPCServer):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ledger(self):
|
def ledger(self):
|
||||||
|
try:
|
||||||
return self.wallet.default_account.ledger
|
return self.wallet.default_account.ledger
|
||||||
|
except AttributeError:
|
||||||
|
return None
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def setup(self):
|
def setup(self):
|
||||||
|
@ -395,51 +387,15 @@ class Daemon(AuthJSONRPCServer):
|
||||||
log.exception)
|
log.exception)
|
||||||
self.analytics_manager.send_claim_action('publish')
|
self.analytics_manager.send_claim_action('publish')
|
||||||
nout = 0
|
nout = 0
|
||||||
log.info("Success! Published to lbry://%s txid: %s nout: %d", name, tx.id, nout)
|
|
||||||
defer.returnValue(self._txo_to_response(tx, nout))
|
|
||||||
|
|
||||||
def _txo_to_response(self, tx, nout):
|
|
||||||
txo = tx.outputs[nout]
|
txo = tx.outputs[nout]
|
||||||
return {
|
log.info("Success! Published to lbry://%s txid: %s nout: %d", name, tx.id, nout)
|
||||||
|
defer.returnValue({
|
||||||
"success": True,
|
"success": True,
|
||||||
"txid": tx.id,
|
"tx": tx,
|
||||||
"nout": nout,
|
|
||||||
"tx": hexlify(tx.raw),
|
|
||||||
"fee": str(Decimal(tx.fee) / COIN),
|
|
||||||
"claim_id": txo.claim_id,
|
"claim_id": txo.claim_id,
|
||||||
"value": hexlify(txo.claim).decode(),
|
"claim_address": self.ledger.hash160_to_address(txo.script.values['pubkey_hash']),
|
||||||
"claim_address": self.ledger.hash160_to_address(txo.script.values['pubkey_hash'])
|
"output": tx.outputs[nout]
|
||||||
}
|
})
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def _resolve(self, *uris, **kwargs):
|
|
||||||
"""Resolves a URI. Can check the cache first before going out to the blockchain and stores the result.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
name: the lbry://<name> to resolve
|
|
||||||
force_refresh: if True, always go out to the blockchain to resolve.
|
|
||||||
"""
|
|
||||||
|
|
||||||
page = kwargs.get('page', 0)
|
|
||||||
page_size = kwargs.get('page_size', 10)
|
|
||||||
check_cache = kwargs.get('check_cache', False) # TODO: put caching back (was force_refresh parameter)
|
|
||||||
results = yield self.wallet.resolve(*uris, page=page, page_size=page_size)
|
|
||||||
self.save_claims((value for value in results.values() if 'error' not in value))
|
|
||||||
yield defer.returnValue(results)
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def save_claims(self, claim_infos):
|
|
||||||
to_save = []
|
|
||||||
for info in claim_infos:
|
|
||||||
if 'value' in info:
|
|
||||||
if info['value']:
|
|
||||||
to_save.append(info)
|
|
||||||
else:
|
|
||||||
if 'certificate' in info and info['certificate']['value']:
|
|
||||||
to_save.append(info['certificate'])
|
|
||||||
if 'claim' in info and info['claim']['value']:
|
|
||||||
to_save.append(info['claim'])
|
|
||||||
yield self.storage.save_claims(to_save)
|
|
||||||
|
|
||||||
def _get_or_download_sd_blob(self, blob, sd_hash):
|
def _get_or_download_sd_blob(self, blob, sd_hash):
|
||||||
if blob:
|
if blob:
|
||||||
|
@ -484,7 +440,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
|
|
||||||
cost = self._get_est_cost_from_stream_size(size)
|
cost = self._get_est_cost_from_stream_size(size)
|
||||||
|
|
||||||
resolved = yield self._resolve(uri)
|
resolved = yield self.wallet.resolve(uri)
|
||||||
|
|
||||||
if uri in resolved and 'claim' in resolved[uri]:
|
if uri in resolved and 'claim' in resolved[uri]:
|
||||||
claim = ClaimDict.load_dict(resolved[uri]['claim']['value'])
|
claim = ClaimDict.load_dict(resolved[uri]['claim']['value'])
|
||||||
|
@ -531,7 +487,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
Resolve a name and return the estimated stream cost
|
Resolve a name and return the estimated stream cost
|
||||||
"""
|
"""
|
||||||
|
|
||||||
resolved = (yield self._resolve(uri))[uri]
|
resolved = (yield self.wallet.resolve(uri))[uri]
|
||||||
if resolved:
|
if resolved:
|
||||||
claim_response = resolved[uri]
|
claim_response = resolved[uri]
|
||||||
else:
|
else:
|
||||||
|
@ -1012,7 +968,8 @@ class Daemon(AuthJSONRPCServer):
|
||||||
Returns:
|
Returns:
|
||||||
(float) amount of lbry credits in wallet
|
(float) amount of lbry credits in wallet
|
||||||
"""
|
"""
|
||||||
assert address is None, "Limiting by address needs to be re-implemented in new wallet."
|
if address is not None:
|
||||||
|
raise NotImplementedError("Limiting by address needs to be re-implemented in new wallet.")
|
||||||
dewies = yield self.wallet.default_account.get_balance(
|
dewies = yield self.wallet.default_account.get_balance(
|
||||||
0 if include_unconfirmed else 6
|
0 if include_unconfirmed else 6
|
||||||
)
|
)
|
||||||
|
@ -1046,7 +1003,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
||||||
@defer.inlineCallbacks
|
|
||||||
def jsonrpc_wallet_decrypt(self):
|
def jsonrpc_wallet_decrypt(self):
|
||||||
"""
|
"""
|
||||||
Decrypt an encrypted wallet, this will remove the wallet password
|
Decrypt an encrypted wallet, this will remove the wallet password
|
||||||
|
@ -1060,13 +1016,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
Returns:
|
Returns:
|
||||||
(bool) true if wallet is decrypted, otherwise false
|
(bool) true if wallet is decrypted, otherwise false
|
||||||
"""
|
"""
|
||||||
|
return defer.succeed(self.wallet.decrypt_wallet())
|
||||||
result = self.wallet.decrypt_wallet()
|
|
||||||
response = yield self._render_response(result)
|
|
||||||
defer.returnValue(response)
|
|
||||||
|
|
||||||
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
||||||
@defer.inlineCallbacks
|
|
||||||
def jsonrpc_wallet_encrypt(self, new_password):
|
def jsonrpc_wallet_encrypt(self, new_password):
|
||||||
"""
|
"""
|
||||||
Encrypt a wallet with a password, if the wallet is already encrypted this will update
|
Encrypt a wallet with a password, if the wallet is already encrypted this will update
|
||||||
|
@ -1081,13 +1033,11 @@ class Daemon(AuthJSONRPCServer):
|
||||||
Returns:
|
Returns:
|
||||||
(bool) true if wallet is decrypted, otherwise false
|
(bool) true if wallet is decrypted, otherwise false
|
||||||
"""
|
"""
|
||||||
|
return defer.succeed(self.wallet.encrypt_wallet(new_password))
|
||||||
self.wallet.encrypt_wallet(new_password)
|
|
||||||
response = yield self._render_response(self.wallet.wallet.use_encryption)
|
|
||||||
defer.returnValue(response)
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def jsonrpc_stop(self):
|
@AuthJSONRPCServer.deprecated("stop")
|
||||||
|
def jsonrpc_daemon_stop(self):
|
||||||
"""
|
"""
|
||||||
Stop lbrynet-daemon
|
Stop lbrynet-daemon
|
||||||
|
|
||||||
|
@ -1100,11 +1050,24 @@ class Daemon(AuthJSONRPCServer):
|
||||||
Returns:
|
Returns:
|
||||||
(string) Shutdown message
|
(string) Shutdown message
|
||||||
"""
|
"""
|
||||||
|
return self.jsonrpc_stop()
|
||||||
|
|
||||||
|
def jsonrpc_stop(self):
|
||||||
|
"""
|
||||||
|
Stop lbrynet
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
stop
|
||||||
|
|
||||||
|
Options:
|
||||||
|
None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(string) Shutdown message
|
||||||
|
"""
|
||||||
log.info("Shutting down lbrynet daemon")
|
log.info("Shutting down lbrynet daemon")
|
||||||
response = yield self._render_response("Shutting down")
|
|
||||||
reactor.callLater(0.1, reactor.fireSystemEvent, "shutdown")
|
reactor.callLater(0.1, reactor.fireSystemEvent, "shutdown")
|
||||||
defer.returnValue(response)
|
defer.returnValue("Shutting down")
|
||||||
|
|
||||||
@requires(FILE_MANAGER_COMPONENT)
|
@requires(FILE_MANAGER_COMPONENT)
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@ -1198,7 +1161,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
name = parse_lbry_uri(name).name
|
name = parse_lbry_uri(name).name
|
||||||
metadata = yield self._resolve(name, check_cache=not force)
|
metadata = yield self.wallet.resolve(name, check_cache=not force)
|
||||||
if name in metadata:
|
if name in metadata:
|
||||||
metadata = metadata[name]
|
metadata = metadata[name]
|
||||||
except UnknownNameError:
|
except UnknownNameError:
|
||||||
|
@ -1337,7 +1300,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
except URIParseError:
|
except URIParseError:
|
||||||
results[u] = {"error": "%s is not a valid uri" % u}
|
results[u] = {"error": "%s is not a valid uri" % u}
|
||||||
|
|
||||||
resolved = yield self._resolve(*valid_uris, check_cache=not force)
|
resolved = yield self.wallet.resolve(*valid_uris, check_cache=not force)
|
||||||
|
|
||||||
for resolved_uri in resolved:
|
for resolved_uri in resolved:
|
||||||
results[resolved_uri] = resolved[resolved_uri]
|
results[resolved_uri] = resolved[resolved_uri]
|
||||||
|
@ -1398,7 +1361,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
if parsed_uri.is_channel and not parsed_uri.path:
|
if parsed_uri.is_channel and not parsed_uri.path:
|
||||||
raise Exception("cannot download a channel claim, specify a /path")
|
raise Exception("cannot download a channel claim, specify a /path")
|
||||||
|
|
||||||
resolved_result = yield self._resolve(uri)
|
resolved_result = yield self.wallet.resolve(uri)
|
||||||
if resolved_result and uri in resolved_result:
|
if resolved_result and uri in resolved_result:
|
||||||
resolved = resolved_result[uri]
|
resolved = resolved_result[uri]
|
||||||
else:
|
else:
|
||||||
|
@ -1584,13 +1547,30 @@ class Daemon(AuthJSONRPCServer):
|
||||||
'claim_id' : (str) claim ID of the resulting claim
|
'claim_id' : (str) claim ID of the resulting claim
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
|
parsed = parse_lbry_uri(channel_name)
|
||||||
|
if not parsed.is_channel:
|
||||||
|
raise Exception("Cannot make a new channel for a non channel name")
|
||||||
|
if parsed.path:
|
||||||
|
raise Exception("Invalid channel uri")
|
||||||
|
except (TypeError, URIParseError):
|
||||||
|
raise Exception("Invalid channel name")
|
||||||
|
if amount <= 0:
|
||||||
|
raise Exception("Invalid amount")
|
||||||
amount = int(amount * COIN)
|
amount = int(amount * COIN)
|
||||||
tx = yield self.wallet.claim_new_channel(channel_name, amount)
|
tx = yield self.wallet.claim_new_channel(channel_name, amount)
|
||||||
self.wallet.save()
|
self.wallet.save()
|
||||||
result = self._txo_to_response(tx, 0)
|
|
||||||
self.analytics_manager.send_new_channel()
|
self.analytics_manager.send_new_channel()
|
||||||
log.info("Claimed a new channel! Result: %s", result)
|
nout = 0
|
||||||
defer.returnValue(result)
|
txo = tx.outputs[nout]
|
||||||
|
log.info("Claimed a new channel! lbry://%s txid: %s nout: %d", channel_name, tx.id, nout)
|
||||||
|
defer.returnValue({
|
||||||
|
"success": True,
|
||||||
|
"tx": tx,
|
||||||
|
"claim_id": txo.claim_id,
|
||||||
|
"claim_address": self.ledger.hash160_to_address(txo.script.values['pubkey_hash']),
|
||||||
|
"output": txo
|
||||||
|
})
|
||||||
|
|
||||||
@requires(WALLET_COMPONENT)
|
@requires(WALLET_COMPONENT)
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@ -1764,6 +1744,11 @@ class Daemon(AuthJSONRPCServer):
|
||||||
|
|
||||||
bid = int(bid * COIN)
|
bid = int(bid * COIN)
|
||||||
|
|
||||||
|
for address in [claim_address, change_address]:
|
||||||
|
if address is not None:
|
||||||
|
# raises an error if the address is invalid
|
||||||
|
decode_address(address)
|
||||||
|
|
||||||
available = yield self.wallet.default_account.get_balance()
|
available = yield self.wallet.default_account.get_balance()
|
||||||
if bid >= available:
|
if bid >= available:
|
||||||
# TODO: add check for existing claim balance
|
# TODO: add check for existing claim balance
|
||||||
|
@ -1880,8 +1865,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
|
|
||||||
result = yield self._publish_stream(name, bid, claim_dict, file_path, certificate,
|
result = yield self._publish_stream(name, bid, claim_dict, file_path, certificate,
|
||||||
claim_address, change_address)
|
claim_address, change_address)
|
||||||
response = yield self._render_response(result)
|
defer.returnValue(result)
|
||||||
defer.returnValue(response)
|
|
||||||
|
|
||||||
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@ -2179,7 +2163,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
except URIParseError:
|
except URIParseError:
|
||||||
results[chan_uri] = {"error": "%s is not a valid uri" % chan_uri}
|
results[chan_uri] = {"error": "%s is not a valid uri" % chan_uri}
|
||||||
|
|
||||||
resolved = yield self._resolve(*valid_uris, page=page, page_size=page_size)
|
resolved = yield self.wallet.resolve(*valid_uris, page=page, page_size=page_size)
|
||||||
for u in resolved:
|
for u in resolved:
|
||||||
if 'error' in resolved[u]:
|
if 'error' in resolved[u]:
|
||||||
results[u] = resolved[u]
|
results[u] = resolved[u]
|
||||||
|
@ -2384,6 +2368,32 @@ class Daemon(AuthJSONRPCServer):
|
||||||
d.addCallback(lambda address: self._render_response(address))
|
d.addCallback(lambda address: self._render_response(address))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
||||||
|
@AuthJSONRPCServer.deprecated("wallet_send")
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def jsonrpc_send_amount_to_address(self, amount, address):
|
||||||
|
"""
|
||||||
|
Queue a payment of credits to an address
|
||||||
|
Usage:
|
||||||
|
send_amount_to_address (<amount> | --amount=<amount>) (<address> | --address=<address>)
|
||||||
|
Options:
|
||||||
|
--amount=<amount> : (float) amount to send
|
||||||
|
--address=<address> : (str) address to send credits to
|
||||||
|
Returns:
|
||||||
|
(bool) true if payment successfully scheduled
|
||||||
|
"""
|
||||||
|
if amount < 0:
|
||||||
|
raise NegativeFundsError()
|
||||||
|
elif not amount:
|
||||||
|
raise NullFundsError()
|
||||||
|
|
||||||
|
reserved_points = self.wallet.reserve_points(address, amount)
|
||||||
|
if reserved_points is None:
|
||||||
|
raise InsufficientFundsError()
|
||||||
|
yield self.wallet.send_points_to_address(reserved_points, amount)
|
||||||
|
self.analytics_manager.send_credits_sent()
|
||||||
|
defer.returnValue(True)
|
||||||
|
|
||||||
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def jsonrpc_wallet_send(self, amount, address=None, claim_id=None):
|
def jsonrpc_wallet_send(self, amount, address=None, claim_id=None):
|
||||||
|
@ -2749,7 +2759,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
if uri or stream_hash or sd_hash:
|
if uri or stream_hash or sd_hash:
|
||||||
if uri:
|
if uri:
|
||||||
metadata = (yield self._resolve(uri))[uri]
|
metadata = (yield self.wallet.resolve(uri))[uri]
|
||||||
sd_hash = utils.get_sd_hash(metadata)
|
sd_hash = utils.get_sd_hash(metadata)
|
||||||
stream_hash = yield self.storage.get_stream_hash_for_sd_hash(sd_hash)
|
stream_hash = yield self.storage.get_stream_hash_for_sd_hash(sd_hash)
|
||||||
elif stream_hash:
|
elif stream_hash:
|
||||||
|
@ -2898,7 +2908,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
hosts = {}
|
hosts = {}
|
||||||
|
|
||||||
for k, v in data_store.items():
|
for k, v in data_store.items():
|
||||||
for contact, _ in v:
|
for contact in map(itemgetter(0), v):
|
||||||
hosts.setdefault(contact, []).append(hexlify(k).decode())
|
hosts.setdefault(contact, []).append(hexlify(k).decode())
|
||||||
|
|
||||||
contact_set = set()
|
contact_set = set()
|
||||||
|
@ -2907,7 +2917,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
|
|
||||||
for i in range(len(self.dht_node._routingTable._buckets)):
|
for i in range(len(self.dht_node._routingTable._buckets)):
|
||||||
for contact in self.dht_node._routingTable._buckets[i]._contacts:
|
for contact in self.dht_node._routingTable._buckets[i]._contacts:
|
||||||
blobs = [hexlify(raw_hash).decode() for raw_hash in hosts.pop(contact)] if contact in hosts else []
|
blobs = list(hosts.pop(contact)) if contact in hosts else []
|
||||||
blob_hashes.update(blobs)
|
blob_hashes.update(blobs)
|
||||||
host = {
|
host = {
|
||||||
"address": contact.address,
|
"address": contact.address,
|
||||||
|
@ -2949,6 +2959,24 @@ class Daemon(AuthJSONRPCServer):
|
||||||
|
|
||||||
return self._blob_availability(blob_hash, search_timeout, blob_timeout)
|
return self._blob_availability(blob_hash, search_timeout, blob_timeout)
|
||||||
|
|
||||||
|
@requires(UPNP_COMPONENT, WALLET_COMPONENT, DHT_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
||||||
|
@AuthJSONRPCServer.deprecated("stream_availability")
|
||||||
|
def jsonrpc_get_availability(self, uri, sd_timeout=None, peer_timeout=None):
|
||||||
|
"""
|
||||||
|
Get stream availability for lbry uri
|
||||||
|
Usage:
|
||||||
|
get_availability (<uri> | --uri=<uri>) [<sd_timeout> | --sd_timeout=<sd_timeout>]
|
||||||
|
[<peer_timeout> | --peer_timeout=<peer_timeout>]
|
||||||
|
Options:
|
||||||
|
--uri=<uri> : (str) check availability for this uri
|
||||||
|
--sd_timeout=<sd_timeout> : (int) sd blob download timeout
|
||||||
|
--peer_timeout=<peer_timeout> : (int) how long to look for peers
|
||||||
|
Returns:
|
||||||
|
(float) Peers per blob / total blobs
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.jsonrpc_stream_availability(uri, peer_timeout, sd_timeout)
|
||||||
|
|
||||||
@requires(UPNP_COMPONENT, WALLET_COMPONENT, DHT_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
@requires(UPNP_COMPONENT, WALLET_COMPONENT, DHT_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def jsonrpc_stream_availability(self, uri, search_timeout=None, blob_timeout=None):
|
def jsonrpc_stream_availability(self, uri, search_timeout=None, blob_timeout=None):
|
||||||
|
@ -3002,7 +3030,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
resolved_result = (yield self._resolve(uri))[uri]
|
resolved_result = (yield self.wallet.resolve(uri))[uri]
|
||||||
response['did_resolve'] = True
|
response['did_resolve'] = True
|
||||||
except UnknownNameError:
|
except UnknownNameError:
|
||||||
response['error'] = "Failed to resolve name"
|
response['error'] = "Failed to resolve name"
|
||||||
|
@ -3229,10 +3257,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
everything=False, outputs=1, broadcast=False):
|
everything=False, outputs=1, broadcast=False):
|
||||||
"""
|
"""
|
||||||
Transfer some amount (or --everything) to an account from another
|
Transfer some amount (or --everything) to an account from another
|
||||||
account (can be the same account). Decimal amounts are interpreted
|
account (can be the same account). Amounts are interpreted as LBC.
|
||||||
as LBC and non-decimal amounts are interpreted as dewies. You can
|
You can also spread the transfer across a number of --outputs (cannot
|
||||||
also spread the transfer across a number of --outputs (cannot be
|
be used together with --everything).
|
||||||
used together with --everything).
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
fund (<to_account> | --to_account=<to_account>)
|
fund (<to_account> | --to_account=<to_account>)
|
||||||
|
@ -3244,7 +3271,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
Options:
|
Options:
|
||||||
--to_account=<to_account> : (str) send to this account
|
--to_account=<to_account> : (str) send to this account
|
||||||
--from_account=<from_account> : (str) spend from this account
|
--from_account=<from_account> : (str) spend from this account
|
||||||
--amount=<amount> : (str) the amount to transfer (lbc or dewies)
|
--amount=<amount> : (str) the amount to transfer lbc
|
||||||
--everything : (bool) transfer everything (excluding claims), default: false.
|
--everything : (bool) transfer everything (excluding claims), default: false.
|
||||||
--outputs=<outputs> : (int) split payment across many outputs, default: 1.
|
--outputs=<outputs> : (int) split payment across many outputs, default: 1.
|
||||||
--broadcast : (bool) actually broadcast the transaction, default: false.
|
--broadcast : (bool) actually broadcast the transaction, default: false.
|
||||||
|
@ -3263,25 +3290,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
return from_account.fund(
|
return from_account.fund(
|
||||||
to_account=to_account, amount=amount, everything=everything,
|
to_account=to_account, amount=amount, everything=everything,
|
||||||
outputs=outputs, broadcast=broadcast
|
outputs=outputs, broadcast=broadcast
|
||||||
).addCallback(lambda tx: self.tx_to_json(tx, from_account.ledger))
|
)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def tx_to_json(tx, ledger):
|
|
||||||
return {
|
|
||||||
'txid': tx.id,
|
|
||||||
'inputs': [
|
|
||||||
{'amount': txi.amount, 'address': txi.txo_ref.txo.get_address(ledger)}
|
|
||||||
for txi in tx.inputs
|
|
||||||
],
|
|
||||||
'outputs': [
|
|
||||||
{'amount': txo.amount, 'address': txo.get_address(ledger)}
|
|
||||||
for txo in tx.outputs
|
|
||||||
],
|
|
||||||
'total_input': tx.input_sum,
|
|
||||||
'total_output': tx.input_sum,
|
|
||||||
'total_fee': tx.fee,
|
|
||||||
'xhex': hexlify(tx.raw).decode(),
|
|
||||||
}
|
|
||||||
|
|
||||||
def get_account_or_error(self, argument: str, account_name: str, lbc_only=False):
|
def get_account_or_error(self, argument: str, account_name: str, lbc_only=False):
|
||||||
for account in self.wallet.default_wallet.accounts:
|
for account in self.wallet.default_wallet.accounts:
|
||||||
|
@ -3306,9 +3315,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
if '.' in amount:
|
if '.' in amount:
|
||||||
return int(Decimal(amount) * COIN)
|
return int(Decimal(amount) * COIN)
|
||||||
elif amount.isdigit():
|
elif amount.isdigit():
|
||||||
return int(amount)
|
amount = int(amount)
|
||||||
elif isinstance(amount, int):
|
if isinstance(amount, int):
|
||||||
return amount
|
return amount * COIN
|
||||||
raise ValueError("Invalid value for '{}' argument: {}".format(argument, amount))
|
raise ValueError("Invalid value for '{}' argument: {}".format(argument, amount))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,225 +0,0 @@
|
||||||
# pylint: skip-file
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import colorama
|
|
||||||
from docopt import docopt
|
|
||||||
from collections import OrderedDict
|
|
||||||
from lbrynet import conf
|
|
||||||
from lbrynet.core import utils
|
|
||||||
from lbrynet.daemon.auth.client import JSONRPCException, LBRYAPIClient, AuthAPIClient
|
|
||||||
from lbrynet.daemon.Daemon import Daemon
|
|
||||||
from lbrynet.core.system_info import get_platform
|
|
||||||
from jsonrpc.common import RPCError
|
|
||||||
from requests.exceptions import ConnectionError
|
|
||||||
from urllib2 import URLError, HTTPError
|
|
||||||
from httplib import UNAUTHORIZED
|
|
||||||
|
|
||||||
|
|
||||||
def remove_brackets(key):
|
|
||||||
if key.startswith("<") and key.endswith(">"):
|
|
||||||
return str(key[1:-1])
|
|
||||||
return key
|
|
||||||
|
|
||||||
|
|
||||||
def set_kwargs(parsed_args):
|
|
||||||
kwargs = OrderedDict()
|
|
||||||
for key, arg in parsed_args.iteritems():
|
|
||||||
if arg is None:
|
|
||||||
continue
|
|
||||||
elif key.startswith("--") and remove_brackets(key[2:]) not in kwargs:
|
|
||||||
k = remove_brackets(key[2:])
|
|
||||||
elif remove_brackets(key) not in kwargs:
|
|
||||||
k = remove_brackets(key)
|
|
||||||
kwargs[k] = guess_type(arg, k)
|
|
||||||
return kwargs
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
argv = sys.argv[1:]
|
|
||||||
|
|
||||||
# check if a config file has been specified. If so, shift
|
|
||||||
# all the arguments so that the parsing can continue without
|
|
||||||
# noticing
|
|
||||||
if len(argv) and argv[0] == "--conf":
|
|
||||||
if len(argv) < 2:
|
|
||||||
print_error("No config file specified for --conf option")
|
|
||||||
print_help()
|
|
||||||
return
|
|
||||||
|
|
||||||
conf.conf_file = argv[1]
|
|
||||||
argv = argv[2:]
|
|
||||||
|
|
||||||
if len(argv):
|
|
||||||
method, args = argv[0], argv[1:]
|
|
||||||
else:
|
|
||||||
print_help()
|
|
||||||
return
|
|
||||||
|
|
||||||
if method in ['help', '--help', '-h']:
|
|
||||||
if len(args) == 1:
|
|
||||||
print_help_for_command(args[0])
|
|
||||||
else:
|
|
||||||
print_help()
|
|
||||||
return
|
|
||||||
|
|
||||||
elif method in ['version', '--version']:
|
|
||||||
print(utils.json_dumps_pretty(get_platform(get_ip=False)))
|
|
||||||
return
|
|
||||||
|
|
||||||
if method not in Daemon.callable_methods:
|
|
||||||
if method not in Daemon.deprecated_methods:
|
|
||||||
print_error("\"%s\" is not a valid command." % method)
|
|
||||||
return
|
|
||||||
new_method = Daemon.deprecated_methods[method].new_command
|
|
||||||
print_error("\"%s\" is deprecated, using \"%s\"." % (method, new_method))
|
|
||||||
method = new_method
|
|
||||||
|
|
||||||
fn = Daemon.callable_methods[method]
|
|
||||||
|
|
||||||
parsed = docopt(fn.__doc__, args)
|
|
||||||
kwargs = set_kwargs(parsed)
|
|
||||||
colorama.init()
|
|
||||||
conf.initialize_settings()
|
|
||||||
|
|
||||||
try:
|
|
||||||
api = LBRYAPIClient.get_client()
|
|
||||||
api.status()
|
|
||||||
except (URLError, ConnectionError) as err:
|
|
||||||
if isinstance(err, HTTPError) and err.code == UNAUTHORIZED:
|
|
||||||
api = AuthAPIClient.config()
|
|
||||||
# this can happen if the daemon is using auth with the --http-auth flag
|
|
||||||
# when the config setting is to not use it
|
|
||||||
try:
|
|
||||||
api.status()
|
|
||||||
except:
|
|
||||||
print_error("Daemon requires authentication, but none was provided.",
|
|
||||||
suggest_help=False)
|
|
||||||
return 1
|
|
||||||
else:
|
|
||||||
print_error("Could not connect to daemon. Are you sure it's running?",
|
|
||||||
suggest_help=False)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# TODO: check if port is bound. Error if its not
|
|
||||||
|
|
||||||
try:
|
|
||||||
result = api.call(method, kwargs)
|
|
||||||
if isinstance(result, basestring):
|
|
||||||
# printing the undumped string is prettier
|
|
||||||
print(result)
|
|
||||||
else:
|
|
||||||
print(utils.json_dumps_pretty(result))
|
|
||||||
except (RPCError, KeyError, JSONRPCException, HTTPError) as err:
|
|
||||||
if isinstance(err, HTTPError):
|
|
||||||
error_body = err.read()
|
|
||||||
try:
|
|
||||||
error_data = json.loads(error_body)
|
|
||||||
except ValueError:
|
|
||||||
print(
|
|
||||||
"There was an error, and the response was not valid JSON.\n" +
|
|
||||||
"Raw JSONRPC response:\n" + error_body
|
|
||||||
)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
print_error(error_data['error']['message'] + "\n", suggest_help=False)
|
|
||||||
|
|
||||||
if 'data' in error_data['error'] and 'traceback' in error_data['error']['data']:
|
|
||||||
print("Here's the traceback for the error you encountered:")
|
|
||||||
print("\n".join(error_data['error']['data']['traceback']))
|
|
||||||
|
|
||||||
print_help_for_command(method)
|
|
||||||
elif isinstance(err, RPCError):
|
|
||||||
print_error(err.msg, suggest_help=False)
|
|
||||||
# print_help_for_command(method)
|
|
||||||
else:
|
|
||||||
print_error("Something went wrong\n", suggest_help=False)
|
|
||||||
print(str(err))
|
|
||||||
|
|
||||||
return 1
|
|
||||||
|
|
||||||
|
|
||||||
def guess_type(x, key=None):
|
|
||||||
if not isinstance(x, (unicode, str)):
|
|
||||||
return x
|
|
||||||
if key in ('uri', 'channel_name', 'name', 'file_name', 'download_directory'):
|
|
||||||
return x
|
|
||||||
if x in ('true', 'True', 'TRUE'):
|
|
||||||
return True
|
|
||||||
if x in ('false', 'False', 'FALSE'):
|
|
||||||
return False
|
|
||||||
if '.' in x:
|
|
||||||
try:
|
|
||||||
return float(x)
|
|
||||||
except ValueError:
|
|
||||||
# not a float
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
return int(x)
|
|
||||||
except ValueError:
|
|
||||||
return x
|
|
||||||
|
|
||||||
|
|
||||||
def print_help_suggestion():
|
|
||||||
print("See `{} help` for more information.".format(os.path.basename(sys.argv[0])))
|
|
||||||
|
|
||||||
|
|
||||||
def print_error(message, suggest_help=True):
|
|
||||||
error_style = colorama.Style.BRIGHT + colorama.Fore.RED
|
|
||||||
print(error_style + "ERROR: " + message + colorama.Style.RESET_ALL)
|
|
||||||
if suggest_help:
|
|
||||||
print_help_suggestion()
|
|
||||||
|
|
||||||
|
|
||||||
def print_help():
|
|
||||||
print("\n".join([
|
|
||||||
"NAME",
|
|
||||||
" lbrynet-cli - LBRY command line client.",
|
|
||||||
"",
|
|
||||||
"USAGE",
|
|
||||||
" lbrynet-cli [--conf <config file>] <command> [<args>]",
|
|
||||||
"",
|
|
||||||
"EXAMPLES",
|
|
||||||
" lbrynet-cli commands # list available commands",
|
|
||||||
" lbrynet-cli status # get daemon status",
|
|
||||||
" lbrynet-cli --conf ~/l1.conf status # like above but using ~/l1.conf as config file",
|
|
||||||
" lbrynet-cli resolve_name what # resolve a name",
|
|
||||||
" lbrynet-cli help resolve_name # get help for a command",
|
|
||||||
]))
|
|
||||||
|
|
||||||
|
|
||||||
def print_help_for_command(command):
|
|
||||||
fn = Daemon.callable_methods.get(command)
|
|
||||||
if fn:
|
|
||||||
print("Help for %s method:\n%s" % (command, fn.__doc__))
|
|
||||||
|
|
||||||
|
|
||||||
def wrap_list_to_term_width(l, width=None, separator=', ', prefix=''):
|
|
||||||
if width is None:
|
|
||||||
try:
|
|
||||||
_, width = os.popen('stty size', 'r').read().split()
|
|
||||||
width = int(width)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if not width:
|
|
||||||
width = 80
|
|
||||||
|
|
||||||
lines = []
|
|
||||||
curr_line = ''
|
|
||||||
for item in l:
|
|
||||||
new_line = curr_line + item + separator
|
|
||||||
if len(new_line) + len(prefix) > width:
|
|
||||||
lines.append(curr_line)
|
|
||||||
curr_line = item + separator
|
|
||||||
else:
|
|
||||||
curr_line = new_line
|
|
||||||
lines.append(curr_line)
|
|
||||||
|
|
||||||
ret = prefix + ("\n" + prefix).join(lines)
|
|
||||||
if ret.endswith(separator):
|
|
||||||
ret = ret[:-len(separator)]
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
|
@ -64,15 +64,6 @@ def start(argv=None, conf_path=None):
|
||||||
log_support.configure_loggly_handler()
|
log_support.configure_loggly_handler()
|
||||||
log.debug('Final Settings: %s', conf.settings.get_current_settings_dict())
|
log.debug('Final Settings: %s', conf.settings.get_current_settings_dict())
|
||||||
|
|
||||||
# fixme: fix that, JSONRPCProxy is gone on py3
|
|
||||||
#try:
|
|
||||||
# log.debug('Checking for an existing lbrynet daemon instance')
|
|
||||||
# JSONRPCProxy.from_url(conf.settings.get_api_connection_string()).status()
|
|
||||||
# log.info("lbrynet-daemon is already running")
|
|
||||||
# return
|
|
||||||
#except Exception:
|
|
||||||
# log.debug('No lbrynet instance found, continuing to start')
|
|
||||||
|
|
||||||
log.info("Starting lbrynet-daemon from command line")
|
log.info("Starting lbrynet-daemon from command line")
|
||||||
|
|
||||||
if test_internet_connection():
|
if test_internet_connection():
|
||||||
|
|
|
@ -22,6 +22,7 @@ from lbrynet.daemon.ComponentManager import ComponentManager
|
||||||
from .util import APIKey, get_auth_message, LBRY_SECRET
|
from .util import APIKey, get_auth_message, LBRY_SECRET
|
||||||
from .undecorated import undecorated
|
from .undecorated import undecorated
|
||||||
from .factory import AuthJSONRPCResource
|
from .factory import AuthJSONRPCResource
|
||||||
|
from lbrynet.daemon.json_response_encoder import JSONResponseEncoder
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
EMPTY_PARAMS = [{}]
|
EMPTY_PARAMS = [{}]
|
||||||
|
@ -85,11 +86,6 @@ class JSONRPCError:
|
||||||
return cls(message, code=code, traceback=traceback)
|
return cls(message, code=code, traceback=traceback)
|
||||||
|
|
||||||
|
|
||||||
def default_decimal(obj):
|
|
||||||
if isinstance(obj, Decimal):
|
|
||||||
return float(obj)
|
|
||||||
|
|
||||||
|
|
||||||
class UnknownAPIMethodError(Exception):
|
class UnknownAPIMethodError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -109,7 +105,7 @@ def jsonrpc_dumps_pretty(obj, **kwargs):
|
||||||
else:
|
else:
|
||||||
data = {"jsonrpc": "2.0", "result": obj, "id": id_}
|
data = {"jsonrpc": "2.0", "result": obj, "id": id_}
|
||||||
|
|
||||||
return json.dumps(data, cls=jsonrpclib.JSONRPCEncoder, sort_keys=True, indent=2, **kwargs) + "\n"
|
return json.dumps(data, cls=JSONResponseEncoder, sort_keys=True, indent=2, **kwargs) + "\n"
|
||||||
|
|
||||||
|
|
||||||
class JSONRPCServerType(type):
|
class JSONRPCServerType(type):
|
||||||
|
@ -314,7 +310,7 @@ class AuthJSONRPCServer(AuthorizedBase):
|
||||||
# last resort, just cast it as a string
|
# last resort, just cast it as a string
|
||||||
error = JSONRPCError(str(failure))
|
error = JSONRPCError(str(failure))
|
||||||
|
|
||||||
response_content = jsonrpc_dumps_pretty(error, id=id_)
|
response_content = jsonrpc_dumps_pretty(error, id=id_, ledger=self.ledger)
|
||||||
self._set_headers(request, response_content)
|
self._set_headers(request, response_content)
|
||||||
request.setResponseCode(200)
|
request.setResponseCode(200)
|
||||||
self._render_message(request, response_content)
|
self._render_message(request, response_content)
|
||||||
|
@ -575,7 +571,7 @@ class AuthJSONRPCServer(AuthorizedBase):
|
||||||
|
|
||||||
def _callback_render(self, result, request, id_, auth_required=False):
|
def _callback_render(self, result, request, id_, auth_required=False):
|
||||||
try:
|
try:
|
||||||
message = jsonrpc_dumps_pretty(result, id=id_, default=default_decimal)
|
message = jsonrpc_dumps_pretty(result, id=id_, ledger=self.ledger)
|
||||||
request.setResponseCode(200)
|
request.setResponseCode(200)
|
||||||
self._set_headers(request, message, auth_required)
|
self._set_headers(request, message, auth_required)
|
||||||
self._render_message(request, message)
|
self._render_message(request, message)
|
||||||
|
|
44
lbrynet/daemon/json_response_encoder.py
Normal file
44
lbrynet/daemon/json_response_encoder.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
from decimal import Decimal
|
||||||
|
from binascii import hexlify
|
||||||
|
from datetime import datetime
|
||||||
|
from json import JSONEncoder
|
||||||
|
from wallet.transaction import Transaction, Output
|
||||||
|
|
||||||
|
|
||||||
|
class JSONResponseEncoder(JSONEncoder):
|
||||||
|
|
||||||
|
def __init__(self, *args, ledger, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.ledger = ledger
|
||||||
|
|
||||||
|
def default(self, obj):
|
||||||
|
if isinstance(obj, Transaction):
|
||||||
|
return self.encode_transaction(obj)
|
||||||
|
if isinstance(obj, Output):
|
||||||
|
return self.encode_output(obj)
|
||||||
|
if isinstance(obj, datetime):
|
||||||
|
return obj.strftime("%Y%m%dT%H:%M:%S")
|
||||||
|
if isinstance(obj, Decimal):
|
||||||
|
return float(obj)
|
||||||
|
return super().default(obj)
|
||||||
|
|
||||||
|
def encode_transaction(self, tx):
|
||||||
|
return {
|
||||||
|
'txid': tx.id,
|
||||||
|
'inputs': [self.encode_input(txo) for txo in tx.inputs],
|
||||||
|
'outputs': [self.encode_output(txo) for txo in tx.outputs],
|
||||||
|
'total_input': tx.input_sum,
|
||||||
|
'total_output': tx.input_sum - tx.fee,
|
||||||
|
'total_fee': tx.fee,
|
||||||
|
'hex': hexlify(tx.raw).decode(),
|
||||||
|
}
|
||||||
|
|
||||||
|
def encode_output(self, txo):
|
||||||
|
return {
|
||||||
|
'nout': txo.position,
|
||||||
|
'amount': txo.amount,
|
||||||
|
'address': txo.get_address(self.ledger)
|
||||||
|
}
|
||||||
|
|
||||||
|
def encode_input(self, txi):
|
||||||
|
return self.encode_output(txi.txo_ref.txo)
|
|
@ -656,6 +656,19 @@ class SQLiteStorage:
|
||||||
if support_dl:
|
if support_dl:
|
||||||
yield defer.DeferredList(support_dl)
|
yield defer.DeferredList(support_dl)
|
||||||
|
|
||||||
|
def save_claims_for_resolve(self, claim_infos):
|
||||||
|
to_save = []
|
||||||
|
for info in claim_infos:
|
||||||
|
if 'value' in info:
|
||||||
|
if info['value']:
|
||||||
|
to_save.append(info)
|
||||||
|
else:
|
||||||
|
if 'certificate' in info and info['certificate']['value']:
|
||||||
|
to_save.append(info['certificate'])
|
||||||
|
if 'claim' in info and info['claim']['value']:
|
||||||
|
to_save.append(info['claim'])
|
||||||
|
return self.save_claims(to_save)
|
||||||
|
|
||||||
def get_old_stream_hashes_for_claim_id(self, claim_id, new_stream_hash):
|
def get_old_stream_hashes_for_claim_id(self, claim_id, new_stream_hash):
|
||||||
return self.run_and_return_list(
|
return self.run_and_return_list(
|
||||||
"select f.stream_hash from file f "
|
"select f.stream_hash from file f "
|
||||||
|
|
|
@ -147,11 +147,16 @@ class LbryWalletManager(BaseWalletManager):
|
||||||
def get_info_exchanger(self):
|
def get_info_exchanger(self):
|
||||||
return LBRYcrdAddressRequester(self)
|
return LBRYcrdAddressRequester(self)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
def resolve(self, *uris, **kwargs):
|
def resolve(self, *uris, **kwargs):
|
||||||
page = kwargs.get('page', 0)
|
page = kwargs.get('page', 0)
|
||||||
page_size = kwargs.get('page_size', 10)
|
page_size = kwargs.get('page_size', 10)
|
||||||
|
check_cache = kwargs.get('check_cache', False) # TODO: put caching back (was force_refresh parameter)
|
||||||
ledger = self.default_account.ledger # type: MainNetLedger
|
ledger = self.default_account.ledger # type: MainNetLedger
|
||||||
return ledger.resolve(page, page_size, *uris)
|
results = ledger.resolve(page, page_size, *uris)
|
||||||
|
yield self.old_db.save_claims_for_resolve(
|
||||||
|
(value for value in results.values() if 'error' not in value))
|
||||||
|
defer.returnValue(results)
|
||||||
|
|
||||||
def get_name_claims(self):
|
def get_name_claims(self):
|
||||||
return defer.succeed([])
|
return defer.succeed([])
|
||||||
|
@ -214,16 +219,6 @@ class LbryWalletManager(BaseWalletManager):
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def claim_new_channel(self, channel_name, amount):
|
def claim_new_channel(self, channel_name, amount):
|
||||||
try:
|
|
||||||
parsed = parse_lbry_uri(channel_name)
|
|
||||||
if not parsed.is_channel:
|
|
||||||
raise Exception("Cannot make a new channel for a non channel name")
|
|
||||||
if parsed.path:
|
|
||||||
raise Exception("Invalid channel uri")
|
|
||||||
except (TypeError, URIParseError):
|
|
||||||
raise Exception("Invalid channel name")
|
|
||||||
if amount <= 0:
|
|
||||||
raise Exception("Invalid amount")
|
|
||||||
account = self.default_account
|
account = self.default_account
|
||||||
address = yield account.receiving.get_or_create_usable_address()
|
address = yield account.receiving.get_or_create_usable_address()
|
||||||
cert, key = generate_certificate()
|
cert, key = generate_certificate()
|
||||||
|
|
Loading…
Reference in a new issue