shared.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. tw.shared: classes and functions shared by all tracking wallet classes
  12. """
  13. from ..objmethods import HiliteStr, InitErrors, MMGenObject
  14. from ..obj import TwComment
  15. from ..addr import MMGenID
  16. class TwMMGenID(HiliteStr, InitErrors, MMGenObject):
  17. color = 'orange'
  18. width = 0
  19. trunc_ok = False
  20. def __new__(cls, proto, id_str):
  21. if isinstance(id_str, cls):
  22. return id_str
  23. try:
  24. ret = addr = disp = MMGenID(proto, id_str)
  25. sort_key, idtype = (ret.sort_key, 'mmgen')
  26. except Exception as e:
  27. try:
  28. coin, addr = id_str.split(':', 1)
  29. assert coin == proto.base_coin.lower(), (
  30. f'not a string beginning with the prefix {proto.base_coin.lower()!r}:')
  31. ret, sort_key, idtype, disp = (id_str, 'z_'+id_str, 'non-mmgen', 'non-MMGen')
  32. addr = proto.coin_addr(addr)
  33. except Exception as e2:
  34. return cls.init_fail(e, id_str, e2=e2)
  35. me = str.__new__(cls, ret)
  36. me.obj = ret
  37. me.disp = disp
  38. me.addr = addr
  39. me.sort_key = sort_key
  40. me.type = idtype
  41. me.proto = proto
  42. return me
  43. def fmt(self, width, /, **kwargs):
  44. return super().fmtc(self.disp, width, **kwargs)
  45. # non-displaying container for TwMMGenID, TwComment
  46. class TwLabel(str, InitErrors, MMGenObject):
  47. exc = 'BadTwLabel'
  48. passthru_excs = ('BadTwComment',)
  49. def __new__(cls, proto, text):
  50. if isinstance(text, cls):
  51. return text
  52. try:
  53. match text.split(None, 1):
  54. case [mmid_in]:
  55. comment = TwComment('')
  56. case [mmid_in, comment]:
  57. comment = TwComment(comment)
  58. mmid = TwMMGenID(proto, mmid_in)
  59. me = str.__new__(cls, mmid + (' ' + comment if comment else ''))
  60. me.mmid = mmid
  61. me.comment = comment
  62. me.proto = proto
  63. return me
  64. except Exception as e:
  65. return cls.init_fail(e, text)
  66. def get_tw_label(proto, s):
  67. """
  68. raise an exception on a malformed comment, return None on an empty or invalid label
  69. """
  70. try:
  71. return TwLabel(proto, s)
  72. except Exception as e:
  73. if type(e).__name__ == 'BadTwComment': # do it this way to avoid importing .exception
  74. raise
  75. else:
  76. return None