From 795b5d8b62556bf76366da2b92ac9d23f5200845 Mon Sep 17 00:00:00 2001 From: MMGen Date: Sat, 26 May 2018 11:19:17 +0000 Subject: [PATCH] *TrackingWallet refactor MMGenTrackingWallet now split into: - TwUnspentOutputs, for unspent outputs display - TrackingWallet, for label and other operations EthereumTrackingWallet is now subclassed from TrackingWallet --- mmgen/altcoins/eth/tw.py | 16 ++--- mmgen/tool.py | 11 +-- mmgen/tw.py | 143 ++++++++++++++++++++------------------- mmgen/tx.py | 4 +- 4 files changed, 87 insertions(+), 87 deletions(-) diff --git a/mmgen/altcoins/eth/tw.py b/mmgen/altcoins/eth/tw.py index 82660a11..3c209a68 100755 --- a/mmgen/altcoins/eth/tw.py +++ b/mmgen/altcoins/eth/tw.py @@ -20,12 +20,14 @@ altcoins.eth.tw: ETH tracking wallet functions and methods for the MMGen suite """ +import json from mmgen.common import * from mmgen.obj import * -import json +from mmgen.tw import TrackingWallet,TwAddrList +from mmgen.addr import AddrData # No file locking - 2 processes accessing the wallet at the same time will corrupt it -class EthereumTrackingWallet(object): +class EthereumTrackingWallet(TrackingWallet): data_dir = os.path.join(g.altcoin_data_dir,'eth') tw_file = os.path.join(data_dir,'tracking-wallet.json') @@ -89,19 +91,16 @@ class EthereumTrackingWallet(object): from collections import OrderedDict return OrderedDict(map(lambda x: (x['mmid'],{'addr':x['addr'],'comment':x['comment']}), self.sorted_list())) - @classmethod - def import_label(cls,coinaddr,lbl): - tw = cls() - for addr,d in tw.data.items(): + def import_label(self,coinaddr,lbl): + for addr,d in self.data.items(): if addr == coinaddr: d['comment'] = lbl.comment - tw.write() + self.write() return None else: # emulate RPC library return ('rpcfail',(None,2,"Address '{}' not found in tracking wallet".format(coinaddr))) -from mmgen.tw import TwAddrList class EthereumTwAddrList(TwAddrList): def __init__(self,usr_addr_list,minconf,showempty,showbtcaddrs,all_labels): @@ -126,7 +125,6 @@ class EthereumTwAddrList(TwAddrList): self[label.mmid]['amt'] += bal self.total += bal -from mmgen.addr import AddrData class EthereumAddrData(AddrData): @classmethod diff --git a/mmgen/tool.py b/mmgen/tool.py index 2a0bbe40..f950ba1e 100755 --- a/mmgen/tool.py +++ b/mmgen/tool.py @@ -713,8 +713,8 @@ def Txview(*infiles,**kwargs): def Twview(pager=False,reverse=False,wide=False,minconf=1,sort='age',show_days=True,show_mmid=True): rpc_init() - from mmgen.tw import MMGenTrackingWallet - tw = MMGenTrackingWallet(minconf=minconf) + from mmgen.tw import TwUnspentOutputs + tw = TwUnspentOutputs(minconf=minconf) tw.do_sort(sort,reverse=reverse) tw.show_days = show_days tw.show_mmid = show_mmid @@ -723,7 +723,8 @@ def Twview(pager=False,reverse=False,wide=False,minconf=1,sort='age',show_days=T def Add_label(mmaddr_or_coin_addr,label): rpc_init() - from mmgen.tw import MMGenTrackingWallet - MMGenTrackingWallet.add_label(mmaddr_or_coin_addr,label,on_fail='raise') + from mmgen.tw import TrackingWallet + TrackingWallet().add_label(mmaddr_or_coin_addr,label,on_fail='raise') -def Remove_label(mmaddr_or_coin_addr): Add_label(mmaddr_or_coin_addr,'') +def Remove_label(mmaddr_or_coin_addr): + Add_label(mmaddr_or_coin_addr,'') diff --git a/mmgen/tw.py b/mmgen/tw.py index cc4d47a7..2922139e 100755 --- a/mmgen/tw.py +++ b/mmgen/tw.py @@ -26,7 +26,7 @@ from mmgen.tx import is_mmgen_id CUR_HOME,ERASE_ALL = '\033[H','\033[0J' -class MMGenTrackingWallet(MMGenObject): +class TwUnspentOutputs(MMGenObject): class MMGenTwOutputList(list,MMGenObject): pass @@ -280,7 +280,7 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen idx,lbl = self.get_idx_and_label_from_user() if idx: e = self.unspent[idx-1] - if type(self).add_label(e.twmmid,lbl,addr=e.addr): + if TrackingWallet().add_label(e.twmmid,lbl,addr=e.addr): self.get_unspent_data() self.do_sort() msg(u'{}\n{}\n{}'.format(self.fmt_display,prompt,p)) @@ -312,75 +312,6 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen self.display() msg(prompt) - @classmethod - def import_label(cls,coinaddr,lbl): - # NOTE: this works because importaddress() removes the old account before - # associating the new account with the address. - # Will be replaced by setlabel() with new RPC label API - # RPC args: addr,label,rescan[=true],p2sh[=none] - return g.rpch.importaddress(coinaddr,lbl,False,on_fail='return') - - # returns on failure - @classmethod - def add_label(cls,arg1,label='',addr=None,silent=False,on_fail='return'): - from mmgen.tx import is_mmgen_id,is_coin_addr - mmaddr,coinaddr = None,None - if is_coin_addr(addr or arg1): - coinaddr = CoinAddr(addr or arg1,on_fail='return') - if is_mmgen_id(arg1): - mmaddr = TwMMGenID(arg1) - - if mmaddr and not coinaddr: - from mmgen.addr import AddrData - coinaddr = AddrData(source='tw').mmaddr2coinaddr(mmaddr) - - try: - if not is_mmgen_id(arg1): - assert coinaddr,u"Invalid coin address for this chain: {}".format(arg1) - assert coinaddr,u"{pn} address '{ma}' not found in tracking wallet" - assert coinaddr.is_in_tracking_wallet(),u"Address '{ca}' not found in tracking wallet" - except Exception as e: - msg(e[0].format(pn=g.proj_name,ma=mmaddr,ca=coinaddr)) - return False - - # Allow for the possibility that BTC addr of MMGen addr was entered. - # Do reverse lookup, so that MMGen addr will not be marked as non-MMGen. - if not mmaddr: - from mmgen.addr import AddrData - mmaddr = AddrData(source='tw').coinaddr2mmaddr(coinaddr) - - if not mmaddr: mmaddr = '{}:{}'.format(g.proto.base_coin.lower(),coinaddr) - - mmaddr = TwMMGenID(mmaddr) - - cmt = TwComment(label,on_fail=on_fail) - if cmt in (False,None): return False - - lbl = TwLabel(mmaddr + ('',' '+cmt)[bool(cmt)],on_fail=on_fail) - - if g.coin == 'ETH': - from mmgen.altcoins.eth.tw import EthereumTrackingWallet - cls = EthereumTrackingWallet - - ret = cls.import_label(coinaddr,lbl) - - from mmgen.rpc import rpc_error,rpc_errmsg - if rpc_error(ret): - msg('From {}: {}'.format(g.proto.daemon_name,rpc_errmsg(ret))) - if not silent: - msg('Label could not be {}'.format(('removed','added')[bool(label)])) - return False - else: - m = mmaddr.type.replace('mmg','MMG') - a = mmaddr.replace(g.proto.base_coin.lower()+':','') - s = '{} address {} in tracking wallet'.format(m,a) - if label: msg(u"Added label '{}' to {}".format(label,s)) - else: msg(u'Removed label from {}'.format(s)) - return True - - @classmethod - def remove_label(cls,mmaddr): cls.add_label(mmaddr,'') - class TwAddrList(MMGenDict): def __new__(cls,*args,**kwargs): @@ -504,3 +435,73 @@ class TwAddrList(MMGenDict): )) return '\n'.join(out + ['\nTOTAL: {} {}'.format(self.total.hl(color=True),g.coin)]) + +class TrackingWallet(MMGenObject): + + def __new__(cls,*args,**kwargs): + if g.coin == 'ETH': + from mmgen.altcoins.eth.tw import EthereumTrackingWallet + cls = EthereumTrackingWallet + return MMGenObject.__new__(cls,*args,**kwargs) + + def import_label(self,coinaddr,lbl): + # NOTE: this works because importaddress() removes the old account before + # associating the new account with the address. + # Will be replaced by setlabel() with new RPC label API + # RPC args: addr,label,rescan[=true],p2sh[=none] + return g.rpch.importaddress(coinaddr,lbl,False,on_fail='return') + + # returns on failure + def add_label(self,arg1,label='',addr=None,silent=False,on_fail='return'): + from mmgen.tx import is_mmgen_id,is_coin_addr + mmaddr,coinaddr = None,None + if is_coin_addr(addr or arg1): + coinaddr = CoinAddr(addr or arg1,on_fail='return') + if is_mmgen_id(arg1): + mmaddr = TwMMGenID(arg1) + + if mmaddr and not coinaddr: + from mmgen.addr import AddrData + coinaddr = AddrData(source='tw').mmaddr2coinaddr(mmaddr) + + try: + if not is_mmgen_id(arg1): + assert coinaddr,u"Invalid coin address for this chain: {}".format(arg1) + assert coinaddr,u"{pn} address '{ma}' not found in tracking wallet" + assert coinaddr.is_in_tracking_wallet(),u"Address '{ca}' not found in tracking wallet" + except Exception as e: + msg(e[0].format(pn=g.proj_name,ma=mmaddr,ca=coinaddr)) + return False + + # Allow for the possibility that BTC addr of MMGen addr was entered. + # Do reverse lookup, so that MMGen addr will not be marked as non-MMGen. + if not mmaddr: + from mmgen.addr import AddrData + mmaddr = AddrData(source='tw').coinaddr2mmaddr(coinaddr) + + if not mmaddr: mmaddr = '{}:{}'.format(g.proto.base_coin.lower(),coinaddr) + + mmaddr = TwMMGenID(mmaddr) + + cmt = TwComment(label,on_fail=on_fail) + if cmt in (False,None): return False + + lbl = TwLabel(mmaddr + ('',' '+cmt)[bool(cmt)],on_fail=on_fail) + + ret = self.import_label(coinaddr,lbl) + + from mmgen.rpc import rpc_error,rpc_errmsg + if rpc_error(ret): + msg('From {}: {}'.format(g.proto.daemon_name,rpc_errmsg(ret))) + if not silent: + msg('Label could not be {}'.format(('removed','added')[bool(label)])) + return False + else: + m = mmaddr.type.replace('mmg','MMG') + a = mmaddr.replace(g.proto.base_coin.lower()+':','') + s = '{} address {} in tracking wallet'.format(m,a) + if label: msg(u"Added label '{}' to {}".format(label,s)) + else: msg(u'Removed label from {}'.format(s)) + return True + + def remove_label(self,mmaddr): self.add_label(mmaddr,'') diff --git a/mmgen/tx.py b/mmgen/tx.py index 64d1055a..2e3d5a7a 100755 --- a/mmgen/tx.py +++ b/mmgen/tx.py @@ -1195,8 +1195,8 @@ class MMGenTX(MMGenObject): do_license_msg() - from mmgen.tw import MMGenTrackingWallet - tw = MMGenTrackingWallet(minconf=opt.minconf) + from mmgen.tw import TwUnspentOutputs + tw = TwUnspentOutputs(minconf=opt.minconf) tw.view_and_sort(self) tw.display_total()