mirror of
https://github.com/LBRYFoundation/lbry-sdk.git
synced 2025-08-23 17:27:25 +00:00
is_received
This commit is contained in:
parent
3ff9e99416
commit
8ef2647fa9
5 changed files with 66 additions and 12 deletions
|
@ -3902,18 +3902,19 @@ class Daemon(metaclass=JSONRPCServerType):
|
||||||
return tx
|
return tx
|
||||||
|
|
||||||
@requires(WALLET_COMPONENT)
|
@requires(WALLET_COMPONENT)
|
||||||
def jsonrpc_support_list(self, *args, **kwargs):
|
def jsonrpc_support_list(self, *args, tips=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
List supports and tips in my control.
|
List supports and tips in my control.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
support_list [<account_id> | --account_id=<account_id>] [--wallet_id=<wallet_id>]
|
support_list [<account_id> | --account_id=<account_id>] [--wallet_id=<wallet_id>]
|
||||||
[--name=<name>...] [--claim_id=<claim_id>...]
|
[--name=<name>...] [--claim_id=<claim_id>...] [--tips]
|
||||||
[--page=<page>] [--page_size=<page_size>]
|
[--page=<page>] [--page_size=<page_size>]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--name=<name> : (str or list) claim name
|
--name=<name> : (str or list) claim name
|
||||||
--claim_id=<claim_id> : (str or list) claim id
|
--claim_id=<claim_id> : (str or list) claim id
|
||||||
|
--tips : (bool) only show tips (is_received=true)
|
||||||
--account_id=<account_id> : (str) id of the account to query
|
--account_id=<account_id> : (str) id of the account to query
|
||||||
--wallet_id=<wallet_id> : (str) restrict results to specific wallet
|
--wallet_id=<wallet_id> : (str) restrict results to specific wallet
|
||||||
--page=<page> : (int) page to return during paginating
|
--page=<page> : (int) page to return during paginating
|
||||||
|
@ -3923,6 +3924,9 @@ class Daemon(metaclass=JSONRPCServerType):
|
||||||
"""
|
"""
|
||||||
kwargs['type'] = 'support'
|
kwargs['type'] = 'support'
|
||||||
kwargs['unspent'] = True
|
kwargs['unspent'] = True
|
||||||
|
kwargs['include_is_received'] = True
|
||||||
|
if tips is True:
|
||||||
|
kwargs['is_received'] = True
|
||||||
return self.jsonrpc_txo_list(*args, **kwargs)
|
return self.jsonrpc_txo_list(*args, **kwargs)
|
||||||
|
|
||||||
@requires(WALLET_COMPONENT)
|
@requires(WALLET_COMPONENT)
|
||||||
|
@ -4098,6 +4102,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
||||||
def jsonrpc_txo_list(
|
def jsonrpc_txo_list(
|
||||||
self, account_id=None, type=None, txid=None, # pylint: disable=redefined-builtin
|
self, account_id=None, type=None, txid=None, # pylint: disable=redefined-builtin
|
||||||
claim_id=None, name=None, unspent=False,
|
claim_id=None, name=None, unspent=False,
|
||||||
|
include_is_received=False, is_received=None, is_not_received=None,
|
||||||
wallet_id=None, page=None, page_size=None, resolve=False):
|
wallet_id=None, page=None, page_size=None, resolve=False):
|
||||||
"""
|
"""
|
||||||
List my transaction outputs.
|
List my transaction outputs.
|
||||||
|
@ -4105,7 +4110,8 @@ class Daemon(metaclass=JSONRPCServerType):
|
||||||
Usage:
|
Usage:
|
||||||
txo_list [--account_id=<account_id>] [--type=<type>...] [--txid=<txid>...]
|
txo_list [--account_id=<account_id>] [--type=<type>...] [--txid=<txid>...]
|
||||||
[--claim_id=<claim_id>...] [--name=<name>...] [--unspent]
|
[--claim_id=<claim_id>...] [--name=<name>...] [--unspent]
|
||||||
[--wallet_id=<wallet_id>]
|
[--include_is_received] [--is_received] [--is_not_received]
|
||||||
|
[--wallet_id=<wallet_id>] [--include_is_received] [--is_received]
|
||||||
[--page=<page>] [--page_size=<page_size>]
|
[--page=<page>] [--page_size=<page_size>]
|
||||||
[--resolve]
|
[--resolve]
|
||||||
|
|
||||||
|
@ -4116,6 +4122,11 @@ class Daemon(metaclass=JSONRPCServerType):
|
||||||
--unspent : (bool) hide spent outputs, show only unspent ones
|
--unspent : (bool) hide spent outputs, show only unspent ones
|
||||||
--claim_id=<claim_id> : (str or list) claim id
|
--claim_id=<claim_id> : (str or list) claim id
|
||||||
--name=<name> : (str or list) claim name
|
--name=<name> : (str or list) claim name
|
||||||
|
--include_is_received : (bool) calculate the is_received property and
|
||||||
|
include in output, this happens automatically if you
|
||||||
|
use the --is_received or --is_not_received filters
|
||||||
|
--is_received : (bool) only return txos sent from others to this account
|
||||||
|
--is_not_received : (bool) only return txos created by this account
|
||||||
--account_id=<account_id> : (str) id of the account to query
|
--account_id=<account_id> : (str) id of the account to query
|
||||||
--wallet_id=<wallet_id> : (str) restrict results to specific wallet
|
--wallet_id=<wallet_id> : (str) restrict results to specific wallet
|
||||||
--page=<page> : (int) page to return during paginating
|
--page=<page> : (int) page to return during paginating
|
||||||
|
@ -4132,7 +4143,11 @@ class Daemon(metaclass=JSONRPCServerType):
|
||||||
else:
|
else:
|
||||||
claims = partial(self.ledger.get_txos, wallet=wallet, accounts=wallet.accounts)
|
claims = partial(self.ledger.get_txos, wallet=wallet, accounts=wallet.accounts)
|
||||||
claim_count = partial(self.ledger.get_txo_count, wallet=wallet, accounts=wallet.accounts)
|
claim_count = partial(self.ledger.get_txo_count, wallet=wallet, accounts=wallet.accounts)
|
||||||
constraints = {'resolve': resolve, 'unspent': unspent}
|
constraints = {'resolve': resolve, 'unspent': unspent, 'include_is_received': include_is_received}
|
||||||
|
if is_received is True:
|
||||||
|
constraints['is_received'] = True
|
||||||
|
elif is_not_received is True:
|
||||||
|
constraints['is_received'] = False
|
||||||
database.constrain_single_or_list(constraints, 'txo_type', type, lambda x: TXO_TYPES[x])
|
database.constrain_single_or_list(constraints, 'txo_type', type, lambda x: TXO_TYPES[x])
|
||||||
database.constrain_single_or_list(constraints, 'claim_id', claim_id)
|
database.constrain_single_or_list(constraints, 'claim_id', claim_id)
|
||||||
database.constrain_single_or_list(constraints, 'claim_name', name)
|
database.constrain_single_or_list(constraints, 'claim_name', name)
|
||||||
|
|
|
@ -25,7 +25,8 @@ def encode_txo_doc():
|
||||||
'address': "address of who can spend the txo",
|
'address': "address of who can spend the txo",
|
||||||
'confirmations': "number of confirmed blocks",
|
'confirmations': "number of confirmed blocks",
|
||||||
'is_change': "payment to change address, only available when it can be determined",
|
'is_change': "payment to change address, only available when it can be determined",
|
||||||
'is_spent': "true if txo is spent, false or None if it could not be determined",
|
'is_received': "true if txo was sent from external account to this account",
|
||||||
|
'is_spent': "true if txo is spent",
|
||||||
'is_mine': "payment to one of your accounts, only available when it can be determined",
|
'is_mine': "payment to one of your accounts, only available when it can be determined",
|
||||||
'type': "one of 'claim', 'support' or 'purchase'",
|
'type': "one of 'claim', 'support' or 'purchase'",
|
||||||
'name': "when type is 'claim' or 'support', this is the claim name",
|
'name': "when type is 'claim' or 'support', this is the claim name",
|
||||||
|
@ -169,6 +170,8 @@ class JSONResponseEncoder(JSONEncoder):
|
||||||
}
|
}
|
||||||
if txo.is_change is not None:
|
if txo.is_change is not None:
|
||||||
output['is_change'] = txo.is_change
|
output['is_change'] = txo.is_change
|
||||||
|
if txo.is_received is not None:
|
||||||
|
output['is_received'] = txo.is_received
|
||||||
if txo.is_spent is not None:
|
if txo.is_spent is not None:
|
||||||
output['is_spent'] = txo.is_spent
|
output['is_spent'] = txo.is_spent
|
||||||
if txo.is_my_account is not None:
|
if txo.is_my_account is not None:
|
||||||
|
|
|
@ -577,7 +577,19 @@ class Database(SQLiteMixin):
|
||||||
if txs:
|
if txs:
|
||||||
return txs[0]
|
return txs[0]
|
||||||
|
|
||||||
async def select_txos(self, cols, **constraints):
|
async def select_txos(self, cols, wallet=None, include_is_received=False, **constraints):
|
||||||
|
if include_is_received:
|
||||||
|
assert wallet is not None, 'cannot use is_recieved filter without wallet argument'
|
||||||
|
account_in_wallet, values = constraints_to_sql({
|
||||||
|
'$$account__in#is_received': [a.public_key.address for a in wallet.accounts]
|
||||||
|
})
|
||||||
|
cols += f""",
|
||||||
|
NOT EXISTS(
|
||||||
|
SELECT 1 FROM txi JOIN account_address USING (address)
|
||||||
|
WHERE txi.txid=txo.txid AND {account_in_wallet}
|
||||||
|
) as is_received
|
||||||
|
"""
|
||||||
|
constraints.update(values)
|
||||||
sql = f"SELECT {cols} FROM txo JOIN tx USING (txid)"
|
sql = f"SELECT {cols} FROM txo JOIN tx USING (txid)"
|
||||||
if 'accounts' in constraints:
|
if 'accounts' in constraints:
|
||||||
sql += " JOIN account_address USING (address)"
|
sql += " JOIN account_address USING (address)"
|
||||||
|
@ -588,7 +600,8 @@ class Database(SQLiteMixin):
|
||||||
constraints['is_reserved'] = False
|
constraints['is_reserved'] = False
|
||||||
constraints['txoid__not_in'] = "SELECT txoid FROM txi"
|
constraints['txoid__not_in'] = "SELECT txoid FROM txi"
|
||||||
|
|
||||||
async def get_txos(self, wallet=None, no_tx=False, unspent=False, **constraints):
|
async def get_txos(self, wallet=None, no_tx=False, unspent=False, include_is_received=False, **constraints):
|
||||||
|
include_is_received = include_is_received or 'is_received' in constraints
|
||||||
if unspent:
|
if unspent:
|
||||||
self.constrain_unspent(constraints)
|
self.constrain_unspent(constraints)
|
||||||
my_accounts = {a.public_key.address for a in wallet.accounts} if wallet else set()
|
my_accounts = {a.public_key.address for a in wallet.accounts} if wallet else set()
|
||||||
|
@ -601,9 +614,9 @@ class Database(SQLiteMixin):
|
||||||
tx.txid, raw, tx.height, tx.position, tx.is_verified, txo.position, amount, script, (
|
tx.txid, raw, tx.height, tx.position, tx.is_verified, txo.position, amount, script, (
|
||||||
select group_concat(account||"|"||chain) from account_address
|
select group_concat(account||"|"||chain) from account_address
|
||||||
where account_address.address=txo.address
|
where account_address.address=txo.address
|
||||||
), exists(select txoid from txi where txi.txoid=txo.txoid)
|
), exists(select 1 from txi where txi.txoid=txo.txoid)
|
||||||
""",
|
""",
|
||||||
**constraints
|
wallet=wallet, include_is_received=include_is_received, **constraints
|
||||||
)
|
)
|
||||||
txos = []
|
txos = []
|
||||||
txs = {}
|
txs = {}
|
||||||
|
@ -624,6 +637,8 @@ class Database(SQLiteMixin):
|
||||||
row_accounts = dict(a.split('|') for a in row[8].split(','))
|
row_accounts = dict(a.split('|') for a in row[8].split(','))
|
||||||
account_match = set(row_accounts) & my_accounts
|
account_match = set(row_accounts) & my_accounts
|
||||||
txo.is_spent = bool(row[9])
|
txo.is_spent = bool(row[9])
|
||||||
|
if include_is_received:
|
||||||
|
txo.is_received = bool(row[10])
|
||||||
if account_match:
|
if account_match:
|
||||||
txo.is_my_account = True
|
txo.is_my_account = True
|
||||||
txo.is_change = row_accounts[account_match.pop()] == '1'
|
txo.is_change = row_accounts[account_match.pop()] == '1'
|
||||||
|
@ -660,8 +675,8 @@ class Database(SQLiteMixin):
|
||||||
return txos
|
return txos
|
||||||
|
|
||||||
async def get_txo_count(self, unspent=False, **constraints):
|
async def get_txo_count(self, unspent=False, **constraints):
|
||||||
|
constraints['include_is_received'] = 'is_received' in constraints
|
||||||
constraints.pop('resolve', None)
|
constraints.pop('resolve', None)
|
||||||
constraints.pop('wallet', None)
|
|
||||||
constraints.pop('offset', None)
|
constraints.pop('offset', None)
|
||||||
constraints.pop('limit', None)
|
constraints.pop('limit', None)
|
||||||
constraints.pop('order_by', None)
|
constraints.pop('order_by', None)
|
||||||
|
|
|
@ -207,7 +207,7 @@ class OutputEffectiveAmountEstimator:
|
||||||
class Output(InputOutput):
|
class Output(InputOutput):
|
||||||
|
|
||||||
__slots__ = (
|
__slots__ = (
|
||||||
'amount', 'script', 'is_change', 'is_spent', 'is_my_account',
|
'amount', 'script', 'is_change', 'is_spent', 'is_received', 'is_my_account',
|
||||||
'channel', 'private_key', 'meta',
|
'channel', 'private_key', 'meta',
|
||||||
'purchase', 'purchased_claim', 'purchase_receipt',
|
'purchase', 'purchased_claim', 'purchase_receipt',
|
||||||
'reposted_claim', 'claims',
|
'reposted_claim', 'claims',
|
||||||
|
@ -216,7 +216,7 @@ class Output(InputOutput):
|
||||||
def __init__(self, amount: int, script: OutputScript,
|
def __init__(self, amount: int, script: OutputScript,
|
||||||
tx_ref: TXRef = None, position: int = None,
|
tx_ref: TXRef = None, position: int = None,
|
||||||
is_change: Optional[bool] = None, is_spent: Optional[bool] = None,
|
is_change: Optional[bool] = None, is_spent: Optional[bool] = None,
|
||||||
is_my_account: Optional[bool] = None,
|
is_received: Optional[bool] = None, is_my_account: Optional[bool] = None,
|
||||||
channel: Optional['Output'] = None, private_key: Optional[str] = None
|
channel: Optional['Output'] = None, private_key: Optional[str] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(tx_ref, position)
|
super().__init__(tx_ref, position)
|
||||||
|
@ -224,6 +224,7 @@ class Output(InputOutput):
|
||||||
self.script = script
|
self.script = script
|
||||||
self.is_change = is_change
|
self.is_change = is_change
|
||||||
self.is_spent = is_spent
|
self.is_spent = is_spent
|
||||||
|
self.is_received = is_received
|
||||||
self.is_my_account = is_my_account
|
self.is_my_account = is_my_account
|
||||||
self.channel = channel
|
self.channel = channel
|
||||||
self.private_key = private_key
|
self.private_key = private_key
|
||||||
|
|
|
@ -480,6 +480,26 @@ class TransactionOutputCommands(ClaimTestCase):
|
||||||
self.assertTrue(r[0]['is_spent'])
|
self.assertTrue(r[0]['is_spent'])
|
||||||
self.assertTrue(r[1]['is_spent'])
|
self.assertTrue(r[1]['is_spent'])
|
||||||
|
|
||||||
|
async def test_txo_list_received_filtering(self):
|
||||||
|
wallet2 = await self.daemon.jsonrpc_wallet_create('wallet2', create_account=True)
|
||||||
|
address2 = await self.daemon.jsonrpc_address_unused(wallet_id=wallet2.id)
|
||||||
|
await self.channel_create(claim_address=address2)
|
||||||
|
|
||||||
|
r = await self.txo_list(include_is_received=True)
|
||||||
|
self.assertEqual(2, len(r))
|
||||||
|
self.assertFalse(r[0]['is_received'])
|
||||||
|
self.assertTrue(r[1]['is_received'])
|
||||||
|
rt = await self.txo_list(is_not_received=True)
|
||||||
|
self.assertEqual(1, len(rt))
|
||||||
|
self.assertEqual(rt[0], r[0])
|
||||||
|
rf = await self.txo_list(is_received=True)
|
||||||
|
self.assertEqual(1, len(rf))
|
||||||
|
self.assertEqual(rf[0], r[1])
|
||||||
|
|
||||||
|
r = await self.txo_list(include_is_received=True, wallet_id=wallet2.id)
|
||||||
|
self.assertEqual(1, len(r))
|
||||||
|
self.assertTrue(r[0]['is_received'])
|
||||||
|
|
||||||
|
|
||||||
class ClaimCommands(ClaimTestCase):
|
class ClaimCommands(ClaimTestCase):
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue