From 03712efbfb86ed0eb5538b2e2b875989893ff0e4 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Fri, 11 Nov 2022 09:48:57 +0000 Subject: [PATCH] tracking wallet classes: various cleanups --- mmgen/obj.py | 8 +-- mmgen/proto/btc/tw/addresses.py | 8 +-- mmgen/proto/btc/tw/txhistory.py | 8 +-- mmgen/proto/eth/tw/addresses.py | 10 ++-- mmgen/proto/eth/tw/common.py | 21 +++++++- mmgen/proto/eth/tw/ctl.py | 2 +- mmgen/proto/eth/tw/unspent.py | 4 -- mmgen/tw/addresses.py | 53 +++++++++---------- mmgen/tw/common.py | 11 ++-- mmgen/tw/txhistory.py | 93 ++++++++++++++++----------------- mmgen/tw/unspent.py | 16 ++++-- mmgen/tx/base.py | 13 ++++- 12 files changed, 139 insertions(+), 108 deletions(-) diff --git a/mmgen/obj.py b/mmgen/obj.py index db67531f..fd75dfe8 100755 --- a/mmgen/obj.py +++ b/mmgen/obj.py @@ -273,12 +273,12 @@ class Int(int,Hilite,InitErrors): return cls.init_fail(e,n) @classmethod - def fmtc(cls,*args,**kwargs): - cls.method_not_implemented() + def fmtc(cls,n,*args,**kwargs): + return super().fmtc(str(n),*args,**kwargs) @classmethod - def colorize(cls,n,**kwargs): - return super().colorize(repr(n),**kwargs) + def colorize(cls,n,*args,**kwargs): + return super().colorize(str(n),*args,**kwargs) class NonNegativeInt(Int): min_val = 0 diff --git a/mmgen/proto/btc/tw/addresses.py b/mmgen/proto/btc/tw/addresses.py index b5f5e5e6..304692c3 100755 --- a/mmgen/proto/btc/tw/addresses.py +++ b/mmgen/proto/btc/tw/addresses.py @@ -45,10 +45,10 @@ Actions: [q]uit, r[e]draw, add [l]abel: 'p':'a_print_detail', 'l':'a_comment_add' } - squeezed_fs_fs = ' {{n:>{nw}}} {{m:}} {{u:}}%s {{c:}} {{b:}} {{d:}}' - squeezed_hdr_fs_fs = ' {{n:>{nw}}} {{m:{mw}}} {{u:{uw}}}%s {{c:{cw}}} {{b:{bw}}} {{d:}}' - wide_fs_fs = ' {{n:>{nw}}} {{m:}} {{u:}} {{a:}} {{c:}} {{b:}} {{B:<{Bw}}} {{d:}}' - wide_hdr_fs_fs = ' {{n:>{nw}}} {{m:{mw}}} {{u:{uw}}} {{a:{aw}}} {{c:{cw}}} {{b:{bw}}} {{B:{Bw}}} {{d:}}' + squeezed_fs_fs = ' {{n:>{nw}}} {{m}} {{u}}%s {{c}} {{A}} {{d}}' + squeezed_hdr_fs_fs = ' {{n:>{nw}}} {{m:{mw}}} {{u:{uw}}}%s {{c:{cw}}} {{A:{Aw}}} {{d}}' + wide_fs_fs = ' {{n:>{nw}}} {{m}} {{u}} {{a}} {{c}} {{A}} {{b:<{bw}}} {{D}}' + wide_hdr_fs_fs = ' {{n:>{nw}}} {{m:{mw}}} {{u:{uw}}} {{a:{aw}}} {{c:{cw}}} {{A:{Aw}}} {{b:{bw}}} {{D}}' async def get_rpc_data(self): diff --git a/mmgen/proto/btc/tw/txhistory.py b/mmgen/proto/btc/tw/txhistory.py index bafd27e1..a9f9383e 100755 --- a/mmgen/proto/btc/tw/txhistory.py +++ b/mmgen/proto/btc/tw/txhistory.py @@ -129,11 +129,11 @@ class BitcoinTwTransaction(BitcoinTwCommon): def age_disp(self,age_fmt,width,color): if age_fmt == 'confs': - ret_str = str(self.confirmations).rjust(width) + ret_str = str(self.confirmations).ljust(width) return gray(ret_str) if self.confirmations < 0 and color else ret_str elif age_fmt == 'block': ret = (self.rpc.blockcount - (abs(self.confirmations) - 1)) * (-1 if self.confirmations < 0 else 1) - ret_str = str(ret).rjust(width) + ret_str = str(ret).ljust(width) return gray(ret_str) if ret < 0 and color else ret_str else: return self.parent.date_formatter[age_fmt](self.rpc,self.tx.get('blocktime',0)) @@ -253,8 +253,8 @@ Actions: [q]uit, r[e]draw: 'p':'a_print_squeezed', 'P':'a_print_detail' } - squeezed_fs_fs = ' {{n:>{nw}}} {{d:>{dw}}} {txid_fs}{{a1}} {{A}} {{a2}} {{l}}' - squeezed_hdr_fs_fs = ' {{n:>{nw}}} {{d:{dw}}} {txid_fs}{{a1:{aw}}} {{A}} {{a2:{a2w}}} {{l}}' + squeezed_fs_fs = ' {{n:>{nw}}} {{d:>{dw}}} {txid_fs}{{i}} {{A}} {{o}} {{c}}' + squeezed_hdr_fs_fs = ' {{n:>{nw}}} {{d:{dw}}} {txid_fs}{{i:{iw}}} {{A}} {{o:{ow}}} {{c}}' async def get_rpc_data(self): blockhash = ( diff --git a/mmgen/proto/eth/tw/addresses.py b/mmgen/proto/eth/tw/addresses.py index 1921a9b1..761ea8f7 100755 --- a/mmgen/proto/eth/tw/addresses.py +++ b/mmgen/proto/eth/tw/addresses.py @@ -17,7 +17,7 @@ from ....tw.ctl import TrackingWallet from ....addr import CoinAddr from .common import EthereumTwCommon -class EthereumTwAddresses(TwAddresses,EthereumTwCommon): +class EthereumTwAddresses(EthereumTwCommon,TwAddresses): has_age = False prompt = """ @@ -40,10 +40,10 @@ Actions: [q]uit, r[e]draw, [D]elete address, add [l]abel: 'w':'a_view_detail', 'p':'a_print_detail' } - squeezed_fs_fs = ' {{n:>{nw}}} {{m:}}%s {{c:}} {{b:}}' - squeezed_hdr_fs_fs = ' {{n:>{nw}}} {{m:{mw}}}%s {{c:{cw}}} {{b:{bw}}}' - wide_fs_fs = ' {{n:>{nw}}} {{m:}} {{a:}} {{c:}} {{b:}}' - wide_hdr_fs_fs = ' {{n:>{nw}}} {{m:{mw}}} {{a:{aw}}} {{c:{cw}}} {{b:{bw}}}' + squeezed_fs_fs = ' {{n:>{nw}}} {{m:}}%s {{c:}} {{A:}}' + squeezed_hdr_fs_fs = ' {{n:>{nw}}} {{m:{mw}}}%s {{c:{cw}}} {{A:{Aw}}}' + wide_fs_fs = ' {{n:>{nw}}} {{m:}} {{a:}} {{c:}} {{A:}}' + wide_hdr_fs_fs = ' {{n:>{nw}}} {{m:{mw}}} {{a:{aw}}} {{c:{cw}}} {{A:{Aw}}}' async def get_rpc_data(self): diff --git a/mmgen/proto/eth/tw/common.py b/mmgen/proto/eth/tw/common.py index 799c8da5..acb41d74 100755 --- a/mmgen/proto/eth/tw/common.py +++ b/mmgen/proto/eth/tw/common.py @@ -11,12 +11,29 @@ """ proto.eth.tw.common: Ethereum base protocol tracking wallet dependency classes """ - +from ....globalvars import g from ....tw.ctl import TrackingWallet +from ....tw.common import TwCommon from ....addr import CoinAddr from ....tw.common import TwLabel -class EthereumTwCommon: +class EthereumTwCommon(TwCommon): + + def age_disp(self,o,age_fmt): # TODO + pass + + def get_disp_prec(self,wide): + return self.proto.coin_amt.max_prec if wide else 8 + + def subheader(self,color): + ret = '' + if self.disp_prec == 8: + ret += 'Balances truncated to 8 decimal points\n' + if g.cached_balances: + from ....color import nocolor,yellow + ret += (nocolor,yellow)[color]( + 'WARNING: Using cached balances. These may be out of date!') + '\n' + return ret async def get_addr_label_pairs(self,twmmid=None): wallet = ( diff --git a/mmgen/proto/eth/tw/ctl.py b/mmgen/proto/eth/tw/ctl.py index 406e67c1..5c434ca5 100755 --- a/mmgen/proto/eth/tw/ctl.py +++ b/mmgen/proto/eth/tw/ctl.py @@ -27,7 +27,7 @@ from ....amt import ETHAmt from ..contract import Token,TokenResolve from .common import EthereumTwCommon -class EthereumTrackingWallet(TrackingWallet,EthereumTwCommon): +class EthereumTrackingWallet(EthereumTwCommon,TrackingWallet): caps = ('batch',) data_key = 'accounts' diff --git a/mmgen/proto/eth/tw/unspent.py b/mmgen/proto/eth/tw/unspent.py index 14cb0683..e71358c3 100755 --- a/mmgen/proto/eth/tw/unspent.py +++ b/mmgen/proto/eth/tw/unspent.py @@ -100,10 +100,6 @@ class EthereumTokenTwUnspentOutputs(EthereumTwUnspentOutputs): await super().__init__(proto,*args,**kwargs) self.proto.tokensym = self.wallet.symbol - @property - def disp_prec(self): - return 10 # truncate precision for narrow display - async def get_data(self,*args,**kwargs): await super().get_data(*args,**kwargs) for e in self.data: diff --git a/mmgen/tw/addresses.py b/mmgen/tw/addresses.py index 7915d247..f7f52220 100755 --- a/mmgen/tw/addresses.py +++ b/mmgen/tw/addresses.py @@ -12,12 +12,10 @@ tw.addresses: Tracking wallet listaddresses class for the MMGen suite """ -from collections import namedtuple - from ..util import suf from ..base_obj import AsyncInit from ..objmethods import MMGenObject -from ..obj import MMGenList,MMGenListItem,ImmutableAttr,ListItemAttr,TwComment,NonNegativeInt +from ..obj import MMGenListItem,ImmutableAttr,ListItemAttr,TwComment,NonNegativeInt from ..rpc import rpc_init from ..addr import CoinAddr,MMGenID from ..color import red,green @@ -30,7 +28,6 @@ class TwAddresses(MMGenObject,TwCommon,metaclass=AsyncInit): item_desc = 'address' txid_w = 64 sort_key = 'twmmid' - age_fmts_interactive = ('confs','block','days','date','date_time') update_widths_on_age_toggle = True print_output_types = ('detail',) filters = ('showempty','showused','all_labels') @@ -133,15 +130,17 @@ class TwAddresses(MMGenObject,TwCommon,metaclass=AsyncInit): 'mmid': max(len(d.twmmid.disp) for d in data), 'used': 4, 'amt': self.disp_prec + 5, - 'date': self.age_w, + 'date': self.age_w if self.has_age else 0, + 'block': self.age_col_params['block'][0] if wide and self.has_age else 0, + 'date_time': self.age_col_params['date_time'][0] if wide and self.has_age else 0, 'spc': 7, # 6 spaces between cols + 1 leading space in fs }, maxws = { # expandable cols - 'addr': max(len(d.addr) for d in data), + 'addr': max(len(d.addr) for d in data) if self.showcoinaddrs else 0, 'comment': max(d.comment.screen_width for d in data), }, minws = { - 'addr': 12, + 'addr': 12 if self.showcoinaddrs else 0, 'comment': len('Comment'), }, maxws_nice = {'addr': 18}, @@ -162,12 +161,12 @@ class TwAddresses(MMGenObject,TwCommon,metaclass=AsyncInit): 'uw': cw.used, 'aw': cw.addr, 'cw': cw.comment, - 'bw': cw.amt, + 'Aw': cw.amt, 'dw': cw.date } hdr_fs = (self.squeezed_hdr_fs_fs % ('',' {{a:{aw}}}')[self.showcoinaddrs]).format(**fs_parms) - fs = (self.squeezed_fs_fs % ('',' {{a:}}')[self.showcoinaddrs]).format(**fs_parms) + fs = (self.squeezed_fs_fs % ('',' {{a}}')[self.showcoinaddrs]).format(**fs_parms) yield hdr_fs.format( n = '', @@ -175,7 +174,7 @@ class TwAddresses(MMGenObject,TwCommon,metaclass=AsyncInit): u = 'Used', a = 'Address', c = 'Comment', - b = 'Balance', + A = 'Balance', d = self.age_hdr ) yes,no = (red('Yes '),green('No ')) if color else ('Yes ','No ') @@ -187,11 +186,11 @@ class TwAddresses(MMGenObject,TwCommon,metaclass=AsyncInit): yield '' yield fs.format( n = str(n) + ')', - m = MMGenID.fmtc(d.twmmid.disp,width=cw.mmid,color=True), + m = d.twmmid.fmt(width=cw.mmid,color=color), u = yes if d.recvd else no, - a = d.addr.fmt(color=True,width=cw.addr), - c = d.comment.fmt(width=cw.comment,color=True,nullrepl='-'), - b = d.amt.fmt(color=True), + a = d.addr.fmt(color=color,width=cw.addr), + c = d.comment.fmt(width=cw.comment,color=color,nullrepl='-'), + A = d.amt.fmt(color=color,prec=self.disp_prec), d = self.age_disp( d, self.age_fmt ) ) @@ -203,9 +202,9 @@ class TwAddresses(MMGenObject,TwCommon,metaclass=AsyncInit): 'uw': cw.used, 'aw': cw.addr, 'cw': cw.comment, - 'bw': cw.amt, - 'Bw': self.age_col_params['block'][0], - 'dw': self.age_col_params['date_time'][0], + 'Aw': cw.amt, + 'bw': self.age_col_params['block'][0], + 'Dw': self.age_col_params['date_time'][0], } hdr_fs = self.wide_hdr_fs_fs.format(**fs_parms) @@ -217,9 +216,9 @@ class TwAddresses(MMGenObject,TwCommon,metaclass=AsyncInit): u = 'Used', a = 'Address', c = 'Comment', - b = 'Balance', - B = 'Block', - d = 'Date' ) + A = 'Balance', + b = 'Block', + D = 'Date/Time' ).rstrip() yes,no = (red('Yes '),green('No ')) if color else ('Yes ','No ') id_save = data[0].al_id @@ -230,14 +229,14 @@ class TwAddresses(MMGenObject,TwCommon,metaclass=AsyncInit): yield '' yield fs.format( n = str(n) + ')', - m = MMGenID.fmtc(d.twmmid.disp,width=fs_parms['mw'],color=color), + m = d.twmmid.fmt(width=cw.mmid,color=color), u = yes if d.recvd else no, - a = d.addr.fmt(color=color,width=fs_parms['aw']), - c = d.comment.fmt(width=fs_parms['cw'],color=color,nullrepl='-'), - b = d.amt.fmt(color=color), - B = self.age_disp( d, 'block' ), - d = self.age_disp( d, 'date_time' ), - ) + a = d.addr.fmt(color=color,width=cw.addr), + c = d.comment.fmt(width=cw.comment,color=color,nullrepl='-'), + A = d.amt.fmt(color=color,prec=self.disp_prec), + b = self.age_disp( d, 'block' ), + D = self.age_disp( d, 'date_time' ), + ).rstrip() async def set_dates(self,addrs): if not self.dates_set: diff --git a/mmgen/tw/common.py b/mmgen/tw/common.py index 4b366d03..43a0866e 100755 --- a/mmgen/tw/common.py +++ b/mmgen/tw/common.py @@ -44,7 +44,7 @@ class TwCommon: age_fmts = ('confs','block','days','date','date_time') age_fmts_date_dependent = ('days','date','date_time') - age_fmts_interactive = ('confs','block','days','date') + age_fmts_interactive = ('confs','block','days','date','date_time') _age_fmt = 'confs' age_col_params = { @@ -138,8 +138,7 @@ class TwCommon: f'{val!r}: invalid age format for {op_desc} operation (must be one of {ok_vals!r})' ) self._age_fmt = val - @property - def disp_prec(self): + def get_disp_prec(self,wide): return self.proto.coin_amt.max_prec def get_term_columns(self,min_cols): @@ -277,6 +276,8 @@ class TwCommon: dt = getattr(self.display_type,display_type) + self.disp_prec = self.get_disp_prec(wide=dt.detail) + if self.has_age and (self.age_fmt in self.age_fmts_date_dependent or dt.detail): await self.set_dates(self.data) @@ -509,6 +510,10 @@ class TwMMGenID(str,Hilite,InitErrors,MMGenObject): me.proto = proto return me + @classmethod + def fmtc(cls,twmmid,*args,**kwargs): + return super().fmtc(twmmid.disp,*args,**kwargs) + # non-displaying container for TwMMGenID,TwComment class TwLabel(str,InitErrors,MMGenObject): exc = 'BadTwLabel' diff --git a/mmgen/tw/txhistory.py b/mmgen/tw/txhistory.py index eac5df59..27188e87 100755 --- a/mmgen/tw/txhistory.py +++ b/mmgen/tw/txhistory.py @@ -36,7 +36,6 @@ class TwTxHistory(MMGenObject,TwCommon,metaclass=AsyncInit): show_txid = False show_unconfirmed = False show_total_amt = False - age_fmts_interactive = ('confs','block','days','date','date_time') update_widths_on_age_toggle = True print_output_types = ('squeezed','detail') filters = ('show_unconfirmed',) @@ -56,18 +55,18 @@ class TwTxHistory(MMGenObject,TwCommon,metaclass=AsyncInit): def get_column_widths(self,data,wide=False): - # var cols: addr1 addr2 comment [txid] + # var cols: inputs outputs comment [txid] if not hasattr(self,'varcol_maxwidths'): self.varcol_maxwidths = { - 'addr1': max(len(d.vouts_disp('inputs',width=None,color=False)) for d in data), - 'addr2': max(len(d.vouts_disp('outputs',width=None,color=False)) for d in data), + 'inputs': max(len(d.vouts_disp('inputs',width=None,color=False)) for d in data), + 'outputs': max(len(d.vouts_disp('outputs',width=None,color=False)) for d in data), 'comment': max(len(d.comment) for d in data), } maxws = self.varcol_maxwidths.copy() minws = { - 'addr1': 15, - 'addr2': 15, + 'inputs': 15, + 'outputs': 15, 'comment': len('Comment'), } if self.show_txid: @@ -75,11 +74,13 @@ class TwTxHistory(MMGenObject,TwCommon,metaclass=AsyncInit): minws['txid'] = 8 maxws_nice = {'txid': 20} else: + maxws['txid'] = 0 + minws['txid'] = 0 maxws_nice = {} widths = { # fixed cols 'num': max(2,len(str(len(data)))+1), - 'age': self.age_w, + 'date': self.age_w, 'amt': self.disp_prec + 5, 'spc': 6 + self.show_txid, # 5(6) spaces between cols + 1 leading space in fs } @@ -92,8 +93,8 @@ class TwTxHistory(MMGenObject,TwCommon,metaclass=AsyncInit): yield f'Displaying transactions since block {self.sinceblock.hl(color=color)}' yield 'Only wallet-related outputs are shown' yield 'Comment is from first wallet address in outputs or inputs' - if (cw.addr1 < self.varcol_maxwidths['addr1'] or - cw.addr2 < self.varcol_maxwidths['addr2'] ): + if (cw.inputs < self.varcol_maxwidths['inputs'] or + cw.outputs < self.varcol_maxwidths['outputs'] ): yield 'Due to screen width limitations, not all addresses could be displayed' yield '' @@ -101,8 +102,8 @@ class TwTxHistory(MMGenObject,TwCommon,metaclass=AsyncInit): nw = cw.num, dw = self.age_w, txid_fs = f'{{i:{cw.txid}}} ' if self.show_txid else '', - aw = cw.addr1, - a2w = cw.addr2 ) + iw = cw.inputs, + ow = cw.outputs ) fs = self.squeezed_fs_fs.format( nw = cw.num, @@ -110,58 +111,56 @@ class TwTxHistory(MMGenObject,TwCommon,metaclass=AsyncInit): txid_fs = f'{{i:{cw.txid}}} ' if self.show_txid else '' ) yield hdr_fs.format( - n = '', - i = 'TxID', - d = self.age_hdr, - a1 = 'Inputs', - A = 'Amt({})'.format('TX' if self.show_total_amt else 'Wallet').ljust(cw.amt), - a2 = 'Outputs', - l = 'Comment' ).rstrip() + n = '', + t = 'TxID', + d = self.age_hdr, + i = 'Inputs', + A = 'Amt({})'.format('TX' if self.show_total_amt else 'Wallet'), + o = 'Outputs', + c = 'Comment' ).rstrip() for n,d in enumerate(data,1): yield fs.format( - n = str(n) + ')', - i = d.txid_disp( width=cw.txid, color=color ) if hasattr(cw,'txid') else None, - d = d.age_disp( self.age_fmt, width=self.age_w, color=color ), - a1 = d.vouts_disp( 'inputs', width=cw.addr1, color=color ), - A = d.amt_disp(self.show_total_amt).fmt( prec=self.disp_prec, color=color ), - a2 = d.vouts_disp( 'outputs', width=cw.addr2, color=color ), - l = d.comment.fmt( width=cw.comment, color=color ) ).rstrip() + n = str(n) + ')', + t = d.txid_disp( width=cw.txid, color=color ) if hasattr(cw,'txid') else None, + d = d.age_disp( self.age_fmt, width=self.age_w, color=color ), + i = d.vouts_disp( 'inputs', width=cw.inputs, color=color ), + A = d.amt_disp(self.show_total_amt).fmt( prec=self.disp_prec, color=color ), + o = d.vouts_disp( 'outputs', width=cw.outputs, color=color ), + c = d.comment.fmt( width=cw.comment, color=color ) ).rstrip() def gen_detail_display(self,data,cw,color): - yield ( - (f'Displaying transactions since block {self.sinceblock.hl(color=color)}\n' - if self.sinceblock else '') - + 'Only wallet-related outputs are shown' - ) + if self.sinceblock: + yield f'Displaying transactions since block {self.sinceblock.hl(color=color)}' + yield 'Only wallet-related outputs are shown' fs = fmt(""" {n} Block: [{d}] {b} - TxID: [{D}] {i} - Value: {A1} - Wallet Value: {A2} + TxID: [{D}] {t} + Value: {A} + Wallet Value: {B} Fee: {f} Inputs: - {a1} - Outputs ({oc}): - {a2} + {i} + Outputs ({N}): + {o} """,strip_char='\t').strip() for n,d in enumerate(data,1): yield fs.format( - n = str(n) + ')', - d = d.age_disp( 'date_time', width=None, color=None ), - b = d.blockheight_disp(color=color), - D = d.txdate_disp( 'date_time' ), - i = d.txid_disp( width=None, color=color ), - A1 = d.amt_disp(True).hl( color=color ), - A2 = d.amt_disp(False).hl( color=color ), - f = d.fee_disp( color=color ), - a1 = d.vouts_list_disp( 'inputs', color=color, indent=' '*8 ), - oc = d.nOutputs, - a2 = d.vouts_list_disp( 'outputs', color=color, indent=' '*8 ), + n = str(n) + ')', + d = d.age_disp( 'date_time', width=None, color=None ), + b = d.blockheight_disp(color=color), + D = d.txdate_disp( 'date_time' ), + t = d.txid_disp( width=None, color=color ), + A = d.amt_disp(True).hl( color=color ), + B = d.amt_disp(False).hl( color=color ), + f = d.fee_disp( color=color ), + i = d.vouts_list_disp( 'inputs', color=color, indent=' '*8 ), + N = d.nOutputs, + o = d.vouts_list_disp( 'outputs', color=color, indent=' '*8 ), ) sort_disp = { diff --git a/mmgen/tw/unspent.py b/mmgen/tw/unspent.py index 220d6131..df2515cc 100755 --- a/mmgen/tw/unspent.py +++ b/mmgen/tw/unspent.py @@ -20,15 +20,21 @@ twuo: Tracking wallet unspent outputs class for the MMGen suite """ -import asyncio from collections import namedtuple from ..globalvars import g -from ..color import red,yellow -from ..util import msg,die,capfirst,suf,fmt +from ..util import msg,suf,fmt from ..base_obj import AsyncInit from ..objmethods import MMGenObject -from ..obj import ImmutableAttr,ListItemAttr,MMGenListItem,TwComment,get_obj,HexStr,CoinTxID,MMGenList +from ..obj import ( + ImmutableAttr, + ListItemAttr, + MMGenListItem, + TwComment, + get_obj, + HexStr, + CoinTxID, + NonNegativeInt ) from ..addr import CoinAddr,MMGenID from ..rpc import rpc_init from .common import TwCommon,TwMMGenID,get_tw_label @@ -48,7 +54,7 @@ class TwUnspentOutputs(MMGenObject,TwCommon,metaclass=AsyncInit): class MMGenTwUnspentOutput(MMGenListItem): txid = ListItemAttr(CoinTxID) - vout = ListItemAttr(int,typeconv=False) + vout = ListItemAttr(NonNegativeInt) amt = ImmutableAttr(None) amt2 = ListItemAttr(None) # the ETH balance for token account comment = ListItemAttr(TwComment,reassign_ok=True) diff --git a/mmgen/tx/base.py b/mmgen/tx/base.py index 25b327fc..28eeabca 100755 --- a/mmgen/tx/base.py +++ b/mmgen/tx/base.py @@ -14,13 +14,22 @@ tx.base: base transaction class from ..globalvars import * from ..objmethods import MMGenObject -from ..obj import ImmutableAttr,ListItemAttr,MMGenListItem,MMGenTxComment,TwComment,CoinTxID,HexStr +from ..obj import ( + ImmutableAttr, + ListItemAttr, + MMGenListItem, + MMGenTxComment, + TwComment, + CoinTxID, + HexStr, + NonNegativeInt +) from ..addr import MMGenID,CoinAddr from ..util import msg,ymsg,fmt,remove_dups,make_timestamp,die from ..opts import opt class MMGenTxIO(MMGenListItem): - vout = ListItemAttr(int,typeconv=False) + vout = ListItemAttr(NonNegativeInt) amt = ImmutableAttr(None) comment = ListItemAttr(TwComment,reassign_ok=True) mmid = ListItemAttr(MMGenID,include_proto=True)