forked from LBRYCommunity/lbry-sdk
tests
This commit is contained in:
parent
246f055145
commit
25a91f89fd
13 changed files with 482 additions and 34 deletions
|
@ -3271,6 +3271,337 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
"""
|
||||
return self.get_est_cost_from_uri(uri)
|
||||
|
||||
COLLECTION_DOC = """
|
||||
Create, list and abandon collections.
|
||||
"""
|
||||
|
||||
@requires(WALLET_COMPONENT)
|
||||
async def jsonrpc_collection_create(
|
||||
self, name, bid, claims, allow_duplicate_name=False,
|
||||
channel_id=None, channel_name=None, channel_account_id=None,
|
||||
account_id=None, wallet_id=None, claim_address=None, funding_account_ids=None,
|
||||
preview=False, blocking=False, **kwargs):
|
||||
"""
|
||||
Create a new collection ....
|
||||
|
||||
Usage:
|
||||
collection_create (<name> | --name=<name>) (<bid> | --bid=<bid>)
|
||||
(<claims>... | --claims=<claims>...)
|
||||
[--allow_duplicate_name]
|
||||
[--title=<title>] [--description=<description>]
|
||||
[--tags=<tags>...] [--languages=<languages>...] [--locations=<locations>...]
|
||||
[--thumbnail_url=<thumbnail_url>]
|
||||
[--account_id=<account_id>] [--wallet_id=<wallet_id>]
|
||||
[--claim_address=<claim_address>] [--funding_account_ids=<funding_account_ids>...]
|
||||
[--preview] [--blocking]
|
||||
|
||||
Options:
|
||||
--name=<name> : (str) name of the collection
|
||||
--bid=<bid> : (decimal) amount to back the claim
|
||||
--claims=<claims> : (list) claim ids to be included in the collection
|
||||
--allow_duplicate_name : (bool) create new collection even if one already exists with
|
||||
given name. default: false.
|
||||
--title=<title> : (str) title of the collection
|
||||
--description=<description> : (str) description of the collection
|
||||
--clear_languages : (bool) clear existing languages (prior to adding new ones)
|
||||
--tags=<tags> : (list) content tags
|
||||
--clear_languages : (bool) clear existing languages (prior to adding new ones)
|
||||
--languages=<languages> : (list) languages used by the collection,
|
||||
using RFC 5646 format, eg:
|
||||
for English `--languages=en`
|
||||
for Spanish (Spain) `--languages=es-ES`
|
||||
for Spanish (Mexican) `--languages=es-MX`
|
||||
for Chinese (Simplified) `--languages=zh-Hans`
|
||||
for Chinese (Traditional) `--languages=zh-Hant`
|
||||
--locations=<locations> : (list) locations of the collection, consisting of 2 letter
|
||||
`country` code and a `state`, `city` and a postal
|
||||
`code` along with a `latitude` and `longitude`.
|
||||
for JSON RPC: pass a dictionary with aforementioned
|
||||
attributes as keys, eg:
|
||||
...
|
||||
"locations": [{'country': 'US', 'state': 'NH'}]
|
||||
...
|
||||
for command line: pass a colon delimited list
|
||||
with values in the following order:
|
||||
|
||||
"COUNTRY:STATE:CITY:CODE:LATITUDE:LONGITUDE"
|
||||
|
||||
making sure to include colon for blank values, for
|
||||
example to provide only the city:
|
||||
|
||||
... --locations="::Manchester"
|
||||
|
||||
with all values set:
|
||||
|
||||
... --locations="US:NH:Manchester:03101:42.990605:-71.460989"
|
||||
|
||||
optionally, you can just pass the "LATITUDE:LONGITUDE":
|
||||
|
||||
... --locations="42.990605:-71.460989"
|
||||
|
||||
finally, you can also pass JSON string of dictionary
|
||||
on the command line as you would via JSON RPC
|
||||
|
||||
... --locations="{'country': 'US', 'state': 'NH'}"
|
||||
|
||||
--thumbnail_url=<thumbnail_url>: (str) thumbnail url
|
||||
--account_id=<account_id> : (str) account to use for holding the transaction
|
||||
--wallet_id=<wallet_id> : (str) restrict operation to specific wallet
|
||||
--funding_account_ids=<funding_account_ids>: (list) ids of accounts to fund this transaction
|
||||
--claim_address=<claim_address>: (str) address where the collection is sent to, if not specified
|
||||
it will be determined automatically from the account
|
||||
--preview : (bool) do not broadcast the transaction
|
||||
--blocking : (bool) wait until transaction is in mempool
|
||||
|
||||
Returns: {Transaction}
|
||||
"""
|
||||
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
|
||||
account = wallet.get_account_or_default(account_id)
|
||||
funding_accounts = wallet.get_accounts_or_all(funding_account_ids)
|
||||
self.valid_collection_name_or_error(name)
|
||||
channel = await self.get_channel_or_none(wallet, channel_account_id, channel_id, channel_name, for_signing=True)
|
||||
amount = self.get_dewies_or_error('bid', bid, positive_value=True)
|
||||
claim_address = await self.get_receiving_address(claim_address, account)
|
||||
|
||||
existing_collections = await self.ledger.get_collections(accounts=wallet.accounts, claim_name=name)
|
||||
if len(existing_collections) > 0:
|
||||
if not allow_duplicate_name:
|
||||
raise Exception(
|
||||
f"You already have a collection under the name '{name}'. "
|
||||
f"Use --allow-duplicate-name flag to override."
|
||||
)
|
||||
|
||||
claim = Claim()
|
||||
claim.collection.update(claims=claims, **kwargs) # maybe specify claims=[] # here
|
||||
tx = await Transaction.claim_create(
|
||||
name, claim, amount, claim_address, funding_accounts, funding_accounts[0], channel
|
||||
)
|
||||
new_txo = tx.outputs[0]
|
||||
|
||||
if channel:
|
||||
new_txo.sign(channel)
|
||||
await tx.sign(funding_accounts)
|
||||
if not preview:
|
||||
await self.broadcast_or_release(tx, blocking)
|
||||
await self.storage.save_claims([self._old_get_temp_claim_info(
|
||||
tx, new_txo, claim_address, claim, name, dewies_to_lbc(amount)
|
||||
)])
|
||||
# await self.analytics_manager.send_new_channel()
|
||||
else:
|
||||
await account.ledger.release_tx(tx)
|
||||
|
||||
return tx
|
||||
|
||||
@requires(WALLET_COMPONENT)
|
||||
async def jsonrpc_collection_update(
|
||||
self, claim_id, bid=None, claim=None, allow_duplicate_name=False,
|
||||
channel_id=None, channel_name=None, channel_account_id=None, clear_channel=False,
|
||||
account_id=None, wallet_id=None, claim_address=None, funding_account_ids=None,
|
||||
preview=False, blocking=False, replace=False, **kwargs):
|
||||
"""
|
||||
Update an existing collection claim.
|
||||
|
||||
Usage:
|
||||
collection_update (<claim_id> | --claim_id=<claim_id>) [--bid=<bid>]
|
||||
[--claims=<claims>...] [--clear_claim_ids]
|
||||
[--title=<title>] [--description=<description>]
|
||||
[--tags=<tags>...] [--clear_tags]
|
||||
[--languages=<languages>...] [--clear_languages]
|
||||
[--locations=<locations>...] [--clear_locations]
|
||||
[--thumbnail_url=<thumbnail_url>] [--cover_url=<cover_url>]
|
||||
[--account_id=<account_id>] [--wallet_id=<wallet_id>]
|
||||
[--claim_address=<claim_address>] [--new_signing_key]
|
||||
[--funding_account_ids=<funding_account_ids>...]
|
||||
[--preview] [--blocking] [--replace]
|
||||
|
||||
Options:
|
||||
--claim_id=<claim_id> : (str) claim_id of the collection to update
|
||||
--bid=<bid> : (decimal) amount to back the claim
|
||||
--claims=<claim_ids> : (list) claim ids
|
||||
--clear_claims : (bool) clear existing claim references (prior to adding new ones)
|
||||
--title=<title> : (str) title of the collection
|
||||
--description=<description> : (str) description of the collection
|
||||
--tags=<tags> : (list) add content tags
|
||||
--clear_tags : (bool) clear existing tags (prior to adding new ones)
|
||||
--languages=<languages> : (list) languages used by the collection,
|
||||
using RFC 5646 format, eg:
|
||||
for English `--languages=en`
|
||||
for Spanish (Spain) `--languages=es-ES`
|
||||
for Spanish (Mexican) `--languages=es-MX`
|
||||
for Chinese (Simplified) `--languages=zh-Hans`
|
||||
for Chinese (Traditional) `--languages=zh-Hant`
|
||||
--clear_languages : (bool) clear existing languages (prior to adding new ones)
|
||||
--locations=<locations> : (list) locations of the collection, consisting of 2 letter
|
||||
`country` code and a `state`, `city` and a postal
|
||||
`code` along with a `latitude` and `longitude`.
|
||||
for JSON RPC: pass a dictionary with aforementioned
|
||||
attributes as keys, eg:
|
||||
...
|
||||
"locations": [{'country': 'US', 'state': 'NH'}]
|
||||
...
|
||||
for command line: pass a colon delimited list
|
||||
with values in the following order:
|
||||
|
||||
"COUNTRY:STATE:CITY:CODE:LATITUDE:LONGITUDE"
|
||||
|
||||
making sure to include colon for blank values, for
|
||||
example to provide only the city:
|
||||
|
||||
... --locations="::Manchester"
|
||||
|
||||
with all values set:
|
||||
|
||||
... --locations="US:NH:Manchester:03101:42.990605:-71.460989"
|
||||
|
||||
optionally, you can just pass the "LATITUDE:LONGITUDE":
|
||||
|
||||
... --locations="42.990605:-71.460989"
|
||||
|
||||
finally, you can also pass JSON string of dictionary
|
||||
on the command line as you would via JSON RPC
|
||||
|
||||
... --locations="{'country': 'US', 'state': 'NH'}"
|
||||
|
||||
--clear_locations : (bool) clear existing locations (prior to adding new ones)
|
||||
--thumbnail_url=<thumbnail_url>: (str) thumbnail url
|
||||
#--cover_url=<cover_url> : (str) url of cover image
|
||||
--account_id=<account_id> : (str) account in which to look for collection (default: all)
|
||||
--wallet_id=<wallet_id> : (str) restrict operation to specific wallet
|
||||
--funding_account_ids=<funding_account_ids>: (list) ids of accounts to fund this transaction
|
||||
--claim_address=<claim_address>: (str) address where the collection is sent
|
||||
--new_signing_key : (bool) generate a new signing key, will invalidate all previous publishes
|
||||
--preview : (bool) do not broadcast the transaction
|
||||
--blocking : (bool) wait until transaction is in mempool
|
||||
--replace : (bool) instead of modifying specific values on
|
||||
the collection, this will clear all existing values
|
||||
and only save passed in values, useful for form
|
||||
submissions where all values are always set
|
||||
|
||||
Returns: {Transaction}
|
||||
"""
|
||||
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
|
||||
funding_accounts = wallet.get_accounts_or_all(funding_account_ids)
|
||||
if account_id:
|
||||
account = wallet.get_account_or_error(account_id)
|
||||
accounts = [account]
|
||||
else:
|
||||
account = wallet.default_account
|
||||
accounts = wallet.accounts
|
||||
|
||||
existing_collections = await self.ledger.get_collections(
|
||||
wallet=wallet, accounts=accounts, claim_id=claim_id
|
||||
)
|
||||
if len(existing_collections) != 1:
|
||||
account_ids = ', '.join(f"'{account.id}'" for account in accounts)
|
||||
raise Exception(
|
||||
f"Can't find the collection '{claim_id}' in account(s) {account_ids}."
|
||||
)
|
||||
# Here we might have a problem of replacing a stream with a collection
|
||||
old_txo = existing_collections[0]
|
||||
if not old_txo.claim.is_collection: # as we're only checking @ or not, this is not definitive
|
||||
raise Exception(
|
||||
f"A claim with id '{claim_id}' was found but it is not a stream or collection."
|
||||
)
|
||||
|
||||
if bid is not None:
|
||||
amount = self.get_dewies_or_error('bid', bid, positive_value=True)
|
||||
else:
|
||||
amount = old_txo.amount
|
||||
|
||||
if claim_address is not None:
|
||||
self.valid_address_or_error(claim_address)
|
||||
else:
|
||||
claim_address = old_txo.get_address(account.ledger)
|
||||
|
||||
channel = None
|
||||
if channel_id or channel_name:
|
||||
channel = await self.get_channel_or_error(
|
||||
wallet, channel_account_id, channel_id, channel_name, for_signing=True)
|
||||
elif old_txo.claim.is_signed and not clear_channel and not replace:
|
||||
channel = old_txo.channel
|
||||
|
||||
if replace:
|
||||
claim = Claim()
|
||||
claim.collection.message.source.CopyFrom(
|
||||
old_txo.claim.collection.message.source
|
||||
)
|
||||
|
||||
claim.collection.update(**kwargs)
|
||||
else:
|
||||
claim = Claim.from_bytes(old_txo.claim.to_bytes())
|
||||
claim.collection.update(**kwargs)
|
||||
tx = await Transaction.claim_update(
|
||||
old_txo, claim, amount, claim_address, funding_accounts, funding_accounts[0], channel
|
||||
)
|
||||
new_txo = tx.outputs[0]
|
||||
|
||||
new_txo.script.generate()
|
||||
|
||||
if channel:
|
||||
new_txo.sign(channel)
|
||||
await tx.sign(funding_accounts)
|
||||
|
||||
if not preview:
|
||||
await self.broadcast_or_release(tx, blocking)
|
||||
await self.analytics_manager.send_claim_action('publish')
|
||||
else:
|
||||
await account.ledger.release_tx(tx)
|
||||
|
||||
return tx
|
||||
|
||||
@requires(WALLET_COMPONENT)
|
||||
async def jsonrpc_collection_abandon(self, *args, **kwargs):
|
||||
"""
|
||||
Abandon one of my collection claims.
|
||||
|
||||
Usage:
|
||||
collection_abandon [<claim_id> | --claim_id=<claim_id>]
|
||||
[<txid> | --txid=<txid>] [<nout> | --nout=<nout>]
|
||||
[--account_id=<account_id>] [--wallet_id=<wallet_id>]
|
||||
[--preview] [--blocking]
|
||||
|
||||
Options:
|
||||
--claim_id=<claim_id> : (str) claim_id of the claim to abandon
|
||||
--txid=<txid> : (str) txid of the claim to abandon
|
||||
--nout=<nout> : (int) nout of the claim to abandon
|
||||
--account_id=<account_id> : (str) id of the account to use
|
||||
--wallet_id=<wallet_id> : (str) restrict operation to specific wallet
|
||||
--preview : (bool) do not broadcast the transaction
|
||||
--blocking : (bool) wait until abandon is in mempool
|
||||
|
||||
Returns: {Transaction}
|
||||
"""
|
||||
return await self.jsonrpc_stream_abandon(*args, **kwargs)
|
||||
|
||||
@requires(WALLET_COMPONENT)
|
||||
def jsonrpc_collection_list(self, resolve_claims=False, account_id=None, wallet_id=None, page=None, page_size=None):
|
||||
"""
|
||||
List my collection claims.
|
||||
|
||||
Usage:
|
||||
collection_list [--resolve_claims] [<account_id> | --account_id=<account_id>] [--wallet_id=<wallet_id>]
|
||||
[--page=<page>] [--page_size=<page_size>]
|
||||
|
||||
Options:
|
||||
--resolve_claims : (bool) resolve every claim
|
||||
--account_id=<account_id> : (str) id of the account to use
|
||||
--wallet_id=<wallet_id> : (str) restrict results to specific wallet
|
||||
--page=<page> : (int) page to return during paginating
|
||||
--page_size=<page_size> : (int) number of items on page during pagination
|
||||
|
||||
Returns: {Paginated[Output]}
|
||||
"""
|
||||
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
|
||||
if account_id:
|
||||
account: LBCAccount = wallet.get_account_or_error(account_id)
|
||||
collections = account.get_collections
|
||||
collection_count = account.get_collection_count
|
||||
else:
|
||||
collections = partial(self.ledger.get_collections, wallet=wallet, accounts=wallet.accounts)
|
||||
collection_count = partial(self.ledger.get_collection_count, wallet=wallet, accounts=wallet.accounts)
|
||||
return paginate_rows(collections, collection_count, page, page_size, resolve=resolve_claims)
|
||||
|
||||
|
||||
SUPPORT_DOC = """
|
||||
Create, list and abandon all types of supports.
|
||||
"""
|
||||
|
|
|
@ -9,6 +9,7 @@ async def jsonrpc_collection_create(
|
|||
|
||||
Usage:
|
||||
collection_create (<name> | --name=<name>) (<bid> | --bid=<bid>)
|
||||
( --claims=<claimIds> )
|
||||
[--allow_duplicate_name=<allow_duplicate_name>]
|
||||
[--title=<title>] [--description=<description>]
|
||||
[--tags=<tags>...] [--languages=<languages>...] [--locations=<locations>...]
|
||||
|
@ -20,12 +21,14 @@ async def jsonrpc_collection_create(
|
|||
Options:
|
||||
--name=<name> : (str) name of the collection
|
||||
--bid=<bid> : (decimal) amount to back the claim
|
||||
--allow_duplicate_name=<allow_duplicate_name> : (bool) create new collection even if one already exists with
|
||||
--allow_duplicate_name=<allow_duplicate_name> : (bool) create new collection even if one already exists with
|
||||
given name. default: false.
|
||||
--claims=<claims> : (list) claim ids
|
||||
--title=<title> : (str) title of the publication
|
||||
--description=<description> : (str) description of the publication
|
||||
--claims=<claimIds> : (list) claim ids
|
||||
--title=<title> : (str) title of the collection
|
||||
--description=<description> : (str) description of the collection
|
||||
--clear_languages : (bool) clear existing languages (prior to adding new ones)
|
||||
--tags=<tags> : (list) content tags
|
||||
--clear_languages : (bool) clear existing languages (prior to adding new ones)
|
||||
--languages=<languages> : (list) languages used by the collection,
|
||||
using RFC 5646 format, eg:
|
||||
for English `--languages=en`
|
||||
|
@ -65,7 +68,7 @@ async def jsonrpc_collection_create(
|
|||
... --locations="{'country': 'US', 'state': 'NH'}"
|
||||
|
||||
--thumbnail_url=<thumbnail_url>: (str) thumbnail url
|
||||
# --cover_url=<cover_url> : (str) url of cover image
|
||||
# --cover_url=<cover_url> : (str) url of cover image
|
||||
--account_id=<account_id> : (str) account to use for holding the transaction
|
||||
--wallet_id=<wallet_id> : (str) restrict operation to specific wallet
|
||||
--funding_account_ids=<funding_account_ids>: (list) ids of accounts to fund this transaction
|
||||
|
@ -94,7 +97,7 @@ async def jsonrpc_collection_create(
|
|||
)
|
||||
|
||||
claim = Claim()
|
||||
claim.collection.update(**kwargs) #maybe specify claims=[]
|
||||
claim.collection.update(**kwargs) #maybe specify claims=[] # here
|
||||
tx = await Transaction.claim_create(
|
||||
name, claim, amount, claim_address, funding_accounts, funding_accounts[0], channel
|
||||
)
|
||||
|
@ -138,8 +141,10 @@ async def jsonrpc_collection_update(
|
|||
Options:
|
||||
--claim_id=<claim_id> : (str) claim_id of the collection to update
|
||||
--bid=<bid> : (decimal) amount to back the claim
|
||||
--title=<title> : (str) title of the publication
|
||||
--description=<description> : (str) description of the publication
|
||||
--claims=<claim_ids> : (list) claim ids
|
||||
--clear_claims : (bool) clear existing claim references (prior to adding new ones)
|
||||
--title=<title> : (str) title of the collection
|
||||
--description=<description> : (str) description of the collection
|
||||
--tags=<tags> : (list) add content tags
|
||||
--clear_tags : (bool) clear existing tags (prior to adding new ones)
|
||||
--languages=<languages> : (list) languages used by the collection,
|
||||
|
|
|
@ -201,6 +201,8 @@ class JSONResponseEncoder(JSONEncoder):
|
|||
output['short_url'] = output['meta'].pop('short_url')
|
||||
if 'canonical_url' in output['meta']:
|
||||
output['canonical_url'] = output['meta'].pop('canonical_url')
|
||||
if txo.claims is not None:
|
||||
output['claims'] = [self.encode_output(o) for o in txo.claims]
|
||||
if txo.script.is_claim_name or txo.script.is_update_claim:
|
||||
try:
|
||||
output['value'] = txo.claim
|
||||
|
|
|
@ -347,10 +347,6 @@ class ClaimList(BaseMessageList[ClaimReference]):
|
|||
__slots__ = ()
|
||||
item_class = ClaimReference
|
||||
|
||||
@property
|
||||
def _message(self):
|
||||
return self.message.claim_references
|
||||
|
||||
def append(self, value):
|
||||
self.add().claim_id = value
|
||||
|
||||
|
|
|
@ -392,9 +392,10 @@ class Collection(BaseClaim):
|
|||
def to_dict(self):
|
||||
claim = super().to_dict()
|
||||
if 'claim_references' in claim:
|
||||
claim['claim_references'] = self.claims.ids
|
||||
claim['claims'] = self.claims.ids
|
||||
del claim['claim_references']
|
||||
return claim
|
||||
|
||||
@property
|
||||
def claims(self) -> ClaimList:
|
||||
return ClaimList(self.message)
|
||||
return ClaimList(self.message.claim_references)
|
||||
|
|
|
@ -267,10 +267,25 @@ class CommandTestCase(IntegrationTestCase):
|
|||
return await self.confirm_and_render(
|
||||
self.daemon.jsonrpc_channel_abandon(*args, **kwargs), confirm
|
||||
)
|
||||
# ClaimIDs = ....
|
||||
async def collection_create(
|
||||
self, name='firstcollection', bid='1.0', confirm=True, **kwargs):
|
||||
return await self.confirm_and_render(
|
||||
self.daemon.jsonrpc_collection_create(name, bid, **kwargs), confirm
|
||||
)
|
||||
# ClaimIDs = ....
|
||||
async def collection_update(
|
||||
self, claim_id, confirm=True, **kwargs):
|
||||
return await self.confirm_and_render(
|
||||
self.daemon.jsonrpc_collection_update(claim_id, **kwargs), confirm
|
||||
)
|
||||
|
||||
# async def collection_create
|
||||
# async def collection_update
|
||||
# async def collection_abandon
|
||||
async def collection_abandon(self, *args, confirm=True, **kwargs):
|
||||
if 'blocking' not in kwargs:
|
||||
kwargs['blocking'] = False
|
||||
return await self.confirm_and_render(
|
||||
self.daemon.jsonrpc_stream_abandon(*args, **kwargs), confirm
|
||||
)
|
||||
|
||||
async def support_create(self, claim_id, bid='1.0', confirm=True, **kwargs):
|
||||
return await self.confirm_and_render(
|
||||
|
|
|
@ -5,7 +5,7 @@ from hashlib import sha256
|
|||
from string import hexdigits
|
||||
|
||||
import ecdsa
|
||||
from lbry.wallet.constants import TXO_TYPES
|
||||
from lbry.wallet.constants import CLAIM_TYPES
|
||||
|
||||
from torba.client.baseaccount import BaseAccount, HierarchicalDeterministic
|
||||
|
||||
|
@ -91,7 +91,7 @@ class Account(BaseAccount):
|
|||
get_total_balance = partial(self.get_balance, confirmations=confirmations, include_claims=True)
|
||||
total = await get_total_balance()
|
||||
if reserved_subtotals:
|
||||
claims_balance = await get_total_balance(txo_type__in=[TXO_TYPES['stream'], TXO_TYPES['channel']])
|
||||
claims_balance = await get_total_balance(txo_type__in=CLAIM_TYPES)
|
||||
for amount, spent, from_me, to_me, height in await self.get_support_summary():
|
||||
if confirmations > 0 and not 0 < height <= self.ledger.headers.height - (confirmations - 1):
|
||||
continue
|
||||
|
@ -163,6 +163,12 @@ class Account(BaseAccount):
|
|||
def get_channel_count(self, **constraints):
|
||||
return self.ledger.get_channel_count(wallet=self.wallet, accounts=[self], **constraints)
|
||||
|
||||
def get_collections(self, **constraints):
|
||||
return self.ledger.get_collections(wallet=self.wallet, accounts=[self], **constraints)
|
||||
|
||||
def get_collection_count(self, **constraints):
|
||||
return self.ledger.get_collection_count(wallet=self.wallet, accounts=[self], **constraints)
|
||||
|
||||
def get_supports(self, **constraints):
|
||||
return self.ledger.get_supports(wallet=self.wallet, accounts=[self], **constraints)
|
||||
|
||||
|
|
|
@ -5,3 +5,9 @@ TXO_TYPES = {
|
|||
"purchase": 4,
|
||||
"collection": 5
|
||||
}
|
||||
|
||||
CLAIM_TYPES = [
|
||||
TXO_TYPES['stream'],
|
||||
TXO_TYPES['channel'],
|
||||
TXO_TYPES['collection'],
|
||||
]
|
||||
|
|
|
@ -3,7 +3,7 @@ from typing import List
|
|||
from torba.client.basedatabase import BaseDatabase
|
||||
|
||||
from lbry.wallet.transaction import Output
|
||||
from lbry.wallet.constants import TXO_TYPES
|
||||
from lbry.wallet.constants import TXO_TYPES, CLAIM_TYPES
|
||||
|
||||
|
||||
class WalletDatabase(BaseDatabase):
|
||||
|
@ -140,14 +140,7 @@ class WalletDatabase(BaseDatabase):
|
|||
|
||||
@staticmethod
|
||||
def constrain_claims(constraints):
|
||||
constraints['txo_type__in'] = [
|
||||
TXO_TYPES['stream'], TXO_TYPES['channel']
|
||||
]
|
||||
|
||||
def constrain_claims(constraints):
|
||||
constraints['txo_type__in'] = [
|
||||
TXO_TYPES['stream'], TXO_TYPES['channel']
|
||||
]
|
||||
constraints['txo_type__in'] = CLAIM_TYPES
|
||||
|
||||
async def get_claims(self, **constraints) -> List[Output]:
|
||||
self.constrain_claims(constraints)
|
||||
|
@ -198,11 +191,11 @@ class WalletDatabase(BaseDatabase):
|
|||
constraints['txo_type'] = TXO_TYPES['collection']
|
||||
|
||||
def get_collections(self, **constraints):
|
||||
self.constrain_supports(constraints)
|
||||
self.constrain_collections(constraints)
|
||||
return self.get_utxos(**constraints)
|
||||
|
||||
def get_collection_count(self, **constraints):
|
||||
self.constrain_supports(constraints)
|
||||
self.constrain_collections(constraints)
|
||||
return self.get_utxo_count(**constraints)
|
||||
|
||||
async def release_all_outputs(self, account):
|
||||
|
|
|
@ -186,10 +186,29 @@ class MainNetLedger(BaseLedger):
|
|||
def get_channel_count(self, **constraints):
|
||||
return self.db.get_channel_count(**constraints)
|
||||
|
||||
def get_collections(self, **constraints):
|
||||
return self.db.get_collections(**constraints)
|
||||
async def get_collections(self, resolve=False, **constraints):
|
||||
collections = await self.db.get_collections(**constraints)
|
||||
if resolve:
|
||||
for collection in collections:
|
||||
claim_ids = collection.claim.collection.claims.ids;
|
||||
try:
|
||||
resolve_results, _, _ = await self.claim_search([], claim_ids=collection.claim.collection.claims.ids)
|
||||
except:
|
||||
log.exception("Resolve failed while looking up collection claim ids:")
|
||||
claims = []
|
||||
for claim_id in claim_ids:
|
||||
found = False
|
||||
for txo in resolve_results:
|
||||
if txo.claim_id == claim_id:
|
||||
claims.append(txo)
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
claims.append(None)
|
||||
collection.claims = claims
|
||||
return collections
|
||||
|
||||
def get_collection_count(self, **constraints):
|
||||
def get_collection_count(self, resolve=False, **constraints):
|
||||
return self.db.get_collection_count(**constraints)
|
||||
|
||||
def get_supports(self, **constraints):
|
||||
|
|
|
@ -32,6 +32,7 @@ class Output(BaseOutput):
|
|||
__slots__ = (
|
||||
'channel', 'private_key', 'meta',
|
||||
'purchase', 'purchased_claim', 'purchase_receipt',
|
||||
'claims',
|
||||
)
|
||||
|
||||
def __init__(self, *args, channel: Optional['Output'] = None,
|
||||
|
@ -42,6 +43,7 @@ class Output(BaseOutput):
|
|||
self.purchase: 'Output' = None # txo containing purchase metadata
|
||||
self.purchased_claim: 'Output' = None # resolved claim pointed to by purchase
|
||||
self.purchase_receipt: 'Output' = None # txo representing purchase receipt for this claim
|
||||
self.claims: List['Output'] = None # resolved claims for collection
|
||||
self.meta = {}
|
||||
|
||||
def update_annotations(self, annotated):
|
||||
|
|
|
@ -1257,3 +1257,55 @@ class SupportCommands(CommandTestCase):
|
|||
self.assertFalse(txs2[0]['support_info'][0]['is_tip'])
|
||||
self.assertEqual(txs2[0]['value'], '0.0')
|
||||
self.assertEqual(txs2[0]['fee'], '-0.0001415')
|
||||
|
||||
|
||||
class CollectionCommands(CommandTestCase):
|
||||
|
||||
async def test_collections(self):
|
||||
claim_ids = [
|
||||
self.get_claim_id(tx) for tx in [
|
||||
await self.stream_create('stream-one'),
|
||||
await self.stream_create('stream-two')
|
||||
]
|
||||
]
|
||||
claim_ids.append(claim_ids[0])
|
||||
claim_ids.append('beef')
|
||||
tx = await self.collection_create('radjingles', claims=claim_ids, title="boring title")
|
||||
claim_id = self.get_claim_id(tx)
|
||||
collections = await self.out(self.daemon.jsonrpc_collection_list())
|
||||
self.assertEqual(collections['items'][0]['value']['title'], 'boring title')
|
||||
self.assertEqual(collections['items'][0]['value']['claims'], claim_ids)
|
||||
|
||||
self.assertItemCount(collections, 1)
|
||||
await self.assertBalance(self.account, '6.939679')
|
||||
|
||||
with self.assertRaisesRegex(Exception, "You already have a collection under the name 'radjingles'."):
|
||||
await self.collection_create('radjingles', claims=claim_ids)
|
||||
|
||||
self.assertItemCount(await self.daemon.jsonrpc_collection_list(), 1)
|
||||
await self.assertBalance(self.account, '6.939679')
|
||||
|
||||
collections = await self.out(self.daemon.jsonrpc_collection_list())
|
||||
self.assertEqual(collections['items'][0]['value']['title'], 'boring title')
|
||||
await self.collection_update(claim_id, title='fancy title')
|
||||
collections = await self.out(self.daemon.jsonrpc_collection_list())
|
||||
self.assertEqual(collections['items'][0]['value']['title'], 'fancy title')
|
||||
self.assertEqual(collections['items'][0]['value']['claims'], claim_ids)
|
||||
self.assertNotIn('claims', collections['items'][0])
|
||||
|
||||
await self.collection_create('radjingles', claims=claim_ids, allow_duplicate_name=True)
|
||||
self.assertItemCount(await self.daemon.jsonrpc_collection_list(), 2)
|
||||
|
||||
await self.collection_abandon(claim_id)
|
||||
self.assertItemCount(await self.daemon.jsonrpc_collection_list(), 1)
|
||||
|
||||
collections = await self.out(self.daemon.jsonrpc_collection_list(resolve_claims=True))
|
||||
self.assertEqual(collections['items'][0]['claims'][0]['name'], 'stream-one')
|
||||
self.assertEqual(collections['items'][0]['claims'][1]['name'], 'stream-two')
|
||||
self.assertEqual(collections['items'][0]['claims'][2]['name'], 'stream-one')
|
||||
self.assertIsNone(collections['items'][0]['claims'][3])
|
||||
|
||||
claims = await self.out(self.daemon.jsonrpc_claim_list())
|
||||
self.assertEqual(claims['items'][0]['name'], 'radjingles')
|
||||
self.assertEqual(claims['items'][1]['name'], 'stream-two')
|
||||
self.assertEqual(claims['items'][2]['name'], 'stream-one')
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from unittest import TestCase
|
||||
from decimal import Decimal
|
||||
|
||||
from lbry.schema.claim import Claim, Stream
|
||||
from lbry.schema.claim import Claim, Stream, Collection
|
||||
|
||||
|
||||
class TestClaimContainerAwareness(TestCase):
|
||||
|
@ -118,6 +118,26 @@ class TestTags(TestCase):
|
|||
self.assertEqual(claim.channel.tags, ['anime'])
|
||||
|
||||
|
||||
class TestCollection(TestCase):
|
||||
|
||||
def test_collection(self):
|
||||
collection = Collection()
|
||||
|
||||
collection.update(claims=['abc123', 'def123'])
|
||||
self.assertListEqual(collection.claims.ids, ['abc123', 'def123'])
|
||||
|
||||
collection.update(claims=['abc123', 'bbb123'])
|
||||
self.assertListEqual(collection.claims.ids, ['abc123', 'def123', 'abc123', 'bbb123'])
|
||||
|
||||
collection.update(clear_claims=True, claims=['bbb987', 'bb'])
|
||||
self.assertListEqual(collection.claims.ids, ['bbb987', 'bb'])
|
||||
|
||||
self.assertEqual(collection.to_dict(), {'claims': ['bbb987', 'bb']})
|
||||
|
||||
collection.update(clear_claims=True)
|
||||
self.assertListEqual(collection.claims.ids, [])
|
||||
|
||||
|
||||
class TestLocations(TestCase):
|
||||
|
||||
def test_location_successful_parsing(self):
|
||||
|
|
Loading…
Reference in a new issue