forked from LBRYCommunity/lbry-sdk
added wallet balance command
This commit is contained in:
parent
fea7275148
commit
e2b92c99ef
5 changed files with 105 additions and 19 deletions
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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'}
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue