123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- """
- tw.prune: Tracking wallet pruned listaddresses class for the MMGen suite
- """
- from ..util import msg, msg_r, rmsg, ymsg
- from ..color import red, green, gray, yellow
- from ..obj import ListItemAttr
- from .addresses import TwAddresses
- from .view import CUR_HOME, ERASE_ALL
- class TwAddressesPrune(TwAddresses):
- mod_subpath = 'tw.prune'
- class TwAddress(TwAddresses.TwAddress):
- valid_attrs = TwAddresses.TwAddress.valid_attrs | {'tag'}
- tag = ListItemAttr(bool, typeconv=False, reassign_ok=True)
- async def __init__(self, *args, warn_used=False, **kwargs):
- self.warn_used = warn_used
- await super().__init__(*args, **kwargs)
- def gen_display(self, data, cw, fs, color, fmt_method):
- id_save = data[0].al_id
- yes, no = red('Yes '), green('No ')
- for n, d in enumerate(data, 1):
- if id_save != d.al_id:
- id_save = d.al_id
- yield ''.ljust(self.term_width)
- yield (
- gray(fmt_method(n, d, cw, fs, False, 'Yes ', 'No ')) if d.tag else
- fmt_method(n, d, cw, fs, True, yes, no))
- def do_prune(self):
- def gen():
- for n, d in enumerate(self.data, 1):
- if d.tag:
- pruned.append(n)
- if d.amt:
- rmsg(f'Warning: pruned address {d.twmmid.addr} has a balance!')
- elif self.warn_used and d.recvd:
- ymsg(f'Warning: pruned address {d.twmmid.addr} is used!')
- else:
- yield d
- pruned = []
- self.reverse = False
- self.do_sort('twmmid')
- self.data = list(gen())
- return pruned
- class action(TwAddresses.action):
- def get_addrnums(self, parent, desc):
- prompt = f'Enter a range or space-separated list of addresses to {desc}: '
- from ..ui import line_input
- msg('')
- while True:
- reply = line_input(parent.cfg, prompt).strip()
- if reply:
- from ..addrlist import AddrIdxList
- from ..obj import get_obj
- selected = get_obj(AddrIdxList, fmt_str=','.join(reply.split()))
- if selected:
- if selected[-1] <= len(parent.disp_data):
- return selected
- msg(f'Address number must be <= {len(parent.disp_data)}')
- else:
- return []
- def query_user(self, desc, addrnum, e):
- from collections import namedtuple
- md = namedtuple('mdata', ['wmsg', 'prompt'])
- m = {
- 'amt': md(
- red('Address #{a} ({b}) has a balance of {c}!'.format(
- a = addrnum,
- b = e.twmmid.addr,
- c = e.amt.hl2(color=False, unit=True))),
- '[p]rune anyway, [P]rune all with balance, [s]kip, [S]kip all with balance: ',
- ),
- 'used': md(
- yellow('Address #{a} ({b}) is used!'.format(
- a = addrnum,
- b = e.twmmid.addr)),
- '[p]rune anyway, [P]rune all used, [s]kip, [S]kip all used: ',
- ),
- }
- from ..term import get_char
- valid_res = 'pPsS'
- msg(m[desc].wmsg)
- while True:
- res = get_char(m[desc].prompt, immed_chars=valid_res)
- if res in valid_res:
- msg('')
- return {
-
- 'p': (False, True),
- 'P': (True, True),
- 's': (False, False),
- 'S': (True, False),
- }[res]
- else:
- msg('\nInvalid keypress')
- async def a_prune(self, parent):
- def do_entry(desc, n, addrnum, e):
- if auto[desc]:
- return False
- else:
- auto[desc], prune = self.query_user(desc, addrnum, e)
- dfl[desc] = auto[desc] and prune
- skip_all_used = auto['used'] and not dfl['used']
- if auto[desc]:
- for idx in addrnums[:n]:
- e = parent.disp_data[idx-1]
- if skip_all_used and e.recvd:
- e.tag = False
- elif desc == 'amt' and e.amt:
- e.tag = prune
- elif desc == 'used' and (e.recvd and not e.amt):
- e.tag = prune
-
- if skip_all_used:
- auto['amt'] = True
- dfl['amt'] = False
- return prune
- addrnums = self.get_addrnums(parent, 'prune')
- dfl = {'amt': False, 'used': False}
- auto = {'amt': False, 'used': False}
- for n, addrnum in enumerate(addrnums):
- e = parent.disp_data[addrnum-1]
- if e.amt and not dfl['amt']:
- e.tag = do_entry('amt', n, addrnum, e)
- elif parent.warn_used and (e.recvd and not e.amt) and not dfl['used']:
- e.tag = do_entry('used', n, addrnum, e)
- else:
- e.tag = True
- if parent.scroll:
- msg_r(CUR_HOME + ERASE_ALL)
- async def a_unprune(self, parent):
- for addrnum in self.get_addrnums(parent, 'unprune'):
- parent.disp_data[addrnum-1].tag = False
- if parent.scroll:
- msg_r(CUR_HOME + ERASE_ALL)
- async def a_clear_prune_list(self, parent):
- for d in parent.data:
- d.tag = False
|