__init__.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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.ops.__init__: Monero wallet ops for the MMGen Suite
  12. """
  13. import re, atexit
  14. from ...color import blue
  15. from ...util import msg, die, fmt
  16. from ...protocol import init_proto
  17. from ...tx.util import get_autosign_obj
  18. from ... import xmrwallet
  19. from .. import uarg_info
  20. class OpBase:
  21. opts = ('wallet_dir',)
  22. trust_monerod = False
  23. do_umount = True
  24. name = None
  25. return_data = False
  26. def __init__(self, cfg, uarg_tuple):
  27. def gen_classes():
  28. for cls in type(self).__mro__:
  29. if not cls.__name__.startswith('OpMixin'):
  30. yield cls
  31. if cls.__name__ == 'OpBase':
  32. break
  33. self.cfg = cfg
  34. self.uargs = uarg_tuple
  35. self.compat_call = self.uargs.compat_call
  36. self.tx_dir = 'txauto_dir' if self.compat_call else 'xmr_tx_dir'
  37. classes = tuple(gen_classes())
  38. self.opts = tuple(set(opt for cls in classes for opt in xmrwallet.opts))
  39. if not hasattr(self, 'stem'):
  40. self.stem = self.name
  41. global fmt_amt, hl_amt, addr_width
  42. def fmt_amt(amt):
  43. return self.proto.coin_amt(amt, from_unit='atomic').fmt(5, prec=12, color=True)
  44. def hl_amt(amt):
  45. return self.proto.coin_amt(amt, from_unit='atomic').hl()
  46. addr_width = 95 if self.cfg.full_address else 24
  47. self.proto = init_proto(cfg, 'xmr', network=self.cfg.network, need_amt=True)
  48. id_cur = None
  49. for cls in classes:
  50. if id(cls.check_uopts) != id_cur:
  51. cls.check_uopts(self)
  52. id_cur = id(cls.check_uopts)
  53. id_cur = None
  54. for cls in classes:
  55. if id(cls.pre_init_action) != id_cur:
  56. cls.pre_init_action(self)
  57. id_cur = id(cls.pre_init_action)
  58. if cfg.autosign:
  59. self.asi = get_autosign_obj(cfg)
  60. def check_uopts(self):
  61. def check_pat_opt(name):
  62. val = getattr(self.cfg, name)
  63. if not re.fullmatch(uarg_info[name].pat, val, re.ASCII):
  64. die(1, '{!r}: invalid value for --{}: it must have format {!r}'.format(
  65. val,
  66. name.replace('_', '-'),
  67. uarg_info[name].annot))
  68. for attr in self.cfg.__dict__:
  69. if attr in xmrwallet.opts and not attr in self.opts:
  70. die(1, 'Option --{} not supported for {!r} operation'.format(
  71. attr.replace('_', '-'),
  72. self.name))
  73. for opt in xmrwallet.pat_opts:
  74. if getattr(self.cfg, opt, None):
  75. check_pat_opt(opt)
  76. def parse_tx_relay_opt(self):
  77. return re.fullmatch(
  78. uarg_info['tx_relay_daemon'].pat,
  79. self.cfg.tx_relay_daemon,
  80. re.ASCII)
  81. def get_tx_cls(self, clsname):
  82. from ..file.tx import MoneroMMGenTX
  83. return getattr(MoneroMMGenTX, clsname + ('Compat' if self.compat_call else ''))
  84. def display_tx_relay_info(self, *, indent=''):
  85. m = self.parse_tx_relay_opt()
  86. msg(fmt(f"""
  87. TX relay info:
  88. Host: {blue(m[1])}
  89. Proxy: {blue(m[2] or 'None')}
  90. """, strip_char='\t', indent=indent))
  91. def mount_removable_device(self, registered=[]):
  92. if self.cfg.autosign:
  93. if not self.asi.device_inserted:
  94. die(1, 'Removable device not present!')
  95. if self.do_umount and not registered:
  96. atexit.register(lambda: self.asi.do_umount())
  97. registered.append(None)
  98. self.asi.do_mount()
  99. self.post_mount_action()
  100. def pre_init_action(self):
  101. pass
  102. def post_main_success(self):
  103. pass
  104. def post_main_failure(self):
  105. pass
  106. async def stop_wallet_daemon(self):
  107. pass
  108. def post_mount_action(self):
  109. pass