tracking wallet classes: reorder methods, cleanups

This commit is contained in:
The MMGen Project 2022-11-12 13:34:41 +00:00
commit d513035aad
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
4 changed files with 83 additions and 85 deletions

View file

@ -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 <seed ID>:[<type>:]<idx list>)' )
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()

View file

@ -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):

View file

@ -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.

View file

@ -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