added wallet balance command

This commit is contained in:
Lex Berezhny 2019-10-13 19:32:10 -04:00
parent fea7275148
commit e2b92c99ef
5 changed files with 105 additions and 19 deletions

View file

@ -38,7 +38,7 @@ from lbry.extras.daemon import comment_client
from lbry.extras.daemon.undecorated import undecorated
from lbry.wallet.transaction import Transaction, Output, Input
from lbry.wallet.account import Account as LBCAccount
from lbry.wallet.dewies import dewies_to_lbc, lbc_to_dewies
from lbry.wallet.dewies import dewies_to_lbc, lbc_to_dewies, dict_values_to_lbc
from lbry.schema.claim import Claim
from lbry.schema.url import URL
@ -1141,6 +1141,31 @@ class Daemon(metaclass=JSONRPCServerType):
self.wallet_manager.wallets.remove(wallet)
return wallet
@requires("wallet")
async def jsonrpc_wallet_balance(self, wallet_id=None, confirmations=0, reserved_subtotals=False):
"""
Return the balance of a wallet
Usage:
wallet_balance [--wallet_id=<wallet_id>] [--confirmations=<confirmations>] [--reserved_subtotals]
Options:
--wallet_id=<wallet_id> : (str) balance for specific wallet
--confirmations=<confirmations> : (int) Only include transactions with this many
confirmed blocks.
--reserved_subtotals : (bool) Include detailed reserved balances on
claims, tips and supports.
Returns:
(decimal) amount of lbry credits in wallet
"""
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
balance = await self.ledger.get_detailed_balance(
accounts=wallet.accounts, confirmations=confirmations,
reserved_subtotals=reserved_subtotals
)
return dict_values_to_lbc(balance)
ACCOUNT_DOC = """
Create, modify and inspect wallet accounts.
"""
@ -1200,7 +1225,10 @@ class Daemon(metaclass=JSONRPCServerType):
"""
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
account = wallet.get_account_or_default(account_id)
return await account.get_granular_balances(confirmations=confirmations, reserved_subtotals=reserved_subtotals)
balance = await account.get_detailed_balance(
confirmations=confirmations, reserved_subtotals=reserved_subtotals
)
return dict_values_to_lbc(balance)
@requires("wallet")
async def jsonrpc_account_add(

View file

@ -5,7 +5,6 @@ from hashlib import sha256
from string import hexdigits
import ecdsa
from lbry.wallet.dewies import dewies_to_lbc
from lbry.wallet.constants import TXO_TYPES
from torba.client.baseaccount import BaseAccount, HierarchicalDeterministic
@ -78,7 +77,7 @@ class Account(BaseAccount):
constraints.update({'txo_type': 0})
return super().get_balance(confirmations, **constraints)
async def get_granular_balances(self, confirmations=0, reserved_subtotals=False):
async def get_detailed_balance(self, confirmations=0, reserved_subtotals=False):
tips_balance, supports_balance, claims_balance = 0, 0, 0
get_total_balance = partial(self.get_balance, confirmations=confirmations, include_claims=True)
total = await get_total_balance()
@ -98,13 +97,13 @@ class Account(BaseAccount):
confirmations=confirmations, include_claims=True, txo_type__gt=0
)
return {
'total': dewies_to_lbc(total),
'available': dewies_to_lbc(total - reserved),
'reserved': dewies_to_lbc(reserved),
'total': total,
'available': total - reserved,
'reserved': reserved,
'reserved_subtotals': {
'claims': dewies_to_lbc(claims_balance),
'supports': dewies_to_lbc(supports_balance),
'tips': dewies_to_lbc(tips_balance)
'claims': claims_balance,
'supports': supports_balance,
'tips': tips_balance
} if reserved_subtotals else None
}

View file

@ -31,3 +31,12 @@ def lbc_to_dewies(lbc: str) -> int:
def dewies_to_lbc(dewies) -> str:
return satoshis_to_coins(dewies)
def dict_values_to_lbc(d):
for key, value in d.items():
if isinstance(value, int):
d[key] = dewies_to_lbc(value)
elif isinstance(value, dict):
dict_values_to_lbc(value)
return d

View file

@ -244,6 +244,23 @@ class MainNetLedger(BaseLedger):
def get_transaction_history_count(self, **constraints):
return self.db.get_transaction_count(**constraints)
@staticmethod
async def get_detailed_balance(accounts, confirmations=0, reserved_subtotals=False):
result = {}
for account in accounts:
balance = await account.get_detailed_balance(confirmations, reserved_subtotals)
if result:
for key, value in balance.items():
if key == 'reserved_subtotals':
if value is not None:
for subkey, subvalue in value.items():
result['reserved_subtotals'][subkey] += subvalue
else:
result[key] += value
else:
result = balance
return result
class TestNetLedger(MainNetLedger):
network_name = 'testnet'

View file

@ -38,34 +38,42 @@ class TransactionCommandsTestCase(CommandTestCase):
await self.assertBalance(self.account, '11.0')
async def test_granular_balances(self):
account_balance = self.daemon.jsonrpc_account_balance
account2 = await self.daemon.jsonrpc_account_create("Tip-er")
self.assertEqual(await account_balance(reserved_subtotals=False), {
account_balance = self.daemon.jsonrpc_account_balance
wallet_balance = self.daemon.jsonrpc_wallet_balance
expected = {
'total': '10.0',
'available': '10.0',
'reserved': '0.0',
'reserved_subtotals': None
})
}
self.assertEqual(await account_balance(reserved_subtotals=False), expected)
self.assertEqual(await wallet_balance(reserved_subtotals=False), expected)
self.assertEqual(await account_balance(reserved_subtotals=True), {
expected = {
'total': '10.0',
'available': '10.0',
'reserved': '0.0',
'reserved_subtotals': {'claims': '0.0', 'supports': '0.0', 'tips': '0.0'}
})
}
self.assertEqual(await account_balance(reserved_subtotals=True), expected)
self.assertEqual(await wallet_balance(reserved_subtotals=True), expected)
# claim with update + supporting our own claim
stream1 = await self.stream_create('granularity', '3.0')
await self.stream_update(self.get_claim_id(stream1), data=b'news', bid='1.0')
await self.support_create(self.get_claim_id(stream1), '2.0')
self.assertEqual(await account_balance(reserved_subtotals=True), {
expected = {
'total': '9.977534',
'available': '6.977534',
'reserved': '3.0',
'reserved_subtotals': {'claims': '1.0', 'supports': '2.0', 'tips': '0.0'}
})
}
self.assertEqual(await account_balance(reserved_subtotals=True), expected)
self.assertEqual(await wallet_balance(reserved_subtotals=True), expected)
account2 = await self.daemon.jsonrpc_account_create("Tip-er")
address2 = await self.daemon.jsonrpc_address_unused(account2.id)
# send lbc to someone else
@ -77,6 +85,12 @@ class TransactionCommandsTestCase(CommandTestCase):
'reserved': '3.0',
'reserved_subtotals': {'claims': '1.0', 'supports': '2.0', 'tips': '0.0'}
})
self.assertEqual(await wallet_balance(reserved_subtotals=True), {
'total': '9.97741',
'available': '6.97741',
'reserved': '3.0',
'reserved_subtotals': {'claims': '1.0', 'supports': '2.0', 'tips': '0.0'}
})
# tip received
support1 = await self.support_create(
@ -88,6 +102,12 @@ class TransactionCommandsTestCase(CommandTestCase):
'reserved': '3.3',
'reserved_subtotals': {'claims': '1.0', 'supports': '2.0', 'tips': '0.3'}
})
self.assertEqual(await wallet_balance(reserved_subtotals=True), {
'total': '9.977268',
'available': '6.677268',
'reserved': '3.3',
'reserved_subtotals': {'claims': '1.0', 'supports': '2.0', 'tips': '0.3'}
})
# tip claimed
tx = await self.daemon.jsonrpc_support_abandon(txid=support1['txid'], nout=0)
@ -98,6 +118,12 @@ class TransactionCommandsTestCase(CommandTestCase):
'reserved': '3.0',
'reserved_subtotals': {'claims': '1.0', 'supports': '2.0', 'tips': '0.0'}
})
self.assertEqual(await wallet_balance(reserved_subtotals=True), {
'total': '9.977161',
'available': '6.977161',
'reserved': '3.0',
'reserved_subtotals': {'claims': '1.0', 'supports': '2.0', 'tips': '0.0'}
})
stream2 = await self.stream_create(
'granularity-is-cool', '0.1', account_id=account2.id, funding_account_ids=[account2.id]
@ -105,10 +131,17 @@ class TransactionCommandsTestCase(CommandTestCase):
# tip another claim
await self.support_create(
self.get_claim_id(stream2), '0.2', tip=True, funding_account_ids=[self.account.id])
self.get_claim_id(stream2), '0.2', tip=True, funding_account_ids=[self.account.id]
)
self.assertEqual(await account_balance(reserved_subtotals=True), {
'total': '9.077157',
'available': '6.077157',
'reserved': '3.0',
'reserved_subtotals': {'claims': '1.0', 'supports': '2.0', 'tips': '0.0'}
})
self.assertEqual(await wallet_balance(reserved_subtotals=True), {
'total': '9.938908',
'available': '6.638908',
'reserved': '3.3',
'reserved_subtotals': {'claims': '1.1', 'supports': '2.0', 'tips': '0.2'}
})