From d513035aad9aee0019e2ddb7fb9989af23709d18 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Sat, 12 Nov 2022 13:34:41 +0000 Subject: [PATCH] tracking wallet classes: reorder methods, cleanups --- mmgen/tw/addresses.py | 10 +-- mmgen/tw/txhistory.py | 12 ++-- mmgen/tw/unspent.py | 2 - mmgen/tw/view.py | 164 +++++++++++++++++++++--------------------- 4 files changed, 93 insertions(+), 95 deletions(-) diff --git a/mmgen/tw/addresses.py b/mmgen/tw/addresses.py index 8be7cc16..1fb44279 100755 --- a/mmgen/tw/addresses.py +++ b/mmgen/tw/addresses.py @@ -27,7 +27,6 @@ class TwAddresses(TwView,metaclass=AsyncInit): hdr_lbl = 'tracking wallet addresses' desc = 'address list' item_desc = 'address' - txid_w = 64 sort_key = 'twmmid' update_widths_on_age_toggle = True print_output_types = ('detail',) @@ -79,10 +78,9 @@ class TwAddresses(TwView,metaclass=AsyncInit): async def __init__(self,proto,minconf=1,mmgen_addrs='',wallet=None,get_data=False): - self.proto = proto - self.minconf = NonNegativeInt(minconf) - self.usr_addr_list = [] - self.rpc = await rpc_init(proto) + self.proto = proto + self.minconf = NonNegativeInt(minconf) + self.rpc = await rpc_init(proto) from .ctl import TrackingWallet self.wallet = wallet or await TrackingWallet(proto,mode='w') @@ -96,6 +94,8 @@ class TwAddresses(TwView,metaclass=AsyncInit): '(must be in form :[:])' ) from ..addrlist import AddrIdxList self.usr_addr_list = [MMGenID(self.proto,f'{a[0]}:{i}') for i in AddrIdxList(a[1])] + else: + self.usr_addr_list = [] if get_data: await self.get_data() diff --git a/mmgen/tw/txhistory.py b/mmgen/tw/txhistory.py index 42685480..3a4d01ac 100755 --- a/mmgen/tw/txhistory.py +++ b/mmgen/tw/txhistory.py @@ -12,13 +12,11 @@ tw.txhistory: Tracking wallet transaction history class for the MMGen suite """ -from collections import namedtuple - from ..util import fmt from ..base_obj import AsyncInit from ..objmethods import MMGenObject -from ..obj import CoinTxID,MMGenList,Int from ..rpc import rpc_init +from ..obj import NonNegativeInt from .view import TwView class TwTxHistory(TwView,metaclass=AsyncInit): @@ -35,7 +33,7 @@ class TwTxHistory(TwView,metaclass=AsyncInit): def __new__(cls,proto,*args,**kwargs): return MMGenObject.__new__(proto.base_proto_subclass(cls,'tw','txhistory')) - txid_w = 64 + has_wallet = False show_txid = False show_unconfirmed = False show_total_amt = False @@ -44,9 +42,9 @@ class TwTxHistory(TwView,metaclass=AsyncInit): filters = ('show_unconfirmed',) async def __init__(self,proto,sinceblock=0): - self.proto = proto - self.rpc = await rpc_init(proto) - self.sinceblock = Int( sinceblock if sinceblock >= 0 else self.rpc.blockcount + sinceblock ) + self.proto = proto + self.rpc = await rpc_init(proto) + self.sinceblock = NonNegativeIntInt( sinceblock if sinceblock >= 0 else self.rpc.blockcount + sinceblock ) @property def no_rpcdata_errmsg(self): diff --git a/mmgen/tw/unspent.py b/mmgen/tw/unspent.py index 081d844e..977ac314 100755 --- a/mmgen/tw/unspent.py +++ b/mmgen/tw/unspent.py @@ -29,7 +29,6 @@ from ..obj import ( ListItemAttr, MMGenListItem, TwComment, - get_obj, HexStr, CoinTxID, NonNegativeInt ) @@ -52,7 +51,6 @@ class TwUnspentOutputs(TwView,metaclass=AsyncInit): return MMGenObject.__new__(proto.base_proto_subclass(cls,'tw','unspent')) show_mmid = True - txid_w = 64 no_rpcdata_errmsg = """ No spendable outputs found! Import addresses with balances into your watch-only wallet using 'mmgen-addrimport' and then re-run this program. diff --git a/mmgen/tw/view.py b/mmgen/tw/view.py index 6dd8bfe2..936f35c5 100755 --- a/mmgen/tw/view.py +++ b/mmgen/tw/view.py @@ -32,10 +32,28 @@ from ..util import msg,msg_r,fmt,die,capfirst,make_timestr # base class for TwUnspentOutputs,TwAddresses,TwTxHistory: class TwView(MMGenObject): + class display_type: + + class squeezed: + detail = False + fmt_method = 'gen_squeezed_display' + need_column_widths = True + item_separator = '\n' + print_header = '[screen print truncated to width {}]\n' + + class detail: + detail = True + fmt_method = 'gen_detail_display' + need_column_widths = True + item_separator = '\n' + print_header = '' + + has_wallet = True dates_set = False cols = None reverse = False group = False + txid_w = 64 sort_key = 'age' interactive = False _display_data = {} @@ -91,48 +109,6 @@ class TwView(MMGenObject): Please resize your screen to at least {} characters and hit any key: """ - class display_type: - - class squeezed: - detail = False - fmt_method = 'gen_squeezed_display' - need_column_widths = True - item_separator = '\n' - print_header = '[screen print truncated to width {}]\n' - - class detail: - detail = True - fmt_method = 'gen_detail_display' - need_column_widths = True - item_separator = '\n' - print_header = '' - - def age_disp(self,o,age_fmt): - if age_fmt == 'confs': - return o.confs or '-' - elif age_fmt == 'block': - return self.rpc.blockcount + 1 - o.confs if o.confs else '-' - else: - return self.date_formatter[age_fmt](self.rpc,o.date) - - async def get_data(self,sort_key=None,reverse_sort=False): - - rpc_data = await self.get_rpc_data() - - if not rpc_data: - die(0,fmt(self.no_rpcdata_errmsg).strip()) - - lbl_id = ('account','label')['label_api' in self.rpc.caps] - - res = self.gen_data(rpc_data,lbl_id) - self.data = MMGenList(await res if type(res).__name__ == 'coroutine' else res) - self.disp_data = list(self.filter_data()) - - if not self.data: - die(1,self.no_data_errmsg) - - self.do_sort(key=sort_key,reverse=reverse_sort) - @property def age_w(self): return self.age_col_params[self.age_fmt][0] @@ -155,9 +131,69 @@ class TwView(MMGenObject): f'{val!r}: invalid age format for {op_desc} operation (must be one of {ok_vals!r})' ) self._age_fmt = val + def age_disp(self,o,age_fmt): + if age_fmt == 'confs': + return o.confs or '-' + elif age_fmt == 'block': + return self.rpc.blockcount + 1 - o.confs if o.confs else '-' + else: + return self.date_formatter[age_fmt](self.rpc,o.date) + def get_disp_prec(self,wide): return self.proto.coin_amt.max_prec + sort_disp = { + 'addr': 'Addr', + 'age': 'Age', + 'amt': 'Amt', + 'txid': 'TxID', + 'twmmid': 'MMGenID', + } + + sort_funcs = { + 'addr': lambda i: i.addr, + 'age': lambda i: 0 - i.confs, + 'amt': lambda i: i.amt, + 'txid': lambda i: f'{i.txid} {i.vout:04}', + 'twmmid': lambda i: i.twmmid.sort_key + } + + def sort_info(self,include_group=True): + ret = ([],['Reverse'])[self.reverse] + ret.append(self.sort_disp[self.sort_key]) + if include_group and self.group and (self.sort_key in ('addr','txid','twmmid')): + ret.append('Grouped') + return ret + + def do_sort(self,key=None,reverse=False): + key = key or self.sort_key + if key not in self.sort_funcs: + die(1,f'{key!r}: invalid sort key. Valid options: {" ".join(self.sort_funcs)}') + self.sort_key = key + assert type(reverse) == bool + self.data.sort(key=self.sort_funcs[key],reverse=reverse or self.reverse) + + async def get_data(self,sort_key=None,reverse_sort=False): + + rpc_data = await self.get_rpc_data() + + if not rpc_data: + die(0,fmt(self.no_rpcdata_errmsg).strip()) + + lbl_id = ('account','label')['label_api' in self.rpc.caps] + + res = self.gen_data(rpc_data,lbl_id) + self.data = MMGenList(await res if type(res).__name__ == 'coroutine' else res) + self.disp_data = list(self.filter_data()) + + if not self.data: + die(1,self.no_data_errmsg) + + self.do_sort(key=sort_key,reverse=reverse_sort) + + def filter_data(self): + return self.data.copy() + def get_term_columns(self,min_cols): from ..term import get_terminal_size,get_char_raw while True: @@ -172,37 +208,6 @@ class TwView(MMGenObject): else: return min_cols - sort_disp = { - 'addr': 'Addr', - 'age': 'Age', - 'amt': 'Amt', - 'txid': 'TxID', - 'twmmid': 'MMGenID', - } - - def sort_info(self,include_group=True): - ret = ([],['Reverse'])[self.reverse] - ret.append(self.sort_disp[self.sort_key]) - if include_group and self.group and (self.sort_key in ('addr','txid','twmmid')): - ret.append('Grouped') - return ret - - sort_funcs = { - 'addr': lambda i: i.addr, - 'age': lambda i: 0 - i.confs, - 'amt': lambda i: i.amt, - 'txid': lambda i: f'{i.txid} {i.vout:04}', - 'twmmid': lambda i: i.twmmid.sort_key - } - - def do_sort(self,key=None,reverse=False): - key = key or self.sort_key - if key not in self.sort_funcs: - die(1,f'{key!r}: invalid sort key. Valid options: {" ".join(self.sort_funcs)}') - self.sort_key = key - assert type(reverse) == bool - self.data.sort(key=self.sort_funcs[key],reverse=reverse or self.reverse) - def compute_column_widths(self,widths,maxws,minws,maxws_nice={},wide=False): def do_ret(freews): @@ -284,8 +289,11 @@ class TwView(MMGenObject): def subheader(self,color): return '' - def filter_data(self): - return self.data.copy() + def footer(self,color): + return '\nTOTAL: {} {}\n'.format( + self.total.hl(color=color) if hasattr(self,'total') else None, + self.proto.dcoin + ) if hasattr(self,'total') else '' async def format(self,display_type,color=True,cached=False,interactive=False): @@ -320,12 +328,6 @@ class TwView(MMGenObject): return self._display_data[display_type] + ('' if interactive else self.footer(color)) - def footer(self,color): - return '\nTOTAL: {} {}\n'.format( - self.total.hl(color=color) if hasattr(self,'total') else None, - self.proto.dcoin - ) if hasattr(self,'total') else '' - async def view_filter_and_sort(self): from ..opts import opt from ..term import get_char