mmgen.tw.{common,addrs,txhistory,unspent}: cleanups
This commit is contained in:
parent
26dd466635
commit
2b026f1ae7
12 changed files with 75 additions and 62 deletions
|
|
@ -71,7 +71,7 @@ class Hilite:
|
|||
assert trunc_ok, "If 'trunc_ok' is false, 'width' must be >= screen width of string"
|
||||
s = truncate_str(s,width-add_len)
|
||||
if s == '' and nullrepl:
|
||||
s = nullrepl.center(width)
|
||||
s = nullrepl.ljust(width)
|
||||
else:
|
||||
s = a+s+b
|
||||
if center:
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ class BitcoinTwCommon:
|
|||
else:
|
||||
lm.confs = d['confirmations']
|
||||
lm.txid = d['txid']
|
||||
lm.vout = d['vout']
|
||||
lm.date = None
|
||||
data[lm] = {
|
||||
'amt': self.proto.coin_amt('0'),
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ class BitcoinTwTxHistory(TwTxHistory,BitcoinTwCommon):
|
|||
prompt = """
|
||||
Sort options: [t]xid, [a]mt, total a[m]t, [A]ge, [b]locknum, [r]everse
|
||||
Column options: toggle [D]ays/date/confs/block, tx[i]d, [T]otal amt
|
||||
Filter options: show [u]nconfirmed
|
||||
Filters: show [u]nconfirmed
|
||||
View/Print: pager [v]iew, full [V]iew, screen [p]rint, full [P]rint
|
||||
Actions: [q]uit, r[e]draw:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -97,12 +97,15 @@ class tool_cmd(tool_cmd_base):
|
|||
return await al.format( showcoinaddrs, sort, show_age, age_fmt or 'confs' )
|
||||
|
||||
async def twops(self,
|
||||
obj,pager,reverse,detail,sort,age_fmt,interactive,show_mmid):
|
||||
obj,pager,reverse,detail,sort,age_fmt,interactive,
|
||||
**kwargs ):
|
||||
|
||||
obj.interactive = interactive
|
||||
obj.reverse = reverse
|
||||
obj.age_fmt = age_fmt
|
||||
obj.show_mmid = show_mmid
|
||||
obj.interactive = interactive
|
||||
|
||||
for k,v in kwargs.items():
|
||||
setattr(obj,k,v)
|
||||
|
||||
await obj.get_data(sort_key=sort,reverse_sort=reverse)
|
||||
|
||||
|
|
@ -128,7 +131,8 @@ class tool_cmd(tool_cmd_base):
|
|||
from ..tw.unspent import TwUnspentOutputs
|
||||
obj = await TwUnspentOutputs(self.proto,minconf=minconf)
|
||||
ret = await self.twops(
|
||||
obj,pager,reverse,wide,sort,age_fmt,interactive,show_mmid)
|
||||
obj,pager,reverse,wide,sort,age_fmt,interactive,
|
||||
show_mmid = show_mmid )
|
||||
del obj.wallet
|
||||
return ret
|
||||
|
||||
|
|
@ -144,7 +148,7 @@ class tool_cmd(tool_cmd_base):
|
|||
|
||||
obj = await TwTxHistory(self.proto,sinceblock=sinceblock)
|
||||
return await self.twops(
|
||||
obj,pager,reverse,detail,sort,age_fmt,interactive,show_mmid=None)
|
||||
obj,pager,reverse,detail,sort,age_fmt,interactive )
|
||||
|
||||
async def add_label(self,mmgen_or_coin_addr:str,label:str):
|
||||
"add descriptive label for address in tracking wallet"
|
||||
|
|
|
|||
|
|
@ -63,9 +63,7 @@ class TwAddrList(MMGenDict,TwCommon,metaclass=AsyncInit):
|
|||
|
||||
mmids = sorted(self,key=sort_algo,reverse=bool(sort and 'reverse' in sort))
|
||||
if show_age:
|
||||
await self.set_dates(
|
||||
self.rpc,
|
||||
[o for o in mmids if hasattr(o,'confs')] )
|
||||
await self.set_dates( [o for o in mmids if hasattr(o,'confs')] )
|
||||
|
||||
def gen_output():
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ from ..addr import MMGenID
|
|||
# mixin class for TwUnspentOutputs,TwAddrList,TwTxHistory:
|
||||
class TwCommon:
|
||||
|
||||
dates_set = False
|
||||
cols = None
|
||||
reverse = False
|
||||
group = False
|
||||
|
|
@ -55,12 +56,21 @@ class TwCommon:
|
|||
'days': lambda rpc,secs: (rpc.cur_date - secs) // 86400 if secs else 0,
|
||||
'date': (
|
||||
lambda rpc,secs: '{}-{:02}-{:02}'.format(*time.gmtime(secs)[:3])[2:]
|
||||
if secs else '--------' ),
|
||||
if secs else '- '),
|
||||
'date_time': (
|
||||
lambda rpc,secs: '{}-{:02}-{:02} {:02}:{:02}'.format(*time.gmtime(secs)[:5])
|
||||
if secs else '---------- -----' ),
|
||||
if secs else '- '),
|
||||
}
|
||||
|
||||
tcols_errmsg = """
|
||||
--columns or MMGEN_COLUMNS value ({}) is too small to display the {}.
|
||||
Minimum value for this configuration: {}
|
||||
"""
|
||||
twid_errmsg = """
|
||||
Screen is too narrow to display the {}
|
||||
Please resize your screen to at least {} characters and hit any key:
|
||||
"""
|
||||
|
||||
def age_disp(self,o,age_fmt):
|
||||
if age_fmt == 'confs':
|
||||
return o.confs
|
||||
|
|
@ -86,14 +96,14 @@ class TwCommon:
|
|||
|
||||
self.do_sort(key=sort_key,reverse=reverse_sort)
|
||||
|
||||
@staticmethod
|
||||
async def set_dates(rpc,us):
|
||||
if us and us[0].date is None:
|
||||
async def set_dates(self,us):
|
||||
if not self.dates_set:
|
||||
# 'blocktime' differs from 'time', is same as getblockheader['time']
|
||||
dates = [ o.get('blocktime',0)
|
||||
for o in await rpc.gathered_icall('gettransaction',[(o.txid,True,False) for o in us]) ]
|
||||
for o in await self.rpc.gathered_icall('gettransaction',[(o.txid,True,False) for o in us]) ]
|
||||
for idx,o in enumerate(us):
|
||||
o.date = dates[idx]
|
||||
self.dates_set = True
|
||||
|
||||
@property
|
||||
def age_w(self):
|
||||
|
|
@ -129,13 +139,9 @@ class TwCommon:
|
|||
return cols
|
||||
if sys.stdout.isatty():
|
||||
if g.columns:
|
||||
die(1,
|
||||
f'\n--columns or MMGEN_COLUMNS value ({g.columns}) is too small to display the {self.desc}.\n'
|
||||
+ f'Minimum value for this configuration: {min_cols}' )
|
||||
die(1,'\n'+fmt(self.tcols_errmsg.format(g.columns,self.desc,min_cols),indent=' '))
|
||||
else:
|
||||
get_char_raw(
|
||||
f'\nScreen is too narrow to display the {self.desc}\n'
|
||||
+ f'Please resize your screen to at least {min_cols} characters and hit any key: ' )
|
||||
get_char_raw('\n'+fmt(self.twid_errmsg.format(self.desc,min_cols),append=''))
|
||||
else:
|
||||
return min_cols
|
||||
|
||||
|
|
@ -175,7 +181,7 @@ class TwCommon:
|
|||
if not cached:
|
||||
data = self.data
|
||||
if self.has_age and self.age_fmt in self.age_fmts_date_dependent:
|
||||
await self.set_dates(self.rpc,data)
|
||||
await self.set_dates(data)
|
||||
|
||||
if not getattr(self,'column_widths',None):
|
||||
self.set_column_params()
|
||||
|
|
@ -202,7 +208,7 @@ class TwCommon:
|
|||
|
||||
async def format_detail(self,color):
|
||||
if self.has_age:
|
||||
await self.set_dates(self.rpc,self.data)
|
||||
await self.set_dates(self.data)
|
||||
|
||||
sep = self.detail_display_separator
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class TwTxHistory(MMGenObject,TwCommon,metaclass=AsyncInit):
|
|||
freew[k] = min( total_freew - sum(freew[k2] for k2 in varcols-{k}), varw[k] )
|
||||
|
||||
self.column_widths = namedtuple('column_params',
|
||||
['col1','txid','addr1','amt','addr2','comment'])(
|
||||
['num','txid','addr1','amt','addr2','comment'])(
|
||||
col1_w,
|
||||
min(
|
||||
# max txid was reduced by txid_adj, so stretch to fill available space, if any
|
||||
|
|
@ -118,14 +118,14 @@ class TwTxHistory(MMGenObject,TwCommon,metaclass=AsyncInit):
|
|||
yield ''
|
||||
|
||||
hdr_fs = self.squeezed_hdr_fs_fs.format(
|
||||
nw = cw.col1,
|
||||
nw = cw.num,
|
||||
dw = self.age_w,
|
||||
txid_fs = f'{{i:{cw.txid}}} ' if self.show_txid else '',
|
||||
aw = cw.addr1,
|
||||
a2w = cw.addr2 )
|
||||
|
||||
fs = self.squeezed_fs_fs.format(
|
||||
nw = cw.col1,
|
||||
nw = cw.num,
|
||||
dw = self.age_w,
|
||||
txid_fs = f'{{i:{cw.txid}}} ' if self.show_txid else '' )
|
||||
|
||||
|
|
@ -206,8 +206,7 @@ class TwTxHistory(MMGenObject,TwCommon,metaclass=AsyncInit):
|
|||
'txid': lambda i: i.txid,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
async def set_dates(rpc,us):
|
||||
async def set_dates(self,us):
|
||||
pass
|
||||
|
||||
@property
|
||||
|
|
|
|||
|
|
@ -126,50 +126,50 @@ class TwUnspentOutputs(MMGenObject,TwCommon,metaclass=AsyncInit):
|
|||
|
||||
self.column_widths = namedtuple(
|
||||
'column_widths',
|
||||
['col1_w','mmid_w','addr_w','btaddr_w','comment_w','tx_w','txdots']
|
||||
)(col1_w, mmid_w, addr_w, btaddr_w, comment_w, tx_w, txdots)
|
||||
['num','mmid','addr','btaddr','comment','tx']
|
||||
)(col1_w, mmid_w, addr_w, btaddr_w, comment_w, tx_w)
|
||||
|
||||
def gen_squeezed_display(self,c,color):
|
||||
fs = self.squeezed_fs_fs.format( cw=c.col1_w, tw=c.tx_w )
|
||||
hdr_fs = self.squeezed_hdr_fs_fs.format( cw=c.col1_w, tw=c.tx_w )
|
||||
def gen_squeezed_display(self,cw,color):
|
||||
fs = self.squeezed_fs_fs.format( cw=cw.num, tw=cw.tx )
|
||||
hdr_fs = self.squeezed_hdr_fs_fs.format( cw=cw.num, tw=cw.tx )
|
||||
yield hdr_fs.format(
|
||||
n = 'Num',
|
||||
t = 'TXid'.ljust(c.tx_w - 2) + ' Vout',
|
||||
a = 'Address'.ljust(c.addr_w),
|
||||
t = 'TXid'.ljust(cw.tx - 2) + ' Vout',
|
||||
a = 'Address'.ljust(cw.addr),
|
||||
A = f'Amt({self.proto.dcoin})'.ljust(self.disp_prec+5),
|
||||
A2 = f' Amt({self.proto.coin})'.ljust(self.disp_prec+4),
|
||||
c = self.age_hdr ).rstrip()
|
||||
|
||||
for n,i in enumerate(self.data):
|
||||
addr_dots = '|' + '.'*(c.addr_w-1)
|
||||
addr_dots = '|' + '.'*(cw.addr-1)
|
||||
mmid_disp = MMGenID.fmtc(
|
||||
(
|
||||
'.'*c.mmid_w if i.skip == 'addr' else
|
||||
'.'*cw.mmid if i.skip == 'addr' else
|
||||
i.twmmid if i.twmmid.type == 'mmgen' else
|
||||
f'Non-{g.proj_name}'
|
||||
),
|
||||
width = c.mmid_w,
|
||||
width = cw.mmid,
|
||||
color = color )
|
||||
|
||||
if self.show_mmid:
|
||||
addr_out = '{} {}{}'.format((
|
||||
type(i.addr).fmtc(addr_dots,width=c.btaddr_w,color=color) if i.skip == 'addr' else
|
||||
i.addr.fmt(width=c.btaddr_w,color=color)
|
||||
type(i.addr).fmtc(addr_dots,width=cw.btaddr,color=color) if i.skip == 'addr' else
|
||||
i.addr.fmt(width=cw.btaddr,color=color)
|
||||
),
|
||||
mmid_disp,
|
||||
(' ' + i.comment.fmt(width=c.comment_w,color=color)) if c.comment_w > 0 else ''
|
||||
(' ' + i.comment.fmt(width=cw.comment,color=color)) if cw.comment > 0 else ''
|
||||
)
|
||||
else:
|
||||
addr_out = (
|
||||
type(i.addr).fmtc(addr_dots,width=c.addr_w,color=color) if i.skip=='addr' else
|
||||
i.addr.fmt(width=c.addr_w,color=color) )
|
||||
type(i.addr).fmtc(addr_dots,width=cw.addr,color=color) if i.skip=='addr' else
|
||||
i.addr.fmt(width=cw.addr,color=color) )
|
||||
|
||||
yield fs.format(
|
||||
n = str(n+1)+')',
|
||||
t = (
|
||||
'' if not i.txid else
|
||||
' ' * (c.tx_w-4) + '|...' if i.skip == 'txid' else
|
||||
i.txid[:c.tx_w-len(c.txdots)] + c.txdots ),
|
||||
' ' * (cw.tx-4) + '|...' if i.skip == 'txid' else
|
||||
i.txid.truncate(width=cw.tx,color=True) ),
|
||||
v = i.vout,
|
||||
a = addr_out,
|
||||
A = i.amt.fmt(color=color,prec=self.disp_prec),
|
||||
|
|
@ -179,8 +179,10 @@ class TwUnspentOutputs(MMGenObject,TwCommon,metaclass=AsyncInit):
|
|||
|
||||
def gen_detail_display(self,color):
|
||||
|
||||
addr_w = max(len(i.addr) for i in self.data)
|
||||
mmid_w = max(len(('',i.twmmid)[i.twmmid.type=='mmgen']) for i in self.data) or 12 # DEADBEEF:S:1
|
||||
data = self.data
|
||||
|
||||
addr_w = max(len(i.addr) for i in data)
|
||||
mmid_w = max(len(('',i.twmmid)[i.twmmid.type=='mmgen']) for i in data) or 12 # DEADBEEF:S:1
|
||||
|
||||
fs = self.wide_fs_fs.format(
|
||||
tw = self.txid_w + 3,
|
||||
|
|
@ -199,9 +201,9 @@ class TwUnspentOutputs(MMGenObject,TwCommon,metaclass=AsyncInit):
|
|||
D = 'Date',
|
||||
l = 'Label' )
|
||||
|
||||
max_comment_len = max([len(i.comment) for i in self.data if i.comment] or [2])
|
||||
max_comment_len = max([len(i.comment) for i in data if i.comment] or [2])
|
||||
|
||||
for n,i in enumerate(self.data):
|
||||
for n,i in enumerate(data):
|
||||
yield fs.format(
|
||||
n = str(n+1) + ')',
|
||||
t = '{},{}'.format(
|
||||
|
|
|
|||
|
|
@ -144,9 +144,9 @@ def pp_fmt(d):
|
|||
def pp_msg(d):
|
||||
msg(pp_fmt(d))
|
||||
|
||||
def fmt(s,indent='',strip_char=None):
|
||||
def fmt(s,indent='',strip_char=None,append='\n'):
|
||||
"de-indent multiple lines of text, or indent with specified string"
|
||||
return indent + ('\n'+indent).join([l.strip(strip_char) for l in s.strip().splitlines()]) + '\n'
|
||||
return indent + ('\n'+indent).join([l.strip(strip_char) for l in s.strip().splitlines()]) + append
|
||||
|
||||
def fmt_list(iterable,fmt='dfl',indent=''):
|
||||
"pretty-format a list"
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ if overlay_fake_os.getenv('MMGEN_BOGUS_UNSPENT_DATA'):
|
|||
|
||||
class overlay_fake_data2:
|
||||
|
||||
async def set_dates(foo,rpc,us):
|
||||
async def set_dates(foo,us):
|
||||
for o in us:
|
||||
o.date = 1831006505 - int(9.7 * 60 * (o.confs - 1))
|
||||
|
||||
|
|
|
|||
|
|
@ -605,7 +605,7 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
|
|||
t.read()
|
||||
return t
|
||||
|
||||
def txsign(self,ni=False,ext='{}.regtest.rawtx',add_args=[]):
|
||||
def txsign(self,ni=False,ext='{}.regtest.rawtx',add_args=[],dev_send=False):
|
||||
ext = ext.format('-α' if g.debug_utf8 else '')
|
||||
keyfile = joinpath(self.tmpdir,parity_devkey_fn)
|
||||
txfile = self.get_file_with_ext(ext,no_dot=True)
|
||||
|
|
@ -616,7 +616,8 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
|
|||
+ ['--rpc-host=bad_host'] # ETH signing must work without RPC
|
||||
+ add_args
|
||||
+ ([],['--yes'])[ni]
|
||||
+ ['-k', keyfile, txfile, dfl_words_file] )
|
||||
+ ([f'--keys-from-file={keyfile}'] if dev_send else [])
|
||||
+ [txfile, dfl_words_file] )
|
||||
return self.txsign_ui_common(t,ni=ni,has_label=True)
|
||||
|
||||
def txsend(self,ni=False,ext='{}.regtest.sigtx',add_args=[]):
|
||||
|
|
@ -662,10 +663,10 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
|
|||
return self.txcreate(args=args,menu=menu,acct='1',tweaks=['confirm_non_mmgen'])
|
||||
def txview1_raw(self):
|
||||
return self.txview(ext_fs='{}.regtest.rawtx')
|
||||
def txsign1(self): return self.txsign(add_args=['--use-internal-keccak-module'])
|
||||
def txsign1(self): return self.txsign(add_args=['--use-internal-keccak-module'],dev_send=True)
|
||||
def tx_status0_bad(self):
|
||||
return self.tx_status(ext='{}.regtest.sigtx',expect_str='neither in mempool nor blockchain',exit_val=1)
|
||||
def txsign1_ni(self): return self.txsign(ni=True)
|
||||
def txsign1_ni(self): return self.txsign(ni=True,dev_send=True)
|
||||
def txsend1(self): return self.txsend()
|
||||
def txview1_sig(self): # do after send so that TxID is displayed
|
||||
return self.txview(ext_fs='{}.regtest.sigtx')
|
||||
|
|
@ -674,14 +675,14 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
|
|||
def txcreate2(self):
|
||||
args = ['98831F3A:E:11,1.234']
|
||||
return self.txcreate(args=args,acct='10',tweaks=['confirm_non_mmgen'])
|
||||
def txsign2(self): return self.txsign(ni=True,ext='1.234,50000]{}.regtest.rawtx')
|
||||
def txsign2(self): return self.txsign(ni=True,ext='1.234,50000]{}.regtest.rawtx',dev_send=True)
|
||||
def txsend2(self): return self.txsend(ext='1.234,50000]{}.regtest.sigtx')
|
||||
def bal2(self): return self.bal(n='2')
|
||||
|
||||
def txcreate3(self):
|
||||
args = ['98831F3A:E:21,2.345']
|
||||
return self.txcreate(args=args,acct='10',tweaks=['confirm_non_mmgen'])
|
||||
def txsign3(self): return self.txsign(ni=True,ext='2.345,50000]{}.regtest.rawtx')
|
||||
def txsign3(self): return self.txsign(ni=True,ext='2.345,50000]{}.regtest.rawtx',dev_send=True)
|
||||
def txsend3(self): return self.txsend(ext='2.345,50000]{}.regtest.sigtx')
|
||||
def bal3(self): return self.bal(n='3')
|
||||
|
||||
|
|
@ -797,14 +798,14 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
|
|||
t.expect('or gas price: ',fee+'\n')
|
||||
return t
|
||||
|
||||
def txsign4(self): return self.txsign(ni=True,ext='.45495,50000]{}.regtest.rawtx')
|
||||
def txsign4(self): return self.txsign(ni=True,ext='.45495,50000]{}.regtest.rawtx',dev_send=True)
|
||||
def txsend4(self): return self.txsend(ext='.45495,50000]{}.regtest.sigtx')
|
||||
def bal4(self): return self.bal(n='4')
|
||||
|
||||
def txcreate5(self):
|
||||
args = [burn_addr + ','+amt1]
|
||||
return self.txcreate(args=args,acct='10',tweaks=['confirm_non_mmgen'])
|
||||
def txsign5(self): return self.txsign(ni=True,ext=amt1+',50000]{}.regtest.rawtx')
|
||||
def txsign5(self): return self.txsign(ni=True,ext=amt1+',50000]{}.regtest.rawtx',dev_send=True)
|
||||
def txsend5(self): return self.txsend(ext=amt1+',50000]{}.regtest.sigtx')
|
||||
def bal5(self): return self.bal(n='5')
|
||||
|
||||
|
|
|
|||
|
|
@ -1367,7 +1367,9 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
|
|||
def bob_msgverify_export_single(self):
|
||||
sid = self._user_sid('bob')
|
||||
mmid = f'{sid}:{self.dfl_mmtype}:1'
|
||||
t = self.spawn('mmgen-tool', [ '--bob', '--color=0', 'listaddress', mmid ], no_msg=True)
|
||||
args = [ '--bob', '--color=0', 'listaddress', mmid ]
|
||||
imsg(f'Running mmgen-tool {fmt_list(args,fmt="bare")}')
|
||||
t = self.spawn('mmgen-tool', args, no_msg=True)
|
||||
addr = t.expect_getend(mmid).split()[0]
|
||||
t.close()
|
||||
return self.bob_msgverify(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue