bal.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #!/usr/bin/env python3
  2. #
  3. # MMGen Wallet, a terminal-based cryptocurrency wallet
  4. # Copyright (C)2013-2024 The MMGen Project <mmgen@tuta.io>
  5. # Licensed under the GNU General Public License, Version 3:
  6. # https://www.gnu.org/licenses
  7. # Public project repositories:
  8. # https://github.com/mmgen/mmgen-wallet
  9. # https://gitlab.com/mmgen/mmgen-wallet
  10. """
  11. proto.btc.tw.bal: Bitcoin base protocol tracking wallet balance class
  12. """
  13. from ....tw.bal import TwGetBalance
  14. from ....tw.shared import get_tw_label
  15. from ....rpc import rpc_init
  16. class BitcoinTwGetBalance(TwGetBalance):
  17. async def __init__(self, cfg, proto, minconf, quiet):
  18. self.rpc = await rpc_init(cfg, proto)
  19. self.walletinfo = await self.rpc.walletinfo
  20. await super().__init__(cfg, proto, minconf, quiet)
  21. start_labels = ('TOTAL', 'Non-MMGen', 'Non-wallet')
  22. conf_cols = {
  23. 'unconfirmed': 'Unconfirmed',
  24. 'lt_minconf': '<{minconf} confs',
  25. 'ge_minconf': '>={minconf} confs',
  26. }
  27. async def create_data(self):
  28. lbl_id = ('account', 'label')['label_api' in self.rpc.caps]
  29. for d in await self.rpc.call('listunspent', 0):
  30. tw_lbl = get_tw_label(self.proto, d[lbl_id])
  31. if tw_lbl:
  32. if tw_lbl.mmid.type == 'mmgen':
  33. label = tw_lbl.mmid.obj.sid
  34. if label not in self.data:
  35. self.data[label] = self.balance_info()
  36. else:
  37. label = 'Non-MMGen'
  38. else:
  39. label = 'Non-wallet'
  40. amt = self.proto.coin_amt(d['amount'])
  41. if not d['confirmations']:
  42. self.data['TOTAL']['unconfirmed'] += amt
  43. self.data[label]['unconfirmed'] += amt
  44. col_key = ('lt_minconf', 'ge_minconf')[d['confirmations'] >= self.minconf]
  45. self.data['TOTAL'][col_key] += amt
  46. self.data[label][col_key] += amt
  47. if d['spendable']: # TODO: use 'solvable' for descriptor wallets?
  48. self.data[label]['spendable'] += amt
  49. def format(self, color):
  50. def gen_spendable_warning():
  51. if check_spendable:
  52. for k, v in self.data.items():
  53. if v['spendable']:
  54. yield red(f'Warning: this wallet contains PRIVATE KEYS for {k} outputs!')
  55. if color:
  56. from ....color import red
  57. else:
  58. from ....color import nocolor as red
  59. desc_wallet = self.walletinfo.get('descriptors')
  60. check_spendable = not desc_wallet or (desc_wallet and self.walletinfo['private_keys_enabled'])
  61. warning = '\n'.join(gen_spendable_warning())
  62. return super().format(color) + ('\n' if warning else '') + warning