include.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #!/usr/bin/env python3
  2. #
  3. # MMGen Wallet, a terminal-based cryptocurrency wallet
  4. # Copyright (C)2013-2025 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. xmrwallet.include: Monero wallet shared data for the MMGen Suite
  12. """
  13. import re
  14. from ..objmethods import MMGenObject, HiliteStr, InitErrors
  15. from ..color import red, green, pink
  16. from ..addr import CoinAddr, AddrIdx
  17. from ..util import die
  18. def gen_acct_addr_info(self, wallet_data, account, indent=''):
  19. fs = indent + '{I:<3} {A} {U} {B} {L}'
  20. addrs_data = wallet_data.addrs_data[account]['addresses']
  21. for d in addrs_data:
  22. d['unlocked_balance'] = 0
  23. if 'per_subaddress' in wallet_data.bals_data:
  24. for d in wallet_data.bals_data['per_subaddress']:
  25. if d['account_index'] == account:
  26. addrs_data[d['address_index']]['unlocked_balance'] = d['unlocked_balance']
  27. from .ops import addr_width
  28. yield fs.format(
  29. I = '',
  30. A = 'Address'.ljust(addr_width),
  31. U = 'Used'.ljust(5),
  32. B = ' Unlocked Balance',
  33. L = 'Label')
  34. for addr in addrs_data:
  35. ca = CoinAddr(self.proto, addr['address'])
  36. bal = addr['unlocked_balance']
  37. if self.cfg.skip_empty_addresses and addr['used'] and not bal:
  38. continue
  39. from .ops import fmt_amt
  40. yield fs.format(
  41. I = addr['address_index'],
  42. A = ca.hl(0) if self.cfg.full_address else ca.fmt(0, color=True, width=addr_width),
  43. U = (red('True ') if addr['used'] else green('False')),
  44. B = fmt_amt(bal),
  45. L = pink(addr['label']))
  46. class XMRWalletAddrSpec(HiliteStr, InitErrors, MMGenObject):
  47. color = 'cyan'
  48. width = 0
  49. trunc_ok = False
  50. min_len = 5 # 1:0:0
  51. max_len = 14 # 9999:9999:9999
  52. def __new__(cls, arg1, arg2=None, arg3=None):
  53. if isinstance(arg1, cls):
  54. return arg1
  55. try:
  56. if isinstance(arg1, str):
  57. me = str.__new__(cls, arg1)
  58. m = re.fullmatch('({n}):({n}):({n}|None)'.format(n=r'[0-9]{1,4}'), arg1)
  59. assert m is not None, f'{arg1!r}: invalid XMRWalletAddrSpec'
  60. for e in m.groups():
  61. if len(e) != 1 and e[0] == '0':
  62. die(2, f'{e}: leading zeroes not permitted in XMRWalletAddrSpec element')
  63. me.wallet = AddrIdx(m[1])
  64. me.account = int(m[2])
  65. me.account_address = None if m[3] == 'None' else int(m[3])
  66. else:
  67. me = str.__new__(cls, f'{arg1}:{arg2}:{arg3}')
  68. for arg in [arg1, arg2] + ([] if arg3 is None else [arg3]):
  69. assert isinstance(arg, int), f'{arg}: XMRWalletAddrSpec component not of type int'
  70. assert arg is None or arg <= 9999, f'{arg}: XMRWalletAddrSpec component greater than 9999'
  71. me.wallet = AddrIdx(arg1)
  72. me.account = arg2
  73. me.account_address = arg3
  74. return me
  75. except Exception as e:
  76. return cls.init_fail(e, me)