info.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #!/usr/bin/env python3
  2. #
  3. # mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet
  4. # Copyright (C)2013-2022 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
  9. # https://gitlab.com/mmgen/mmgen
  10. """
  11. tx.info: transaction info class
  12. """
  13. from ..globalvars import *
  14. from ..color import red,green,orange
  15. from ..opts import opt
  16. from ..util import msg,msg_r
  17. import importlib
  18. class TxInfo:
  19. def __init__(self,tx):
  20. self.tx = tx
  21. def format(self,terse=False,sort='addr'):
  22. tx = self.tx
  23. if tx.proto.base_proto == 'Ethereum':
  24. blockcount = None
  25. else:
  26. try:
  27. blockcount = tx.rpc.blockcount
  28. except:
  29. blockcount = None
  30. def get_max_mmwid(io):
  31. if io == tx.inputs:
  32. sel_f = lambda o: len(o.mmid) + 2 # len('()')
  33. else:
  34. sel_f = lambda o: len(o.mmid) + (2,8)[bool(o.is_chg)] # + len(' (chg)')
  35. return max(max([sel_f(o) for o in io if o.mmid] or [0]),len(nonmm_str))
  36. nonmm_str = f'(non-{g.proj_name} address)'
  37. max_mmwid = max(get_max_mmwid(tx.inputs),get_max_mmwid(tx.outputs))
  38. def gen_view():
  39. yield (self.txinfo_hdr_fs_short if terse else self.txinfo_hdr_fs).format(
  40. i = tx.txid.hl(),
  41. a = tx.send_amt.hl(),
  42. c = tx.dcoin,
  43. t = tx.timestamp,
  44. r = green('True') if tx.is_replaceable() else red('False'),
  45. s = green('True') if tx.signed else red('False'),
  46. l = (
  47. orange(self.strfmt_locktime(terse=True)) if tx.locktime else
  48. green('None') ))
  49. if tx.chain != 'mainnet': # if mainnet has a coin-specific name, display it
  50. yield green(f'Chain: {tx.chain.upper()}') + '\n'
  51. if tx.coin_txid:
  52. yield f'{tx.coin} TxID: {tx.coin_txid.hl()}\n'
  53. enl = ('\n','')[bool(terse)]
  54. yield enl
  55. if tx.comment:
  56. yield f'Comment: {tx.comment.hl()}\n{enl}'
  57. yield self.format_body(blockcount,nonmm_str,max_mmwid,enl,terse=terse,sort=sort)
  58. yield self.txinfo_ftr_fs.format(
  59. i = tx.sum_inputs().hl(),
  60. o = tx.sum_outputs().hl(),
  61. C = tx.change.hl(),
  62. s = tx.send_amt.hl(),
  63. a = self.format_abs_fee(),
  64. r = self.format_rel_fee(terse),
  65. d = tx.dcoin,
  66. c = tx.coin )
  67. if opt.verbose:
  68. yield self.format_verbose_footer()
  69. return ''.join(gen_view()) # TX label might contain non-ascii chars
  70. def view_with_prompt(self,prompt,pause=True):
  71. prompt += ' (y)es, (N)o, pager (v)iew, (t)erse view: '
  72. from ..term import get_char
  73. while True:
  74. reply = get_char( prompt, immed_chars='YyNnVvTt' ).strip('\n\r')
  75. msg('')
  76. if reply == '' or reply in 'Nn':
  77. break
  78. elif reply in 'YyVvTt':
  79. self.view(
  80. pager = reply in 'Vv',
  81. pause = pause,
  82. terse = reply in 'Tt' )
  83. break
  84. else:
  85. msg('Invalid reply')
  86. def view(self,pager=False,pause=True,terse=False):
  87. o = self.format(terse=terse)
  88. if pager:
  89. from ..ui import do_pager
  90. do_pager(o)
  91. else:
  92. msg_r(o)
  93. from ..term import get_char
  94. if pause:
  95. get_char('Press any key to continue: ')
  96. msg('')
  97. def init_info(tx):
  98. return getattr(
  99. importlib.import_module(f'mmgen.proto.{tx.proto.base_proto_coin.lower()}.tx.info'),
  100. ('Token' if tx.proto.tokensym else '') + 'TxInfo' )(tx)