From cd2e2240c3cebd4f9fd4a875eece4ca5d275e20d Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Thu, 26 May 2022 16:07:21 +0000 Subject: [PATCH] new command: `mmgen-tool resolve_address` --- mmgen/main_tool.py | 1 + mmgen/tool/rpc.py | 11 +++++++++++ mmgen/tw/ctl.py | 36 ++++++++++++++++++++++++------------ mmgen/tw/unspent.py | 2 +- test/test_py_d/ts_regtest.py | 10 ++++++++++ 5 files changed, 47 insertions(+), 13 deletions(-) diff --git a/mmgen/main_tool.py b/mmgen/main_tool.py index dcb1f2f5..08054047 100755 --- a/mmgen/main_tool.py +++ b/mmgen/main_tool.py @@ -161,6 +161,7 @@ mods = { 'listaddresses', 'remove_address', 'remove_label', + 'resolve_address', 'twview', 'txhist', ), diff --git a/mmgen/tool/rpc.py b/mmgen/tool/rpc.py index 08aff57a..596c0b63 100755 --- a/mmgen/tool/rpc.py +++ b/mmgen/tool/rpc.py @@ -167,3 +167,14 @@ class tool_cmd(tool_cmd_base): from ..util import msg msg(f'Address {ret!r} deleted from tracking wallet') return ret + + async def resolve_address(self,mmgen_or_coin_addr:str): + "resolve an MMGen address in the tracking wallet to a coin address or vice-versa" + from ..tw.ctl import TrackingWallet + ret = await (await TrackingWallet(self.proto,mode='w')).resolve_address( mmgen_or_coin_addr ) + if ret: + from ..util import Msg + from ..addr import is_coin_addr + return ret.mmaddr if is_coin_addr(self.proto,mmgen_or_coin_addr) else ret.coinaddr + else: + return False diff --git a/mmgen/tw/ctl.py b/mmgen/tw/ctl.py index 76a79fb1..90bfbbf8 100755 --- a/mmgen/tw/ctl.py +++ b/mmgen/tw/ctl.py @@ -219,15 +219,15 @@ class TrackingWallet(MMGenObject,metaclass=AsyncInit): from .addrs import TwAddrList return addr in (await TwAddrList(self.proto,[],0,True,True,True,wallet=self)).coinaddr_list() - # returns on failure - @write_mode - async def add_label(self,arg1,label='',addr=None,silent=False,on_fail='return'): - assert on_fail in ('return','raise'), 'add_label_chk1' + async def resolve_address(self,addrspec,usr_coinaddr=None): + mmaddr,coinaddr = None,None - if is_coin_addr(self.proto,addr or arg1): - coinaddr = get_obj(CoinAddr,proto=self.proto,addr=addr or arg1) - if is_mmgen_id(self.proto,arg1): - mmaddr = TwMMGenID(self.proto,arg1) + + if is_coin_addr(self.proto,usr_coinaddr or addrspec): + coinaddr = get_obj(CoinAddr,proto=self.proto,addr=usr_coinaddr or addrspec) + + if is_mmgen_id(self.proto,addrspec): + mmaddr = TwMMGenID(self.proto,addrspec) if mmaddr and not coinaddr: from ..addrdata import TwAddrData @@ -240,7 +240,7 @@ class TrackingWallet(MMGenObject,metaclass=AsyncInit): assert await self.is_in_wallet(coinaddr), f'Address {coinaddr!r} not found in tracking wallet' except Exception as e: msg(str(e)) - return False + return None # 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. @@ -251,18 +251,30 @@ class TrackingWallet(MMGenObject,metaclass=AsyncInit): if not mmaddr: mmaddr = f'{self.proto.base_coin.lower()}:{coinaddr}' - mmaddr = TwMMGenID(self.proto,mmaddr) + from collections import namedtuple + return namedtuple('addr_info',['mmaddr','coinaddr'])( + TwMMGenID(self.proto,mmaddr), + coinaddr ) + + # returns on failure + @write_mode + async def add_label(self,addrspec,label='',coinaddr=None,silent=False,on_fail='return'): + assert on_fail in ('return','raise'), 'add_label_chk1' + + res = await self.resolve_address(addrspec,coinaddr) + if not res: + return False cmt = TwComment(label) if on_fail=='raise' else get_obj(TwComment,s=label) if cmt in (False,None): return False - lbl_txt = mmaddr + (' ' + cmt if cmt else '') + lbl_txt = res.mmaddr + (' ' + cmt if cmt else '') lbl = ( TwLabel(self.proto,lbl_txt) if on_fail == 'raise' else get_obj(TwLabel,proto=self.proto,text=lbl_txt) ) - if await self.set_label(coinaddr,lbl) == False: + if await self.set_label(res.coinaddr,lbl) == False: if not silent: msg( 'Label could not be {}'.format('added' if label else 'removed') ) return False diff --git a/mmgen/tw/unspent.py b/mmgen/tw/unspent.py index 1354a90d..bbeba930 100755 --- a/mmgen/tw/unspent.py +++ b/mmgen/tw/unspent.py @@ -281,7 +281,7 @@ class TwUnspentOutputs(MMGenObject,TwCommon,metaclass=AsyncInit): async def do_lbl_add(lbl): e = uo.data[idx-1] - if await uo.wallet.add_label( e.twmmid, lbl, addr=e.addr ): + if await uo.wallet.add_label( e.twmmid, lbl, coinaddr=e.addr ): await uo.get_data() uo.oneshot_msg = yellow('Label {} {} #{}\n\n'.format( ('added to' if lbl else 'removed from'), diff --git a/test/test_py_d/ts_regtest.py b/test/test_py_d/ts_regtest.py index 3df09f20..fc6be211 100755 --- a/test/test_py_d/ts_regtest.py +++ b/test/test_py_d/ts_regtest.py @@ -202,6 +202,7 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared): ('bob_bal4', "Bob's balance (after import)"), ('bob_import_list', 'importing flat address list'), ('bob_import_list_rescan', 'importing flat address list with --rescan'), + ('bob_resolve_addr', 'resolving an address in the tracking wallet'), ('bob_split2', "splitting Bob's funds"), ('bob_0conf0_getbalance', "Bob's balance (unconfirmed, minconf=0)"), ('bob_0conf1_getbalance', "Bob's balance (unconfirmed, minconf=1)"), @@ -909,6 +910,15 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared): addr = self.read_from_tmpfile('non-mmgen.addrs').split()[0] return self.user_import('bob',['--quiet','--address='+addr],nAddr=1) + def bob_resolve_addr(self): + mmaddr = '{}:C:1'.format(self._user_sid('bob')) + t = self.spawn('mmgen-tool',['--bob','resolve_address',mmaddr]) + coinaddr = t.read().split()[0].strip() + t = self.spawn('mmgen-tool',['--bob','resolve_address',coinaddr],no_msg=True) + mmaddr_res = t.read().split()[0].strip() + assert mmaddr == mmaddr_res, f'{mmaddr} != {mmaddr_res}' + return t + def bob_import_list(self): addrfile = joinpath(self.tmpdir,'non-mmgen.addrs') return self.user_import('bob',['--quiet','--addrlist',addrfile],nAddr=5)