__init__.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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. tx.__init__: transaction class initializer
  12. """
  13. def _base_proto_subclass(clsname, modname, proto):
  14. if proto:
  15. clsname = ('Token' if proto.tokensym else '') + clsname
  16. modname = f'mmgen.proto.{proto.base_proto_coin.lower()}.tx.{modname}'
  17. else:
  18. modname = 'mmgen.tx.base'
  19. import importlib
  20. return getattr(importlib.import_module(modname), clsname)
  21. def _get_cls_info(clsname, modname, kwargs):
  22. if 'proto' in kwargs:
  23. proto = kwargs['proto']
  24. elif 'data' in kwargs:
  25. proto = kwargs['data']['proto']
  26. elif 'filename' in kwargs:
  27. from .file import MMGenTxFile
  28. proto = MMGenTxFile.get_proto(kwargs['cfg'], kwargs['filename'], quiet_open=True)
  29. elif clsname == 'Base':
  30. proto = None
  31. else:
  32. raise ValueError(
  33. f"{clsname} must be instantiated with 'proto', 'data' or 'filename' keyword")
  34. if clsname == 'Completed':
  35. from ..util import get_extension, die
  36. from .completed import Completed
  37. ext = get_extension(kwargs['filename'])
  38. cls = Completed.ext_to_cls(ext, proto)
  39. if not cls:
  40. die(1, f'{ext!r}: unrecognized file extension for CompletedTX')
  41. clsname = cls.__name__
  42. modname = cls.__module__.rsplit('.', maxsplit=1)[-1]
  43. elif clsname == 'New' and kwargs['target'] == 'swaptx':
  44. clsname = 'NewSwap'
  45. modname = 'new_swap'
  46. kwargs['proto'] = proto
  47. if 'automount' in kwargs:
  48. if kwargs['automount']:
  49. clsname = 'Automount' + clsname
  50. del kwargs['automount']
  51. return (clsname, modname, kwargs)
  52. def _get_obj(_clsname, _modname, **kwargs):
  53. """
  54. determine cls/mod/proto and pass them to _base_proto_subclass() to get a transaction instance
  55. """
  56. clsname, modname, kwargs = _get_cls_info(_clsname, _modname, kwargs)
  57. return _base_proto_subclass(clsname, modname, kwargs['proto'])(**kwargs)
  58. async def _get_obj_async(_clsname, _modname, **kwargs):
  59. clsname, modname, kwargs = _get_cls_info(_clsname, _modname, kwargs)
  60. proto = kwargs['proto']
  61. # NB: tracking wallet needed to retrieve the 'symbol' and 'decimals' parameters of token addr
  62. # (see twctl:import_token()).
  63. # No twctl required for the Unsigned and Signed(data=unsigned.__dict__) classes used during
  64. # signing.
  65. if proto and proto.tokensym and clsname in (
  66. 'New',
  67. 'OnlineSigned',
  68. 'AutomountOnlineSigned',
  69. 'Sent',
  70. 'AutomountSent'):
  71. from ..tw.ctl import TwCtl
  72. kwargs['twctl'] = await TwCtl(kwargs['cfg'], proto, no_rpc=True)
  73. return _base_proto_subclass(clsname, modname, proto)(**kwargs)
  74. def _get(clsname, modname):
  75. return lambda **kwargs: _get_obj(clsname, modname, **kwargs)
  76. def _get_async(clsname, modname):
  77. return lambda **kwargs: _get_obj_async(clsname, modname, **kwargs)
  78. BaseTX = _get('Base', 'base')
  79. UnsignedTX = _get('Unsigned', 'unsigned')
  80. NewTX = _get_async('New', 'new')
  81. NewSwapTX = _get_async('NewSwap', 'new_swap')
  82. CompletedTX = _get_async('Completed', 'completed')
  83. SignedTX = _get_async('Signed', 'signed')
  84. OnlineSignedTX = _get_async('OnlineSigned', 'online')
  85. SentTX = _get_async('Sent', 'online')
  86. BumpTX = _get_async('Bump', 'bump')