asset.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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. swap.asset: swap asset class for the MMGen Wallet suite
  12. """
  13. from collections import namedtuple
  14. from ..util import die
  15. class SwapAsset:
  16. _ad = namedtuple('swap_asset_data', ['desc', 'name', 'full_name', 'abbr', 'tested'])
  17. assets_data = {}
  18. evm_contracts = {}
  19. unsupported = ()
  20. blacklisted = {}
  21. evm_chains = ()
  22. def fmt_assets_data(self, indent=''):
  23. def gen_good():
  24. fs = '%s{:10} {:23} {:9} {}' % indent
  25. yield fs.format('ASSET', 'DESCRIPTION', 'STATUS', 'CONTRACT ADDRESS')
  26. for k, v in self.assets_data.items():
  27. if not k in self.blacklisted:
  28. if k in self.send or k in self.recv:
  29. yield fs.format(
  30. k,
  31. v.desc,
  32. 'tested' if v.tested else 'untested',
  33. self.evm_contracts.get(k,'-'))
  34. def gen_bad():
  35. if self.blacklisted:
  36. fs = '%s{:10} {:23} {}' % indent
  37. yield '\n\nBlacklisted assets:'
  38. yield fs.format('ASSET', 'DESCRIPTION', 'REASON')
  39. for k, v in self.blacklisted.items():
  40. yield fs.format(k, self.assets_data[k].desc, v)
  41. return '\n'.join(gen_good()) + '\n'.join(gen_bad())
  42. @classmethod
  43. def init_from_memo(cls, s):
  44. for d in cls.assets_data.values():
  45. if s in (d.abbr, d.full_name):
  46. return cls(d.name or d.full_name, 'recv')
  47. die('SwapAssetError', f'{s!r}: unrecognized asset name or abbreviation')
  48. @property
  49. def tested(self):
  50. return [k for k, v in self.assets_data.items() if v.tested]
  51. @property
  52. def send(self):
  53. return set(self.assets_data) - set(self.unsupported) - set(self.blacklisted)
  54. @property
  55. def recv(self):
  56. return set(self.assets_data) - set(self.unsupported) - set(self.blacklisted)
  57. @property
  58. def chain(self):
  59. return self.data.full_name.split('.', 1)[0] if self.data.full_name else self.name
  60. @property
  61. def coin(self):
  62. return self.data.name or self.data.full_name.split('.', 1)[0]
  63. @property
  64. def full_name(self):
  65. return self.data.full_name or f'{self.data.name}.{self.data.name}'
  66. @property
  67. def short_name(self):
  68. return self.data.name or self.data.full_name.split('.', 1)[1]
  69. @property
  70. def tokensym(self):
  71. return None if self.data.name else self.data.full_name.split('.', 1)[1]
  72. @property
  73. def memo_asset_name(self):
  74. return self.data.abbr or self.data.full_name
  75. def __init__(self, name, direction):
  76. if name not in self.assets_data:
  77. die('SwapAssetError', f'{name!r}: unrecognized asset')
  78. assert direction in ('send', 'recv'), 'direction must be ‘send’ or ‘recv’'
  79. if direction == 'send' and name not in self.send:
  80. die('SwapAssetError', f'{name!r} unsupported send asset')
  81. if direction == 'recv' and name not in self.recv:
  82. die('SwapAssetError', f'{name!r} unsupported receive asset')
  83. self.direction = direction
  84. self.name = name
  85. self.data = self.assets_data[name]
  86. self.desc = self.data.desc