label.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #!/usr/bin/env python3
  2. #
  3. # MMGen Wallet, a terminal-based cryptocurrency wallet
  4. # Copyright (C)2013-2026 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.label: Monero wallet ops for the MMGen Suite
  12. """
  13. from ...color import pink, cyan, gray
  14. from ...util import msg, ymsg, gmsg, die, make_timestr
  15. from ...ui import keypress_confirm
  16. from ...obj import TwComment
  17. from ...addr import CoinAddr
  18. from ..rpc import MoneroWalletRPC
  19. from .spec import OpMixinSpec
  20. from .wallet import OpWallet
  21. class OpLabel(OpMixinSpec, OpWallet):
  22. spec_id = 'label_spec'
  23. spec_key = ((1, 'source'),)
  24. opts = ()
  25. wallet_offline = True
  26. async def main(self, add_timestr='ask'):
  27. if not self.compat_call:
  28. gmsg('\n{a} label for wallet {b}, account #{c}, address #{d}'.format(
  29. a = 'Setting' if self.label else 'Removing',
  30. b = self.source.idx,
  31. c = self.account,
  32. d = self.address_idx))
  33. h = MoneroWalletRPC(self, self.source)
  34. h.open_wallet('source', refresh=False)
  35. wallet_data = h.get_wallet_data()
  36. max_acct = len(wallet_data.accts_data['subaddress_accounts']) - 1
  37. if self.account > max_acct:
  38. die(2, f'{self.account}: requested account index out of bounds (>{max_acct})')
  39. ret = h.print_acct_addrs(wallet_data, self.account)
  40. if self.address_idx > len(ret) - 1:
  41. die(2, '{}: requested address index out of bounds (>{})'.format(
  42. self.address_idx,
  43. len(ret) - 1))
  44. addr = ret[self.address_idx]
  45. if self.label and add_timestr == 'ask':
  46. add_timestr = keypress_confirm(self.cfg, '\n Add timestamp to label?')
  47. new_label = TwComment(
  48. (self.label + (f' [{make_timestr()}]' if add_timestr else '')) if self.label
  49. else '')
  50. if not self.compat_call:
  51. ca = CoinAddr(self.proto, addr['address'])
  52. from . import addr_width
  53. msg('\n {a} {b}\n {c} {d}\n {e} {f}'.format(
  54. a = 'Address: ',
  55. b = ca.hl(0) if self.cfg.full_address else ca.fmt(0, addr_width, color=True),
  56. c = 'Existing label:',
  57. d = pink(addr['label']) if addr['label'] else gray('[none]'),
  58. e = 'New label: ',
  59. f = pink(new_label) if new_label else gray('[none]')))
  60. op = 'remove' if not new_label else 'update' if addr['label'] else 'set'
  61. if addr['label'] == new_label:
  62. ymsg('\nLabel is unchanged, operation cancelled')
  63. elif self.compat_call or keypress_confirm(self.cfg, f' {op.capitalize()} label?'):
  64. h.set_label(self.account, self.address_idx, new_label)
  65. ret = h.print_acct_addrs(h.get_wallet_data(print=False), self.account)
  66. label_chk = ret[self.address_idx]['label']
  67. if label_chk != new_label:
  68. ymsg(f'Warning: new label {label_chk!r} does not match requested value!')
  69. return False
  70. else:
  71. msg(cyan('\nLabel successfully {}'.format('set' if op == 'set' else op+'d')))
  72. return new_label
  73. else:
  74. ymsg('\nOperation cancelled by user request')