From a351b16e11f91605d81c8ab4f095a73a7c8ad83c Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Wed, 7 May 2025 18:24:07 +0000 Subject: [PATCH] proto.eth.tw.ctl: find unused addresses correctly --- mmgen/proto/eth/tw/addresses.py | 5 ++++- mmgen/proto/eth/tw/ctl.py | 13 ++++++++++++- test/cmdtest_d/ethdev.py | 6 +++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/mmgen/proto/eth/tw/addresses.py b/mmgen/proto/eth/tw/addresses.py index 9e14072d..47cd4b89 100755 --- a/mmgen/proto/eth/tw/addresses.py +++ b/mmgen/proto/eth/tw/addresses.py @@ -13,6 +13,7 @@ proto.eth.tw.addresses: Ethereum base protocol tracking wallet address list clas """ from ....tw.addresses import TwAddresses + from .view import EthereumTwView from .rpc import EthereumTwRPC @@ -69,13 +70,15 @@ class EthereumTwAddresses(TwAddresses, EthereumTwView, EthereumTwRPC): self.minconf = None addrs = {} + used_addrs = self.twctl.used_addrs + for e in await self.twctl.get_label_addr_pairs(): bal = await self.twctl.get_balance(e.coinaddr) addrs[e.label.mmid] = { 'addr': e.coinaddr, 'amt': bal, 'recvd': bal, # current bal only, CF btc.tw.addresses.get_rpc_data() - 'is_used': bool(bal), # ditto + 'is_used': bool(bal) or e.coinaddr in used_addrs, 'confs': 0, 'lbl': e.label} self.total += bal diff --git a/mmgen/proto/eth/tw/ctl.py b/mmgen/proto/eth/tw/ctl.py index 75606405..4978f53f 100755 --- a/mmgen/proto/eth/tw/ctl.py +++ b/mmgen/proto/eth/tw/ctl.py @@ -20,7 +20,7 @@ proto.eth.tw.ctl: Ethereum tracking wallet control class """ -from ....util import msg, ymsg, die +from ....util import msg, ymsg, die, cached_property from ....tw.ctl import TwCtl, write_mode, label_addr_pair from ....tw.shared import TwLabel from ....addr import is_coin_addr, is_mmgen_id, CoinAddr @@ -167,6 +167,17 @@ class EthereumTwCtl(TwCtl): CoinAddr(self.proto, d['addr']) ) for mmid, d in self.mmid_ordered_dict.items()] + # Since it’s nearly impossible to empty an Ethereum account, consider set of used addresses + # to be all accounts with balances. + # Token addresses might have a balance but no corresponding ETH balance, so check them too. + @cached_property + def used_addrs(self): + from decimal import Decimal + return ( + {k for k, v in self.data['accounts'].items() if Decimal(v['balance'])} | + {k for t in self.data['tokens'].values() for k, v in t.items() + if Decimal(v.get('balance', 0))}) + class EthereumTokenTwCtl(EthereumTwCtl): desc = 'Ethereum token tracking wallet' diff --git a/test/cmdtest_d/ethdev.py b/test/cmdtest_d/ethdev.py index 0ec75284..697c813d 100755 --- a/test/cmdtest_d/ethdev.py +++ b/test/cmdtest_d/ethdev.py @@ -319,7 +319,7 @@ class CmdTestEthdevMethods: caller = cmd, file_desc = 'Unsigned automount transaction') - async def _token_transfer_ops(self, *, op, mm_idxs, amt=1000, sid=dfl_sid): + async def _token_transfer_ops(self, *, op, mm_idxs, amt=1000, sid=dfl_sid, token_addr=None): self.spawn(msg_only=True) from mmgen.tool.wallet import tool_cmd usr_mmaddrs = [f'{sid}:E:{i}' for i in mm_idxs] @@ -330,7 +330,7 @@ class CmdTestEthdevMethods: tk = await ResolvedToken( self.cfg, self.proto, - self.read_from_tmpfile(f'token_addr{i+1}').strip(), + self.read_from_tmpfile(token_addr or f'token_addr{i+1}').strip(), rpc = rpc) imsg_r('\n' + await tk.info()) imsg('dev token balance (pre-send): {}'.format(await tk.get_balance(dfl_devaddr))) @@ -356,7 +356,7 @@ class CmdTestEthdevMethods: tk = await ResolvedToken( self.cfg, self.proto, - self.read_from_tmpfile(f'token_addr{i+1}').strip(), + self.read_from_tmpfile(token_addr or f'token_addr{i+1}').strip(), rpc = rpc) imsg('Token: {}'.format(await tk.get_symbol())) imsg(f'dev token balance: {await tk.get_balance(dfl_devaddr)}')