forked from LBRYCommunity/lbry-sdk
most commands now work across all accounts
This commit is contained in:
parent
e2d618f472
commit
98d4d00f96
10 changed files with 426 additions and 223 deletions
|
@ -1703,12 +1703,14 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
|
||||
Returns: {Paginated[Output]}
|
||||
"""
|
||||
account = self.get_account_or_default(account_id)
|
||||
return maybe_paginate(
|
||||
account.get_claims,
|
||||
account.get_claim_count,
|
||||
page, page_size
|
||||
)
|
||||
if account_id:
|
||||
account = self.get_account_or_error(account_id)
|
||||
claims = account.get_claims
|
||||
claim_count = account.get_claim_count
|
||||
else:
|
||||
claims = self.ledger.get_claims
|
||||
claim_count = self.ledger.get_claim_count
|
||||
return maybe_paginate(claims, claim_count, page, page_size)
|
||||
|
||||
@requires(WALLET_COMPONENT)
|
||||
async def jsonrpc_claim_search(self, **kwargs):
|
||||
|
@ -1859,7 +1861,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
||||
async def jsonrpc_channel_create(
|
||||
self, name, bid, allow_duplicate_name=False, account_id=None, claim_address=None,
|
||||
preview=False, blocking=False, **kwargs):
|
||||
funding_account_ids=None, preview=False, blocking=False, **kwargs):
|
||||
"""
|
||||
Create a new channel by generating a channel private key and establishing an '@' prefixed claim.
|
||||
|
||||
|
@ -1871,6 +1873,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
[--tags=<tags>...] [--languages=<languages>...] [--locations=<locations>...]
|
||||
[--thumbnail_url=<thumbnail_url>] [--cover_url=<cover_url>]
|
||||
[--account_id=<account_id>] [--claim_address=<claim_address>]
|
||||
[--funding_account_ids=<funding_account_ids>...]
|
||||
[--preview] [--blocking]
|
||||
|
||||
Options:
|
||||
|
@ -1924,7 +1927,8 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
|
||||
--thumbnail_url=<thumbnail_url>: (str) thumbnail url
|
||||
--cover_url=<cover_url> : (str) url of cover image
|
||||
--account_id=<account_id> : (str) id of the account to store channel
|
||||
--account_id=<account_id> : (str) account to use for holding the transaction
|
||||
--funding_account_ids=<funding_account_ids>: (list) ids of accounts to fund this transaction
|
||||
--claim_address=<claim_address>: (str) address where the channel is sent to, if not specified
|
||||
it will be determined automatically from the account
|
||||
--preview : (bool) do not broadcast the transaction
|
||||
|
@ -1933,6 +1937,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
Returns: {Transaction}
|
||||
"""
|
||||
account = self.get_account_or_default(account_id)
|
||||
funding_accounts = self.get_accounts_or_all(funding_account_ids)
|
||||
self.valid_channel_name_or_error(name)
|
||||
amount = self.get_dewies_or_error('bid', bid, positive_value=True)
|
||||
claim_address = await self.get_receiving_address(claim_address, account)
|
||||
|
@ -1948,7 +1953,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
claim = Claim()
|
||||
claim.channel.update(**kwargs)
|
||||
tx = await Transaction.claim_create(
|
||||
name, claim, amount, claim_address, [account], account
|
||||
name, claim, amount, claim_address, funding_accounts, funding_accounts[0]
|
||||
)
|
||||
txo = tx.outputs[0]
|
||||
txo.generate_channel_private_key()
|
||||
|
@ -1970,7 +1975,8 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
||||
async def jsonrpc_channel_update(
|
||||
self, claim_id, bid=None, account_id=None, claim_address=None,
|
||||
new_signing_key=False, preview=False, blocking=False, replace=False, **kwargs):
|
||||
funding_account_ids=None, new_signing_key=False, preview=False,
|
||||
blocking=False, replace=False, **kwargs):
|
||||
"""
|
||||
Update an existing channel claim.
|
||||
|
||||
|
@ -1984,6 +1990,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
[--locations=<locations>...] [--clear_locations]
|
||||
[--thumbnail_url=<thumbnail_url>] [--cover_url=<cover_url>]
|
||||
[--account_id=<account_id>] [--claim_address=<claim_address>] [--new_signing_key]
|
||||
[--funding_account_ids=<funding_account_ids>...]
|
||||
[--preview] [--blocking] [--replace]
|
||||
|
||||
Options:
|
||||
|
@ -2039,7 +2046,8 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
--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) id of the account to store channel
|
||||
--account_id=<account_id> : (str) account to use for holding the transaction
|
||||
--funding_account_ids=<funding_account_ids>: (list) ids of accounts to fund this transaction
|
||||
--claim_address=<claim_address>: (str) address where the channel is sent
|
||||
--new_signing_key : (bool) generate a new signing key, will invalidate all previous publishes
|
||||
--preview : (bool) do not broadcast the transaction
|
||||
|
@ -2052,6 +2060,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
Returns: {Transaction}
|
||||
"""
|
||||
account = self.get_account_or_default(account_id)
|
||||
funding_accounts = self.get_accounts_or_all(funding_account_ids)
|
||||
|
||||
existing_channels = await account.get_claims(claim_id=claim_id)
|
||||
if len(existing_channels) != 1:
|
||||
|
@ -2081,7 +2090,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
claim = Claim.from_bytes(old_txo.claim.to_bytes())
|
||||
claim.channel.update(**kwargs)
|
||||
tx = await Transaction.claim_update(
|
||||
old_txo, claim, amount, claim_address, [account], account
|
||||
old_txo, claim, amount, claim_address, funding_accounts, funding_accounts[0]
|
||||
)
|
||||
new_txo = tx.outputs[0]
|
||||
|
||||
|
@ -2169,12 +2178,14 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
|
||||
Returns: {Paginated[Output]}
|
||||
"""
|
||||
account = self.get_account_or_default(account_id)
|
||||
return maybe_paginate(
|
||||
account.get_channels,
|
||||
account.get_channel_count,
|
||||
page, page_size
|
||||
)
|
||||
if account_id:
|
||||
account = self.get_account_or_error(account_id)
|
||||
channels = account.get_channels
|
||||
channel_count = account.get_channel_count
|
||||
else:
|
||||
channels = self.ledger.get_channels
|
||||
channel_count = self.ledger.get_channel_count
|
||||
return maybe_paginate(channels, channel_count, page, page_size)
|
||||
|
||||
@requires(WALLET_COMPONENT)
|
||||
async def jsonrpc_channel_export(self, channel_id=None, channel_name=None, account_id=None):
|
||||
|
@ -2261,6 +2272,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
[--channel_id=<channel_id> | --channel_name=<channel_name>]
|
||||
[--channel_account_id=<channel_account_id>...]
|
||||
[--account_id=<account_id>] [--claim_address=<claim_address>]
|
||||
[--funding_account_ids=<funding_account_ids>...]
|
||||
[--preview] [--blocking]
|
||||
|
||||
Options:
|
||||
|
@ -2328,7 +2340,8 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
--channel_name=<channel_name> : (str) name of publisher channel
|
||||
--channel_account_id=<channel_account_id>: (str) one or more account ids for accounts to look in
|
||||
for channel certificates, defaults to all accounts.
|
||||
--account_id=<account_id> : (str) account to use for funding the transaction
|
||||
--account_id=<account_id> : (str) account to use for holding the transaction
|
||||
--funding_account_ids=<funding_account_ids>: (list) ids of accounts to fund this transaction
|
||||
--claim_address=<claim_address>: (str) address where the claim is sent to, if not specified
|
||||
it will be determined automatically from the account
|
||||
--preview : (bool) do not broadcast the transaction
|
||||
|
@ -2359,8 +2372,8 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
async def jsonrpc_stream_create(
|
||||
self, name, bid, file_path, allow_duplicate_name=False,
|
||||
channel_id=None, channel_name=None, channel_account_id=None,
|
||||
account_id=None, claim_address=None, preview=False, blocking=False,
|
||||
**kwargs):
|
||||
account_id=None, claim_address=None, funding_account_ids=None,
|
||||
preview=False, blocking=False, **kwargs):
|
||||
"""
|
||||
Make a new stream claim and announce the associated file to lbrynet.
|
||||
|
||||
|
@ -2375,6 +2388,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
[--channel_id=<channel_id> | --channel_name=<channel_name>]
|
||||
[--channel_account_id=<channel_account_id>...]
|
||||
[--account_id=<account_id>] [--claim_address=<claim_address>]
|
||||
[--funding_account_ids=<funding_account_ids>...]
|
||||
[--preview] [--blocking]
|
||||
|
||||
Options:
|
||||
|
@ -2444,7 +2458,8 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
--channel_name=<channel_name> : (str) name of the publisher channel
|
||||
--channel_account_id=<channel_account_id>: (str) one or more account ids for accounts to look in
|
||||
for channel certificates, defaults to all accounts.
|
||||
--account_id=<account_id> : (str) account to use for funding the transaction
|
||||
--account_id=<account_id> : (str) account to use for holding the transaction
|
||||
--funding_account_ids=<funding_account_ids>: (list) ids of accounts to fund this transaction
|
||||
--claim_address=<claim_address>: (str) address where the claim is sent to, if not specified
|
||||
it will be determined automatically from the account
|
||||
--preview : (bool) do not broadcast the transaction
|
||||
|
@ -2454,6 +2469,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
"""
|
||||
self.valid_stream_name_or_error(name)
|
||||
account = self.get_account_or_default(account_id)
|
||||
funding_accounts = self.get_accounts_or_all(funding_account_ids)
|
||||
channel = await self.get_channel_or_none(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)
|
||||
|
@ -2470,7 +2486,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
claim = Claim()
|
||||
claim.stream.update(file_path=file_path, sd_hash='0'*96, **kwargs)
|
||||
tx = await Transaction.claim_create(
|
||||
name, claim, amount, claim_address, [account], account, channel
|
||||
name, claim, amount, claim_address, funding_accounts, funding_accounts[0], channel
|
||||
)
|
||||
new_txo = tx.outputs[0]
|
||||
|
||||
|
@ -2501,7 +2517,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
async def jsonrpc_stream_update(
|
||||
self, claim_id, bid=None, file_path=None,
|
||||
channel_id=None, channel_name=None, channel_account_id=None, clear_channel=False,
|
||||
account_id=None, claim_address=None,
|
||||
account_id=None, claim_address=None, funding_account_ids=None,
|
||||
preview=False, blocking=False, replace=False, **kwargs):
|
||||
"""
|
||||
Update an existing stream claim and if a new file is provided announce it to lbrynet.
|
||||
|
@ -2520,6 +2536,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
[--channel_id=<channel_id> | --channel_name=<channel_name> | --clear_channel]
|
||||
[--channel_account_id=<channel_account_id>...]
|
||||
[--account_id=<account_id>] [--claim_address=<claim_address>]
|
||||
[--funding_account_ids=<funding_account_ids>...]
|
||||
[--preview] [--blocking] [--replace]
|
||||
|
||||
Options:
|
||||
|
@ -2595,7 +2612,8 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
--clear_channel : (bool) remove channel signature
|
||||
--channel_account_id=<channel_account_id>: (str) one or more account ids for accounts to look in
|
||||
for channel certificates, defaults to all accounts.
|
||||
--account_id=<account_id> : (str) account to use for funding the transaction
|
||||
--account_id=<account_id> : (str) account to use for holding the transaction
|
||||
--funding_account_ids=<funding_account_ids>: (list) ids of accounts to fund this transaction
|
||||
--claim_address=<claim_address>: (str) address where the claim is sent to, if not specified
|
||||
it will be determined automatically from the account
|
||||
--preview : (bool) do not broadcast the transaction
|
||||
|
@ -2608,6 +2626,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
Returns: {Transaction}
|
||||
"""
|
||||
account = self.get_account_or_default(account_id)
|
||||
funding_accounts = self.get_accounts_or_all(funding_account_ids)
|
||||
|
||||
existing_claims = await account.get_claims(claim_id=claim_id)
|
||||
if len(existing_claims) != 1:
|
||||
|
@ -2655,7 +2674,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
claim = Claim.from_bytes(old_txo.claim.to_bytes())
|
||||
claim.stream.update(file_path=file_path, **kwargs)
|
||||
tx = await Transaction.claim_update(
|
||||
old_txo, claim, amount, claim_address, [account], account, channel
|
||||
old_txo, claim, amount, claim_address, funding_accounts, funding_accounts[0], channel
|
||||
)
|
||||
new_txo = tx.outputs[0]
|
||||
|
||||
|
@ -2753,12 +2772,14 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
|
||||
Returns: {Paginated[Output]}
|
||||
"""
|
||||
account = self.get_account_or_default(account_id)
|
||||
return maybe_paginate(
|
||||
account.get_streams,
|
||||
account.get_stream_count,
|
||||
page, page_size
|
||||
)
|
||||
if account_id:
|
||||
account = self.get_account_or_error(account_id)
|
||||
streams = account.get_streams
|
||||
stream_count = account.get_stream_count
|
||||
else:
|
||||
streams = self.ledger.get_streams
|
||||
stream_count = self.ledger.get_stream_count
|
||||
return maybe_paginate(streams, stream_count, page, page_size)
|
||||
|
||||
@requires(WALLET_COMPONENT, EXCHANGE_RATE_MANAGER_COMPONENT, BLOB_COMPONENT,
|
||||
DHT_COMPONENT, DATABASE_COMPONENT,
|
||||
|
@ -2785,7 +2806,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
|
||||
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
||||
async def jsonrpc_support_create(
|
||||
self, claim_id, amount, tip=False, account_id=None,
|
||||
self, claim_id, amount, tip=False, account_id=None, funding_account_ids=None,
|
||||
preview=False, blocking=False):
|
||||
"""
|
||||
Create a support or a tip for name claim.
|
||||
|
@ -2793,18 +2814,21 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
Usage:
|
||||
support_create (<claim_id> | --claim_id=<claim_id>) (<amount> | --amount=<amount>)
|
||||
[--tip] [--account_id=<account_id>] [--preview] [--blocking]
|
||||
[--funding_account_ids=<funding_account_ids>...]
|
||||
|
||||
Options:
|
||||
--claim_id=<claim_id> : (str) claim_id of the claim to support
|
||||
--amount=<amount> : (decimal) amount of support
|
||||
--tip : (bool) send support to claim owner, default: false.
|
||||
--account_id=<account_id> : (str) id of the account to use
|
||||
--account_id=<account_id> : (str) account to use for holding the transaction
|
||||
--funding_account_ids=<funding_account_ids>: (list) ids of accounts to fund this transaction
|
||||
--preview : (bool) do not broadcast the transaction
|
||||
--blocking : (bool) wait until transaction is in mempool
|
||||
|
||||
Returns: {Transaction}
|
||||
"""
|
||||
account = self.get_account_or_default(account_id)
|
||||
funding_accounts = self.get_accounts_or_all(funding_account_ids)
|
||||
amount = self.get_dewies_or_error("amount", amount)
|
||||
claim = await self.ledger.get_claim_by_claim_id(claim_id)
|
||||
claim_address = claim.get_address(self.ledger)
|
||||
|
@ -2812,7 +2836,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
claim_address = await account.receiving.get_or_create_usable_address()
|
||||
|
||||
tx = await Transaction.support(
|
||||
claim.claim_name, claim_id, amount, claim_address, [account], account
|
||||
claim.claim_name, claim_id, amount, claim_address, funding_accounts, funding_accounts[0]
|
||||
)
|
||||
|
||||
if not preview:
|
||||
|
@ -2847,12 +2871,14 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
|
||||
Returns: {Paginated[Output]}
|
||||
"""
|
||||
account = self.get_account_or_default(account_id)
|
||||
return maybe_paginate(
|
||||
account.get_supports,
|
||||
account.get_support_count,
|
||||
page, page_size
|
||||
)
|
||||
if account_id:
|
||||
account = self.get_account_or_error(account_id)
|
||||
supports = account.get_supports
|
||||
support_count = account.get_support_count
|
||||
else:
|
||||
supports = self.ledger.get_supports
|
||||
support_count = self.ledger.get_support_count
|
||||
return maybe_paginate(supports, support_count, page, page_size)
|
||||
|
||||
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
||||
async def jsonrpc_support_abandon(
|
||||
|
@ -2978,12 +3004,14 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
}
|
||||
|
||||
"""
|
||||
account = self.get_account_or_default(account_id)
|
||||
return maybe_paginate(
|
||||
self.wallet_manager.get_history,
|
||||
self.ledger.db.get_transaction_count,
|
||||
page, page_size, account=account
|
||||
)
|
||||
if account_id:
|
||||
account = self.get_account_or_error(account_id)
|
||||
transactions = account.get_transaction_history
|
||||
transaction_count = account.get_transaction_history_count
|
||||
else:
|
||||
transactions = self.ledger.get_transaction_history
|
||||
transaction_count = self.ledger.get_transaction_history_count
|
||||
return maybe_paginate(transactions, transaction_count, page, page_size)
|
||||
|
||||
@requires(WALLET_COMPONENT)
|
||||
def jsonrpc_transaction_show(self, txid):
|
||||
|
@ -3020,12 +3048,14 @@ class Daemon(metaclass=JSONRPCServerType):
|
|||
|
||||
Returns: {Paginated[Output]}
|
||||
"""
|
||||
account = self.get_account_or_default(account_id)
|
||||
return maybe_paginate(
|
||||
account.get_utxos,
|
||||
account.get_utxo_count,
|
||||
page, page_size
|
||||
)
|
||||
if account_id:
|
||||
account = self.get_account_or_error(account_id)
|
||||
utxos = account.get_utxos
|
||||
utxo_count = account.get_utxo_count
|
||||
else:
|
||||
utxos = self.ledger.get_utxos
|
||||
utxo_count = self.ledger.get_utxo_count
|
||||
return maybe_paginate(utxos, utxo_count, page, page_size)
|
||||
|
||||
@requires(WALLET_COMPONENT)
|
||||
def jsonrpc_utxo_release(self, account_id=None):
|
||||
|
|
|
@ -131,41 +131,35 @@ class Account(BaseAccount):
|
|||
details['certificates'] = len(self.channel_keys)
|
||||
return details
|
||||
|
||||
@staticmethod
|
||||
def constraint_spending_utxos(constraints):
|
||||
constraints.update({'is_claim': 0, 'is_update': 0, 'is_support': 0})
|
||||
def get_transaction_history(self, **constraints):
|
||||
return self.ledger.get_transaction_history(account=self, **constraints)
|
||||
|
||||
def get_utxos(self, **constraints):
|
||||
self.constraint_spending_utxos(constraints)
|
||||
return super().get_utxos(**constraints)
|
||||
|
||||
def get_utxo_count(self, **constraints):
|
||||
self.constraint_spending_utxos(constraints)
|
||||
return super().get_utxo_count(**constraints)
|
||||
def get_transaction_history_count(self, **constraints):
|
||||
return self.ledger.get_transaction_history_count(account=self, **constraints)
|
||||
|
||||
def get_claims(self, **constraints):
|
||||
return self.ledger.db.get_claims(account=self, **constraints)
|
||||
return self.ledger.get_claims(account=self, **constraints)
|
||||
|
||||
def get_claim_count(self, **constraints):
|
||||
return self.ledger.db.get_claim_count(account=self, **constraints)
|
||||
return self.ledger.get_claim_count(account=self, **constraints)
|
||||
|
||||
def get_streams(self, **constraints):
|
||||
return self.ledger.db.get_streams(account=self, **constraints)
|
||||
return self.ledger.get_streams(account=self, **constraints)
|
||||
|
||||
def get_stream_count(self, **constraints):
|
||||
return self.ledger.db.get_stream_count(account=self, **constraints)
|
||||
return self.ledger.get_stream_count(account=self, **constraints)
|
||||
|
||||
def get_channels(self, **constraints):
|
||||
return self.ledger.db.get_channels(account=self, **constraints)
|
||||
return self.ledger.get_channels(account=self, **constraints)
|
||||
|
||||
def get_channel_count(self, **constraints):
|
||||
return self.ledger.db.get_channel_count(account=self, **constraints)
|
||||
return self.ledger.get_channel_count(account=self, **constraints)
|
||||
|
||||
def get_supports(self, **constraints):
|
||||
return self.ledger.db.get_supports(account=self, **constraints)
|
||||
return self.ledger.get_supports(account=self, **constraints)
|
||||
|
||||
def get_support_count(self, **constraints):
|
||||
return self.ledger.db.get_support_count(account=self, **constraints)
|
||||
return self.ledger.get_support_count(account=self, **constraints)
|
||||
|
||||
def get_support_summary(self):
|
||||
return self.ledger.db.get_supports_summary(account_id=self.id)
|
||||
|
|
|
@ -53,7 +53,7 @@ class WalletDatabase(BaseDatabase):
|
|||
return row
|
||||
|
||||
async def get_txos(self, **constraints) -> List[Output]:
|
||||
my_account = constraints.get('my_account', constraints.get('account', None))
|
||||
my_accounts = constraints.get('my_accounts', constraints.get('accounts', []))
|
||||
|
||||
txos = await super().get_txos(**constraints)
|
||||
|
||||
|
@ -62,16 +62,20 @@ class WalletDatabase(BaseDatabase):
|
|||
if txo.is_claim and txo.can_decode_claim:
|
||||
if txo.claim.is_signed:
|
||||
channel_ids.add(txo.claim.signing_channel_id)
|
||||
if txo.claim.is_channel and my_account is not None:
|
||||
txo.private_key = my_account.get_channel_private_key(
|
||||
if txo.claim.is_channel and my_accounts:
|
||||
for account in my_accounts:
|
||||
private_key = account.get_channel_private_key(
|
||||
txo.claim.channel.public_key_bytes
|
||||
)
|
||||
if private_key:
|
||||
txo.private_key = private_key
|
||||
break
|
||||
|
||||
if channel_ids:
|
||||
channels = {
|
||||
txo.claim_id: txo for txo in
|
||||
(await self.get_claims(
|
||||
my_account=my_account,
|
||||
my_accounts=my_accounts,
|
||||
claim_id__in=channel_ids
|
||||
))
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import asyncio
|
||||
import logging
|
||||
from binascii import unhexlify
|
||||
from typing import Tuple, List, Dict
|
||||
from typing import Tuple, List
|
||||
from datetime import datetime
|
||||
|
||||
from torba.client.baseledger import BaseLedger
|
||||
from torba.client.baseaccount import SingleKey
|
||||
|
@ -74,10 +75,10 @@ class MainNetLedger(BaseLedger):
|
|||
result[url] = {'error': f'{url} did not resolve to a claim'}
|
||||
return result
|
||||
|
||||
async def claim_search(self, **kwargs) -> Tuple[List, int, int]:
|
||||
async def claim_search(self, **kwargs) -> Tuple[List[Output], int, int]:
|
||||
return await self._inflate_outputs(self.network.claim_search(**kwargs))
|
||||
|
||||
async def get_claim_by_claim_id(self, claim_id) -> Dict[str, Output]:
|
||||
async def get_claim_by_claim_id(self, claim_id) -> Output:
|
||||
for claim in (await self.claim_search(claim_id=claim_id))[0]:
|
||||
return claim
|
||||
|
||||
|
@ -109,6 +110,157 @@ class MainNetLedger(BaseLedger):
|
|||
'Failed to display wallet state, please file issue '
|
||||
'for this bug along with the traceback you see below:')
|
||||
|
||||
def constraint_account_or_all(self, constraints):
|
||||
account = constraints.pop('account', None)
|
||||
if account:
|
||||
constraints['accounts'] = [account]
|
||||
else:
|
||||
constraints['accounts'] = self.accounts
|
||||
|
||||
def constraint_spending_utxos(self, constraints):
|
||||
self.constraint_account_or_all(constraints)
|
||||
constraints.update({'is_claim': 0, 'is_update': 0, 'is_support': 0})
|
||||
|
||||
def get_utxos(self, **constraints):
|
||||
self.constraint_spending_utxos(constraints)
|
||||
return super().get_utxos(**constraints)
|
||||
|
||||
def get_utxo_count(self, **constraints):
|
||||
self.constraint_spending_utxos(constraints)
|
||||
return super().get_utxo_count(**constraints)
|
||||
|
||||
def get_claims(self, **constraints):
|
||||
self.constraint_account_or_all(constraints)
|
||||
return self.db.get_claims(**constraints)
|
||||
|
||||
def get_claim_count(self, **constraints):
|
||||
self.constraint_account_or_all(constraints)
|
||||
return self.db.get_claim_count(**constraints)
|
||||
|
||||
def get_streams(self, **constraints):
|
||||
self.constraint_account_or_all(constraints)
|
||||
return self.db.get_streams(**constraints)
|
||||
|
||||
def get_stream_count(self, **constraints):
|
||||
self.constraint_account_or_all(constraints)
|
||||
return self.db.get_stream_count(**constraints)
|
||||
|
||||
def get_channels(self, **constraints):
|
||||
self.constraint_account_or_all(constraints)
|
||||
return self.db.get_channels(**constraints)
|
||||
|
||||
def get_channel_count(self, **constraints):
|
||||
self.constraint_account_or_all(constraints)
|
||||
return self.db.get_channel_count(**constraints)
|
||||
|
||||
def get_supports(self, **constraints):
|
||||
self.constraint_account_or_all(constraints)
|
||||
return self.db.get_supports(**constraints)
|
||||
|
||||
def get_support_count(self, **constraints):
|
||||
self.constraint_account_or_all(constraints)
|
||||
return self.db.get_support_count(**constraints)
|
||||
|
||||
async def get_transaction_history(self, **constraints):
|
||||
self.constraint_account_or_all(constraints)
|
||||
txs = await self.db.get_transactions(**constraints)
|
||||
headers = self.headers
|
||||
history = []
|
||||
for tx in txs:
|
||||
ts = headers[tx.height]['timestamp'] if tx.height > 0 else None
|
||||
item = {
|
||||
'txid': tx.id,
|
||||
'timestamp': ts,
|
||||
'date': datetime.fromtimestamp(ts).isoformat(' ')[:-3] if tx.height > 0 else None,
|
||||
'confirmations': (headers.height+1) - tx.height if tx.height > 0 else 0,
|
||||
'claim_info': [],
|
||||
'update_info': [],
|
||||
'support_info': [],
|
||||
'abandon_info': []
|
||||
}
|
||||
is_my_inputs = all([txi.is_my_account for txi in tx.inputs])
|
||||
if is_my_inputs:
|
||||
# fees only matter if we are the ones paying them
|
||||
item['value'] = dewies_to_lbc(tx.net_account_balance+tx.fee)
|
||||
item['fee'] = dewies_to_lbc(-tx.fee)
|
||||
else:
|
||||
# someone else paid the fees
|
||||
item['value'] = dewies_to_lbc(tx.net_account_balance)
|
||||
item['fee'] = '0.0'
|
||||
for txo in tx.my_claim_outputs:
|
||||
item['claim_info'].append({
|
||||
'address': txo.get_address(self),
|
||||
'balance_delta': dewies_to_lbc(-txo.amount),
|
||||
'amount': dewies_to_lbc(txo.amount),
|
||||
'claim_id': txo.claim_id,
|
||||
'claim_name': txo.claim_name,
|
||||
'nout': txo.position
|
||||
})
|
||||
for txo in tx.my_update_outputs:
|
||||
if is_my_inputs: # updating my own claim
|
||||
previous = None
|
||||
for txi in tx.inputs:
|
||||
if txi.txo_ref.txo is not None:
|
||||
other_txo = txi.txo_ref.txo
|
||||
if (other_txo.is_claim or other_txo.script.is_support_claim) \
|
||||
and other_txo.claim_id == txo.claim_id:
|
||||
previous = other_txo
|
||||
break
|
||||
if previous is not None:
|
||||
item['update_info'].append({
|
||||
'address': txo.get_address(self),
|
||||
'balance_delta': dewies_to_lbc(previous.amount-txo.amount),
|
||||
'amount': dewies_to_lbc(txo.amount),
|
||||
'claim_id': txo.claim_id,
|
||||
'claim_name': txo.claim_name,
|
||||
'nout': txo.position
|
||||
})
|
||||
else: # someone sent us their claim
|
||||
item['update_info'].append({
|
||||
'address': txo.get_address(self),
|
||||
'balance_delta': dewies_to_lbc(0),
|
||||
'amount': dewies_to_lbc(txo.amount),
|
||||
'claim_id': txo.claim_id,
|
||||
'claim_name': txo.claim_name,
|
||||
'nout': txo.position
|
||||
})
|
||||
for txo in tx.my_support_outputs:
|
||||
item['support_info'].append({
|
||||
'address': txo.get_address(self),
|
||||
'balance_delta': dewies_to_lbc(txo.amount if not is_my_inputs else -txo.amount),
|
||||
'amount': dewies_to_lbc(txo.amount),
|
||||
'claim_id': txo.claim_id,
|
||||
'claim_name': txo.claim_name,
|
||||
'is_tip': not is_my_inputs,
|
||||
'nout': txo.position
|
||||
})
|
||||
if is_my_inputs:
|
||||
for txo in tx.other_support_outputs:
|
||||
item['support_info'].append({
|
||||
'address': txo.get_address(self),
|
||||
'balance_delta': dewies_to_lbc(-txo.amount),
|
||||
'amount': dewies_to_lbc(txo.amount),
|
||||
'claim_id': txo.claim_id,
|
||||
'claim_name': txo.claim_name,
|
||||
'is_tip': is_my_inputs,
|
||||
'nout': txo.position
|
||||
})
|
||||
for txo in tx.my_abandon_outputs:
|
||||
item['abandon_info'].append({
|
||||
'address': txo.get_address(self),
|
||||
'balance_delta': dewies_to_lbc(txo.amount),
|
||||
'amount': dewies_to_lbc(txo.amount),
|
||||
'claim_id': txo.claim_id,
|
||||
'claim_name': txo.claim_name,
|
||||
'nout': txo.position
|
||||
})
|
||||
history.append(item)
|
||||
return history
|
||||
|
||||
def get_transaction_history_count(self, **constraints):
|
||||
self.constraint_account_or_all(constraints)
|
||||
return self.db.get_transaction_count(**constraints)
|
||||
|
||||
|
||||
class TestNetLedger(MainNetLedger):
|
||||
network_name = 'testnet'
|
||||
|
|
|
@ -3,16 +3,13 @@ import json
|
|||
import logging
|
||||
from binascii import unhexlify
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from torba.client.basemanager import BaseWalletManager
|
||||
from torba.rpc.jsonrpc import CodeMessageError
|
||||
|
||||
from lbry.wallet.ledger import MainNetLedger
|
||||
from lbry.wallet.account import BaseAccount
|
||||
from lbry.wallet.transaction import Transaction
|
||||
from lbry.wallet.database import WalletDatabase
|
||||
from lbry.wallet.dewies import dewies_to_lbc
|
||||
from lbry.conf import Config
|
||||
|
||||
|
||||
|
@ -209,102 +206,6 @@ class LbryWalletManager(BaseWalletManager):
|
|||
await self.ledger.maybe_verify_transaction(tx, height)
|
||||
return tx
|
||||
|
||||
@staticmethod
|
||||
async def get_history(account: BaseAccount, **constraints):
|
||||
headers = account.ledger.headers
|
||||
txs = await account.get_transactions(**constraints)
|
||||
history = []
|
||||
for tx in txs:
|
||||
ts = headers[tx.height]['timestamp'] if tx.height > 0 else None
|
||||
item = {
|
||||
'txid': tx.id,
|
||||
'timestamp': ts,
|
||||
'date': datetime.fromtimestamp(ts).isoformat(' ')[:-3] if tx.height > 0 else None,
|
||||
'confirmations': (headers.height+1) - tx.height if tx.height > 0 else 0,
|
||||
'claim_info': [],
|
||||
'update_info': [],
|
||||
'support_info': [],
|
||||
'abandon_info': []
|
||||
}
|
||||
is_my_inputs = all([txi.is_my_account for txi in tx.inputs])
|
||||
if is_my_inputs:
|
||||
# fees only matter if we are the ones paying them
|
||||
item['value'] = dewies_to_lbc(tx.net_account_balance+tx.fee)
|
||||
item['fee'] = dewies_to_lbc(-tx.fee)
|
||||
else:
|
||||
# someone else paid the fees
|
||||
item['value'] = dewies_to_lbc(tx.net_account_balance)
|
||||
item['fee'] = '0.0'
|
||||
for txo in tx.my_claim_outputs:
|
||||
item['claim_info'].append({
|
||||
'address': txo.get_address(account.ledger),
|
||||
'balance_delta': dewies_to_lbc(-txo.amount),
|
||||
'amount': dewies_to_lbc(txo.amount),
|
||||
'claim_id': txo.claim_id,
|
||||
'claim_name': txo.claim_name,
|
||||
'nout': txo.position
|
||||
})
|
||||
for txo in tx.my_update_outputs:
|
||||
if is_my_inputs: # updating my own claim
|
||||
previous = None
|
||||
for txi in tx.inputs:
|
||||
if txi.txo_ref.txo is not None:
|
||||
other_txo = txi.txo_ref.txo
|
||||
if (other_txo.is_claim or other_txo.script.is_support_claim) \
|
||||
and other_txo.claim_id == txo.claim_id:
|
||||
previous = other_txo
|
||||
break
|
||||
if previous is not None:
|
||||
item['update_info'].append({
|
||||
'address': txo.get_address(account.ledger),
|
||||
'balance_delta': dewies_to_lbc(previous.amount-txo.amount),
|
||||
'amount': dewies_to_lbc(txo.amount),
|
||||
'claim_id': txo.claim_id,
|
||||
'claim_name': txo.claim_name,
|
||||
'nout': txo.position
|
||||
})
|
||||
else: # someone sent us their claim
|
||||
item['update_info'].append({
|
||||
'address': txo.get_address(account.ledger),
|
||||
'balance_delta': dewies_to_lbc(0),
|
||||
'amount': dewies_to_lbc(txo.amount),
|
||||
'claim_id': txo.claim_id,
|
||||
'claim_name': txo.claim_name,
|
||||
'nout': txo.position
|
||||
})
|
||||
for txo in tx.my_support_outputs:
|
||||
item['support_info'].append({
|
||||
'address': txo.get_address(account.ledger),
|
||||
'balance_delta': dewies_to_lbc(txo.amount if not is_my_inputs else -txo.amount),
|
||||
'amount': dewies_to_lbc(txo.amount),
|
||||
'claim_id': txo.claim_id,
|
||||
'claim_name': txo.claim_name,
|
||||
'is_tip': not is_my_inputs,
|
||||
'nout': txo.position
|
||||
})
|
||||
if is_my_inputs:
|
||||
for txo in tx.other_support_outputs:
|
||||
item['support_info'].append({
|
||||
'address': txo.get_address(account.ledger),
|
||||
'balance_delta': dewies_to_lbc(-txo.amount),
|
||||
'amount': dewies_to_lbc(txo.amount),
|
||||
'claim_id': txo.claim_id,
|
||||
'claim_name': txo.claim_name,
|
||||
'is_tip': is_my_inputs,
|
||||
'nout': txo.position
|
||||
})
|
||||
for txo in tx.my_abandon_outputs:
|
||||
item['abandon_info'].append({
|
||||
'address': txo.get_address(account.ledger),
|
||||
'balance_delta': dewies_to_lbc(txo.amount),
|
||||
'amount': dewies_to_lbc(txo.amount),
|
||||
'claim_id': txo.claim_id,
|
||||
'claim_name': txo.claim_name,
|
||||
'nout': txo.position
|
||||
})
|
||||
history.append(item)
|
||||
return history
|
||||
|
||||
def save(self):
|
||||
for wallet in self.wallets:
|
||||
wallet.save()
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
from lbry.testcase import CommandTestCase
|
||||
from lbry.wallet.dewies import dewies_to_lbc
|
||||
|
||||
|
||||
def extract(d, keys):
|
||||
return dict((k, d[k]) for k in keys)
|
||||
|
||||
|
||||
class AccountManagement(CommandTestCase):
|
||||
|
@ -65,3 +70,101 @@ class AccountManagement(CommandTestCase):
|
|||
self.account.channel_keys[keys[1]] = "some invalid junk"
|
||||
await self.account.maybe_migrate_certificates()
|
||||
self.assertEqual(list(self.account.channel_keys.keys()), [keys[2]])
|
||||
|
||||
async def assertFindsClaims(self, claim_names, awaitable):
|
||||
self.assertEqual(claim_names, [txo.claim_name for txo in await awaitable])
|
||||
|
||||
async def assertOutputAmount(self, amounts, awaitable):
|
||||
self.assertEqual(amounts, [dewies_to_lbc(txo.amount) for txo in await awaitable])
|
||||
|
||||
async def test_commands_across_accounts(self):
|
||||
channel_list = self.daemon.jsonrpc_channel_list
|
||||
stream_list = self.daemon.jsonrpc_stream_list
|
||||
support_list = self.daemon.jsonrpc_support_list
|
||||
utxo_list = self.daemon.jsonrpc_utxo_list
|
||||
default_account = self.daemon.default_account
|
||||
second_account = await self.daemon.jsonrpc_account_create('second account')
|
||||
|
||||
tx = await self.daemon.jsonrpc_account_send(
|
||||
'0.05', await self.daemon.jsonrpc_address_unused(account_id=second_account.id)
|
||||
)
|
||||
await self.confirm_tx(tx.id)
|
||||
await self.assertOutputAmount(['0.05', '9.949876'], utxo_list())
|
||||
await self.assertOutputAmount(['0.05'], utxo_list(account_id=second_account.id))
|
||||
await self.assertOutputAmount(['9.949876'], utxo_list(account_id=default_account.id))
|
||||
|
||||
channel1 = await self.channel_create('@channel-in-account1', '0.01')
|
||||
channel2 = await self.channel_create(
|
||||
'@channel-in-account2', '0.01', account_id=second_account.id, funding_account_ids=[default_account.id]
|
||||
)
|
||||
|
||||
await self.assertFindsClaims(['@channel-in-account2', '@channel-in-account1'], channel_list())
|
||||
await self.assertFindsClaims(['@channel-in-account1'], channel_list(account_id=default_account.id))
|
||||
await self.assertFindsClaims(['@channel-in-account2'], channel_list(account_id=second_account.id))
|
||||
|
||||
stream1 = await self.stream_create('stream-in-account1', '0.01', channel_id=self.get_claim_id(channel1))
|
||||
stream2 = await self.stream_create(
|
||||
'stream-in-account2', '0.01', channel_id=self.get_claim_id(channel2),
|
||||
account_id=second_account.id, funding_account_ids=[default_account.id]
|
||||
)
|
||||
await self.assertFindsClaims(['stream-in-account2', 'stream-in-account1'], stream_list())
|
||||
await self.assertFindsClaims(['stream-in-account1'], stream_list(account_id=default_account.id))
|
||||
await self.assertFindsClaims(['stream-in-account2'], stream_list(account_id=second_account.id))
|
||||
|
||||
await self.assertFindsClaims(
|
||||
['stream-in-account2', 'stream-in-account1', '@channel-in-account2', '@channel-in-account1'],
|
||||
self.daemon.jsonrpc_claim_list()
|
||||
)
|
||||
await self.assertFindsClaims(
|
||||
['stream-in-account1', '@channel-in-account1'],
|
||||
self.daemon.jsonrpc_claim_list(account_id=default_account.id)
|
||||
)
|
||||
await self.assertFindsClaims(
|
||||
['stream-in-account2', '@channel-in-account2'],
|
||||
self.daemon.jsonrpc_claim_list(account_id=second_account.id)
|
||||
)
|
||||
|
||||
support1 = await self.support_create(self.get_claim_id(stream1), '0.01')
|
||||
support2 = await self.support_create(
|
||||
self.get_claim_id(stream2), '0.01', account_id=second_account.id, funding_account_ids=[default_account.id]
|
||||
)
|
||||
self.assertEqual([support2['txid'], support1['txid']], [txo.tx_ref.id for txo in await support_list()])
|
||||
self.assertEqual([support1['txid']], [txo.tx_ref.id for txo in await support_list(account_id=default_account.id)])
|
||||
self.assertEqual([support2['txid']], [txo.tx_ref.id for txo in await support_list(account_id=second_account.id)])
|
||||
|
||||
history = await self.daemon.jsonrpc_transaction_list()
|
||||
self.assertEqual(len(history), 8)
|
||||
self.assertEqual(extract(history[0]['support_info'][0], ['claim_name', 'is_tip', 'amount', 'balance_delta']), {
|
||||
'claim_name': 'stream-in-account2',
|
||||
'is_tip': False,
|
||||
'amount': '0.01',
|
||||
'balance_delta': '-0.01'
|
||||
})
|
||||
self.assertEqual(extract(history[1]['support_info'][0], ['claim_name', 'is_tip', 'amount', 'balance_delta']), {
|
||||
'claim_name': 'stream-in-account1',
|
||||
'is_tip': False,
|
||||
'amount': '0.01',
|
||||
'balance_delta': '-0.01'
|
||||
})
|
||||
self.assertEqual(extract(history[2]['claim_info'][0], ['claim_name', 'amount', 'balance_delta']), {
|
||||
'claim_name': 'stream-in-account2',
|
||||
'amount': '0.01',
|
||||
'balance_delta': '-0.01'
|
||||
})
|
||||
self.assertEqual(extract(history[3]['claim_info'][0], ['claim_name', 'amount', 'balance_delta']), {
|
||||
'claim_name': 'stream-in-account1',
|
||||
'amount': '0.01',
|
||||
'balance_delta': '-0.01'
|
||||
})
|
||||
self.assertEqual(extract(history[4]['claim_info'][0], ['claim_name', 'amount', 'balance_delta']), {
|
||||
'claim_name': '@channel-in-account2',
|
||||
'amount': '0.01',
|
||||
'balance_delta': '-0.01'
|
||||
})
|
||||
self.assertEqual(extract(history[5]['claim_info'][0], ['claim_name', 'amount', 'balance_delta']), {
|
||||
'claim_name': '@channel-in-account1',
|
||||
'amount': '0.01',
|
||||
'balance_delta': '-0.01'
|
||||
})
|
||||
self.assertEqual(history[6]['value'], '0.0')
|
||||
self.assertEqual(history[7]['value'], '10.0')
|
||||
|
|
|
@ -478,7 +478,8 @@ class ChannelCommands(CommandTestCase):
|
|||
tx = await self.out(self.channel_update(claim_id, claim_address=other_address))
|
||||
|
||||
# after sending
|
||||
self.assertEqual(len(await self.daemon.jsonrpc_channel_list()), 2)
|
||||
self.assertEqual(len(await self.daemon.jsonrpc_channel_list()), 3)
|
||||
self.assertEqual(len(await self.daemon.jsonrpc_channel_list(account_id=self.account.id)), 2)
|
||||
self.assertEqual(len(await self.daemon.jsonrpc_channel_list(account_id=account2_id)), 1)
|
||||
|
||||
# shoud not have private key
|
||||
|
@ -618,12 +619,17 @@ class StreamCommands(ClaimTestCase):
|
|||
channels = await self.out(self.daemon.jsonrpc_channel_list(account1_id))
|
||||
self.assertEqual(len(channels), 1)
|
||||
self.assertEqual(channels[0]['name'], '@spam')
|
||||
self.assertEqual(channels, await self.out(self.daemon.jsonrpc_channel_list()))
|
||||
self.assertEqual(channels, await self.out(self.daemon.jsonrpc_channel_list(account1_id)))
|
||||
|
||||
channels = await self.out(self.daemon.jsonrpc_channel_list(account2_id))
|
||||
self.assertEqual(len(channels), 1)
|
||||
self.assertEqual(channels[0]['name'], '@baz')
|
||||
|
||||
channels = await self.out(self.daemon.jsonrpc_channel_list())
|
||||
self.assertEqual(len(channels), 2)
|
||||
self.assertEqual(channels[0]['name'], '@baz')
|
||||
self.assertEqual(channels[1]['name'], '@spam')
|
||||
|
||||
# defaults to using all accounts to lookup channel
|
||||
await self.stream_create('hovercraft1', '0.1', channel_id=baz_id)
|
||||
self.assertEqual((await self.claim_search(name='hovercraft1'))[0]['signing_channel']['name'], '@baz')
|
||||
|
@ -806,13 +812,15 @@ class StreamCommands(ClaimTestCase):
|
|||
|
||||
# before sending
|
||||
self.assertEqual(len(await self.daemon.jsonrpc_claim_list()), 4)
|
||||
self.assertEqual(len(await self.daemon.jsonrpc_claim_list(account_id=self.account.id)), 4)
|
||||
self.assertEqual(len(await self.daemon.jsonrpc_claim_list(account_id=account2_id)), 0)
|
||||
|
||||
other_address = await account2.receiving.get_or_create_usable_address()
|
||||
tx = await self.out(self.stream_update(claim_id, claim_address=other_address))
|
||||
|
||||
# after sending
|
||||
self.assertEqual(len(await self.daemon.jsonrpc_claim_list()), 3)
|
||||
self.assertEqual(len(await self.daemon.jsonrpc_claim_list()), 4)
|
||||
self.assertEqual(len(await self.daemon.jsonrpc_claim_list(account_id=self.account.id)), 3)
|
||||
self.assertEqual(len(await self.daemon.jsonrpc_claim_list(account_id=account2_id)), 1)
|
||||
|
||||
async def test_setting_fee_fields(self):
|
||||
|
@ -1112,8 +1120,7 @@ class SupportCommands(CommandTestCase):
|
|||
await self.assertBalance(account2, '5.0')
|
||||
|
||||
# create the claim we'll be tipping and supporting
|
||||
tx = await self.stream_create()
|
||||
claim_id = self.get_claim_id(tx)
|
||||
claim_id = self.get_claim_id(await self.stream_create())
|
||||
|
||||
# account1 and account2 balances:
|
||||
await self.assertBalance(self.account, '3.979769')
|
||||
|
@ -1121,18 +1128,17 @@ class SupportCommands(CommandTestCase):
|
|||
|
||||
# send a tip to the claim using account2
|
||||
tip = await self.out(
|
||||
self.daemon.jsonrpc_support_create(claim_id, '1.0', True, account2_id)
|
||||
self.daemon.jsonrpc_support_create(
|
||||
claim_id, '1.0', True, account2_id, funding_account_ids=[account2_id])
|
||||
)
|
||||
await self.on_transaction_dict(tip)
|
||||
await self.generate(1)
|
||||
await self.on_transaction_dict(tip)
|
||||
await self.confirm_tx(tip['txid'])
|
||||
|
||||
# tips don't affect balance so account1 balance is same but account2 balance went down
|
||||
await self.assertBalance(self.account, '3.979769')
|
||||
await self.assertBalance(account2, '3.9998585')
|
||||
|
||||
# verify that the incoming tip is marked correctly as is_tip=True in account1
|
||||
txs = await self.out(self.daemon.jsonrpc_transaction_list())
|
||||
txs = await self.out(self.daemon.jsonrpc_transaction_list(self.account.id))
|
||||
self.assertEqual(len(txs[0]['support_info']), 1)
|
||||
self.assertEqual(txs[0]['support_info'][0]['balance_delta'], '1.0')
|
||||
self.assertEqual(txs[0]['support_info'][0]['claim_id'], claim_id)
|
||||
|
@ -1153,11 +1159,10 @@ class SupportCommands(CommandTestCase):
|
|||
|
||||
# send a support to the claim using account2
|
||||
support = await self.out(
|
||||
self.daemon.jsonrpc_support_create(claim_id, '2.0', False, account2_id)
|
||||
self.daemon.jsonrpc_support_create(
|
||||
claim_id, '2.0', False, account2_id, funding_account_ids=[account2_id])
|
||||
)
|
||||
await self.on_transaction_dict(support)
|
||||
await self.generate(1)
|
||||
await self.on_transaction_dict(support)
|
||||
await self.confirm_tx(support['txid'])
|
||||
|
||||
# account2 balance went down ~2
|
||||
await self.assertBalance(self.account, '3.979769')
|
||||
|
|
|
@ -50,7 +50,7 @@ class AddressManager:
|
|||
|
||||
def _query_addresses(self, **constraints):
|
||||
return self.account.ledger.db.get_addresses(
|
||||
account=self.account,
|
||||
accounts=[self.account],
|
||||
chain=self.chain_number,
|
||||
**constraints
|
||||
)
|
||||
|
@ -406,7 +406,7 @@ class BaseAccount:
|
|||
if confirmations > 0:
|
||||
height = self.ledger.headers.height - (confirmations-1)
|
||||
constraints.update({'height__lte': height, 'height__gt': 0})
|
||||
return self.ledger.db.get_balance(account=self, **constraints)
|
||||
return self.ledger.db.get_balance(accounts=[self], **constraints)
|
||||
|
||||
async def get_max_gap(self):
|
||||
change_gap = await self.change.get_max_gap()
|
||||
|
@ -417,16 +417,16 @@ class BaseAccount:
|
|||
}
|
||||
|
||||
def get_utxos(self, **constraints):
|
||||
return self.ledger.db.get_utxos(account=self, **constraints)
|
||||
return self.ledger.get_utxos(account=self, **constraints)
|
||||
|
||||
def get_utxo_count(self, **constraints):
|
||||
return self.ledger.db.get_utxo_count(account=self, **constraints)
|
||||
return self.ledger.get_utxo_count(account=self, **constraints)
|
||||
|
||||
def get_transactions(self, **constraints):
|
||||
return self.ledger.db.get_transactions(account=self, **constraints)
|
||||
return self.ledger.get_transactions(account=self, **constraints)
|
||||
|
||||
def get_transaction_count(self, **constraints):
|
||||
return self.ledger.db.get_transaction_count(account=self, **constraints)
|
||||
return self.ledger.get_transaction_count(account=self, **constraints)
|
||||
|
||||
async def fund(self, to_account, amount=None, everything=False,
|
||||
outputs=1, broadcast=False, **constraints):
|
||||
|
|
|
@ -160,14 +160,10 @@ def query(select, **constraints):
|
|||
offset = constraints.pop('offset', None)
|
||||
order_by = constraints.pop('order_by', None)
|
||||
|
||||
constraints.pop('my_account', None)
|
||||
account = constraints.pop('account', None)
|
||||
if account is not None:
|
||||
if not isinstance(account, list):
|
||||
account = [account]
|
||||
constraints['account__in'] = [
|
||||
(a.public_key.address if isinstance(a, BaseAccount) else a) for a in account
|
||||
]
|
||||
constraints.pop('my_accounts', None)
|
||||
accounts = constraints.pop('accounts', None)
|
||||
if accounts is not None:
|
||||
constraints['account__in'] = [a.public_key.address for a in accounts]
|
||||
|
||||
where, values = constraints_to_sql(constraints)
|
||||
if where:
|
||||
|
@ -395,22 +391,26 @@ class BaseDatabase(SQLiteMixin):
|
|||
# 2. update address histories removing deleted TXs
|
||||
return True
|
||||
|
||||
async def select_transactions(self, cols, account=None, **constraints):
|
||||
if 'txid' not in constraints and account is not None:
|
||||
constraints['$account'] = account.public_key.address
|
||||
constraints['txid__in'] = """
|
||||
async def select_transactions(self, cols, accounts=None, **constraints):
|
||||
if 'txid' not in constraints:
|
||||
assert accounts is not None, "'accounts' argument required when no 'txid' constraint"
|
||||
constraints.update({
|
||||
f'$account{i}': a.public_key.address for i, a in enumerate(accounts)
|
||||
})
|
||||
account_values = ', '.join([f':$account{i}' for i in range(len(accounts))])
|
||||
constraints['txid__in'] = f"""
|
||||
SELECT txo.txid FROM txo
|
||||
JOIN pubkey_address USING (address) WHERE pubkey_address.account = :$account
|
||||
INNER JOIN pubkey_address USING (address) WHERE pubkey_address.account IN ({account_values})
|
||||
UNION
|
||||
SELECT txi.txid FROM txi
|
||||
JOIN pubkey_address USING (address) WHERE pubkey_address.account = :$account
|
||||
INNER JOIN pubkey_address USING (address) WHERE pubkey_address.account IN ({account_values})
|
||||
"""
|
||||
return await self.db.execute_fetchall(
|
||||
*query("SELECT {} FROM tx".format(cols), **constraints)
|
||||
)
|
||||
|
||||
async def get_transactions(self, my_account=None, **constraints):
|
||||
my_account = my_account or constraints.get('account', None)
|
||||
async def get_transactions(self, **constraints):
|
||||
accounts = constraints.get('accounts', None)
|
||||
|
||||
tx_rows = await self.select_transactions(
|
||||
'txid, raw, height, position, is_verified',
|
||||
|
@ -436,7 +436,7 @@ class BaseDatabase(SQLiteMixin):
|
|||
annotated_txos.update({
|
||||
txo.id: txo for txo in
|
||||
(await self.get_txos(
|
||||
my_account=my_account,
|
||||
my_accounts=accounts,
|
||||
txid__in=txids[offset:offset+step],
|
||||
))
|
||||
})
|
||||
|
@ -446,7 +446,7 @@ class BaseDatabase(SQLiteMixin):
|
|||
referenced_txos.update({
|
||||
txo.id: txo for txo in
|
||||
(await self.get_txos(
|
||||
my_account=my_account,
|
||||
my_accounts=accounts,
|
||||
txoid__in=txi_txoids[offset:offset+step],
|
||||
))
|
||||
})
|
||||
|
@ -484,12 +484,14 @@ class BaseDatabase(SQLiteMixin):
|
|||
" JOIN tx USING (txid)".format(cols), **constraints
|
||||
))
|
||||
|
||||
async def get_txos(self, my_account=None, no_tx=False, **constraints):
|
||||
my_account = my_account or constraints.get('account', None)
|
||||
if isinstance(my_account, BaseAccount):
|
||||
my_account = my_account.public_key.address
|
||||
async def get_txos(self, my_accounts=None, no_tx=False, **constraints):
|
||||
my_accounts = [
|
||||
(a.public_key.address if isinstance(a, BaseAccount) else a)
|
||||
for a in (my_accounts or constraints.get('accounts', []))
|
||||
]
|
||||
if 'order_by' not in constraints:
|
||||
constraints['order_by'] = ["tx.height=0 DESC", "tx.height DESC", "tx.position DESC"]
|
||||
constraints['order_by'] = [
|
||||
"tx.height=0 DESC", "tx.height DESC", "tx.position DESC", "txo.position"]
|
||||
rows = await self.select_txos(
|
||||
"tx.txid, raw, tx.height, tx.position, tx.is_verified, "
|
||||
"txo.position, chain, account, amount, script",
|
||||
|
@ -513,7 +515,7 @@ class BaseDatabase(SQLiteMixin):
|
|||
)
|
||||
txo = txs[row[0]].outputs[row[5]]
|
||||
txo.is_change = row[6] == 1
|
||||
txo.is_my_account = row[7] == my_account
|
||||
txo.is_my_account = row[7] in my_accounts
|
||||
txos.append(txo)
|
||||
return txos
|
||||
|
||||
|
|
|
@ -227,6 +227,18 @@ class BaseLedger(metaclass=LedgerRegistry):
|
|||
def release_tx(self, tx):
|
||||
return self.release_outputs([txi.txo_ref.txo for txi in tx.inputs])
|
||||
|
||||
def get_utxos(self, **constraints):
|
||||
return self.db.get_utxos(**constraints)
|
||||
|
||||
def get_utxo_count(self, **constraints):
|
||||
return self.db.get_utxo_count(**constraints)
|
||||
|
||||
def get_transactions(self, **constraints):
|
||||
return self.db.get_transactions(**constraints)
|
||||
|
||||
def get_transaction_count(self, **constraints):
|
||||
return self.db.get_transaction_count(**constraints)
|
||||
|
||||
async def get_local_status_and_history(self, address):
|
||||
address_details = await self.db.get_address(address=address)
|
||||
history = address_details['history'] or ''
|
||||
|
|
Loading…
Reference in a new issue