From b6acf87916dce2cedf77fdd4f31421f21d705232 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Mon, 15 Apr 2024 09:48:14 +0000 Subject: [PATCH] mmgen-xmrwallet: add --skip-empty-accounts, --skip-empty-addresses --- mmgen/main_xmrwallet.py | 4 ++++ mmgen/xmrwallet.py | 37 ++++++++++++++++++++++--------- test/cmdtest_py_d/ct_xmrwallet.py | 10 ++++----- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/mmgen/main_xmrwallet.py b/mmgen/main_xmrwallet.py index 70798cbc..3a87c99c 100755 --- a/mmgen/main_xmrwallet.py +++ b/mmgen/main_xmrwallet.py @@ -73,6 +73,10 @@ opts_data = { -d, --outdir=D Save transaction files to directory 'D' instead of the working directory -D, --daemon=H:P Connect to the monerod at {D} +-e, --skip-empty-accounts Skip display of empty accounts in wallets + where applicable +-E, --skip-empty-addresses Skip display of used empty addresses in + wallets where applicable -k, --use-internal-keccak-module Force use of the internal keccak module -p, --hash-preset=P Use scrypt hash preset 'P' for password hashing (default: '{gc.dfl_hash_preset}') diff --git a/mmgen/xmrwallet.py b/mmgen/xmrwallet.py index 56fa9bb4..5c451b6f 100755 --- a/mmgen/xmrwallet.py +++ b/mmgen/xmrwallet.py @@ -125,6 +125,8 @@ def gen_acct_addr_info(self, wallet_data, account, indent=''): for addr in addrs_data: ca = CoinAddr(self.proto, addr['address']) bal = addr['unlocked_balance'] + if self.cfg.skip_empty_addresses and addr['used'] and not bal: + continue yield fs.format( I = addr['address_index'], A = ca.hl() if self.cfg.full_address else ca.fmt(color=True, width=addr_width), @@ -710,7 +712,9 @@ class MoneroWalletOps: 'no_stop_wallet_daemon', 'no_relay', 'watch_only', - 'autosign' ) + 'autosign', + 'skip_empty_accounts', + 'skip_empty_addresses') pat_opts = ('daemon','tx_relay_daemon') @@ -929,6 +933,12 @@ class MoneroWalletOps: def get_idx_from_fn(cls,fn): return int( re.match(r'[0-9a-fA-F]{8}-(\d+)-Monero(WatchOnly)?Wallet.*',fn.name)[1] ) + def pre_init_action(self): + if self.cfg.skip_empty_accounts: + msg(orange('Skipping display of empty accounts where applicable')) + if self.cfg.skip_empty_addresses: + msg(orange('Skipping display of empty used addresses where applicable')) + def get_coin_daemon_rpc(self): host,port = self.cfg.daemon.split(':') if self.cfg.daemon else ('localhost',self.wd.monerod_port) @@ -1066,7 +1076,7 @@ class MoneroWalletOps: await self.c.stop_daemon(quiet=True) # closes wallet gmsg_r('done') - def gen_accts_info(self, accts_data, addrs_data, indent=' '): + def gen_accts_info(self, accts_data, addrs_data, indent=' ', skip_empty_ok=False): fs = indent + ' {I:<3} {A} {N} {B} {L}' yield indent + f'Accounts of wallet {self.fn.name}:' yield fs.format( @@ -1076,6 +1086,8 @@ class MoneroWalletOps: B = ' Unlocked Balance', L = 'Label') for i,e in enumerate(accts_data['subaddress_accounts']): + if skip_empty_ok and self.cfg.skip_empty_accounts and not e['unlocked_balance']: + continue ca = CoinAddr(self.proto, e['base_address']) yield fs.format( I = str(e['account_index']), @@ -1084,14 +1096,14 @@ class MoneroWalletOps: B = fmt_amt(e['unlocked_balance']), L = pink(e['label'])) - def get_wallet_data(self, print=True): + def get_wallet_data(self, print=True, skip_empty_ok=False): accts_data = self.c.call('get_accounts') addrs_data = [ self.c.call('get_address',account_index=i) for i in range(len(accts_data['subaddress_accounts'])) ] if print: - msg('\n' + '\n'.join(self.gen_accts_info(accts_data, addrs_data))) + msg('\n' + '\n'.join(self.gen_accts_info(accts_data, addrs_data, skip_empty_ok=skip_empty_ok))) bals_data = self.c.call('get_balance', all_accounts=True) return namedtuple('wallet_data', ['accts_data', 'addrs_data', 'bals_data'])( accts_data, addrs_data, bals_data) @@ -1360,7 +1372,7 @@ class MoneroWalletOps: return True class sync(wallet): - opts = ('rescan_blockchain',) + opts = ('rescan_blockchain', 'skip_empty_accounts', 'skip_empty_addresses') def check_uopts(self): if self.cfg.rescan_blockchain and self.cfg.watch_only: @@ -1420,7 +1432,7 @@ class MoneroWalletOps: t_elapsed = int(time.time() - t_start) - wd = self.rpc(self, d).get_wallet_data(print=False) + wd = self.rpc(self, d).get_wallet_data(print=False, skip_empty_ok=True) msg(' Balance: {} Unlocked balance: {}'.format( hl_amt(wd.accts_data['total_balance']), @@ -1442,7 +1454,8 @@ class MoneroWalletOps: yield from self.rpc(self, self.addr_data[wnum]).gen_accts_info( wallet_data.accts_data, wallet_data.addrs_data, - indent = '') + indent = '', + skip_empty_ok = True) yield '' def post_main_success(self): @@ -1476,6 +1489,8 @@ class MoneroWalletOps: yield green(f'Wallet {wallet_fn}:') for account in range(len(wallet_data.addrs_data)): bal = ad[account]['unlocked_balance'] + if self.cfg.skip_empty_accounts and not bal: + continue yield '' yield ' Account #{a} [{b} {c}]'.format( a = account, @@ -1503,7 +1518,7 @@ class MoneroWalletOps: wallet_height = self.c.call('get_height')['height'] msg(f' Wallet height: {wallet_height}') - self.wallets_data[fn.name] = self.rpc(self, d).get_wallet_data(print=False) + self.wallets_data[fn.name] = self.rpc(self, d).get_wallet_data(print=False, skip_empty_ok=True) if not last: self.c.call('close_wallet') @@ -1564,7 +1579,9 @@ class MoneroWalletOps: 'no_relay', 'tx_relay_daemon', 'watch_only', - 'priority') + 'priority', + 'skip_empty_accounts', + 'skip_empty_addresses') sweep_type = 'single-address' def check_uopts(self): @@ -1694,7 +1711,7 @@ class MoneroWalletOps: h.open_wallet('source') - wallet_data = h.get_wallet_data() + wallet_data = h.get_wallet_data(skip_empty_ok=True) self.check_account_exists(wallet_data.accts_data, self.account) diff --git a/test/cmdtest_py_d/ct_xmrwallet.py b/test/cmdtest_py_d/ct_xmrwallet.py index 22e119b1..86b6fe08 100755 --- a/test/cmdtest_py_d/ct_xmrwallet.py +++ b/test/cmdtest_py_d/ct_xmrwallet.py @@ -474,13 +474,13 @@ class CmdTestXMRWallet(CmdTestBase): return t def sync_wallets_all(self): - return self.sync_wallets('alice',add_opts=['--rescan-blockchain']) + return self.sync_wallets('alice', add_opts=['--rescan-blockchain', '-Ee']) def sync_wallets_selected(self): return self.sync_wallets('alice', wallets='1-2,4', add_opts=['--full-address']) def list_wallets_all(self): - return self.sync_wallets('alice', op='list', add_opts=['--full-address']) + return self.sync_wallets('alice', op='list', add_opts=['-Ee', '--full-address']) def sync_wallets(self,user,op='sync',wallets=None,add_opts=[],bal_chk_func=None): data = self.users[user] @@ -588,11 +588,11 @@ class CmdTestXMRWallet(CmdTestBase): return self.mine_chk('alice', 2, 0, lambda x: x.ub > 1, 'unlocked balance > 1') def sweep_to_wallet_account(self): - self.do_op('sweep', 'alice', '2:0,3:0', use_existing=True, add_opts=['--full-address']) + self.do_op('sweep', 'alice', '2:0,3:0', use_existing=True, add_opts=['-Ee', '--full-address']) return self.mine_chk('alice', 3, 0, lambda x: x.ub > 1, 'unlocked balance > 1') def sweep_to_wallet_account_proxy(self): - self.do_op('sweep', 'alice', '3:0,2:1', self.tx_relay_daemon_proxy_parm, add_opts=['--priority=3']) + self.do_op('sweep', 'alice', '3:0,2:1', self.tx_relay_daemon_proxy_parm, add_opts=['--priority=3', '-Ee']) return self.mine_chk('alice', 2, 1, lambda x: x.ub > 1, 'unlocked balance > 1') def sweep_to_same_account_noproxy(self): @@ -619,7 +619,7 @@ class CmdTestXMRWallet(CmdTestBase): def transfer_to_miner_create(self,amt): get_file_with_ext(self.users['alice'].udir,'sigtx',delete_all=True) addr = read_from_file(self.users['miner'].addrfile_fs.format(2)) - return self.do_op('transfer','alice',f'2:1:{addr},{amt}',no_relay=True,do_ret=True) + return self.do_op('transfer', 'alice', f'2:1:{addr},{amt}', no_relay=True, do_ret=True, add_opts=['-Ee']) def transfer_to_miner_create1(self): return self.transfer_to_miner_create('0.0111')