mmgen-xmrwallet: new txlist operation

Testing:

    $ test/test.py -e xmrwallet_txlist
This commit is contained in:
The MMGen Project 2023-04-30 09:36:01 +00:00
commit a1986fe631
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
6 changed files with 95 additions and 16 deletions

View file

@ -1 +1 @@
13.3.dev49
13.3.dev50

View file

@ -48,6 +48,7 @@ relay - relay a transaction from a transaction file created using ‘sweep
or transfer with the --no-relay option
submit - submit an autosigned transaction to a wallet and the network
txview - display detailed information about a transaction file or files
txlist - same as above, but display terse information in tabular format
dump - produce JSON dumps of wallet metadata (accounts, addresses and
labels) for a list or range of wallets
restore - same as create, but additionally restore wallet metadata from
@ -134,7 +135,7 @@ wallets, creating the dumps is as easy as executing ‘mmgen-xmrwallet
JSON and thus suitable for efficient incremental backup using git.
TXVIEW OPERATION NOTES
TXVIEW AND TXLIST OPERATION NOTES
Transactions are displayed in chronological order based on submit time or
creation time. With --autosign, submitted transactions on the removable

View file

@ -49,7 +49,7 @@ opts_data = {
'[opts] sweep [xmr_keyaddrfile] SWEEP_SPEC',
'[opts] submit [TX_file]',
'[opts] relay <TX_file>',
'[opts] txview [TX_file] ...',
'[opts] txview | txlist [TX_file] ...',
'[opts] export-outputs [wallets]',
'[opts] import-key-images [wallets]',
],
@ -113,7 +113,7 @@ cmd_args = cfg._args
if cmd_args and cfg.autosign and (
cmd_args[0] in (
MoneroWalletOps.kafile_arg_ops
+ ('export-outputs','import-key-images','txview')
+ ('export-outputs','import-key-images','txview','txlist')
)
or len(cmd_args) == 1 and cmd_args[0] == 'submit'
):
@ -132,7 +132,7 @@ if op.replace('-','_') not in MoneroWalletOps.ops:
if op in ('relay','submit'):
if len(cmd_args) != 0:
cfg._opts.usage()
elif op == 'txview':
elif op in ('txview','txlist'):
infile = [infile] + cmd_args
elif op in ('create','sync','list','dump','restore'): # kafile_arg_ops
if len(cmd_args) > 1:

View file

@ -26,7 +26,7 @@ from pathlib import PosixPath as Path
from .objmethods import MMGenObject,Hilite,InitErrors
from .obj import CoinTxID,Int
from .color import red,yellow,green,blue,cyan,pink,orange
from .color import red,yellow,green,blue,cyan,pink,orange,purple
from .util import (
msg,
msg_r,
@ -190,6 +190,7 @@ class MoneroMMGenTX:
'amount',
'fee',
'blob' }
oneline_fs = '{a:7} {b:8} {c:19} {d:13} {e:8} {f:6} {x:2} {g:6} {h:17} {j}'
chksum_nchars = 6
xmrwallet_tx_data = namedtuple('xmrwallet_tx_data',[
'op',
@ -218,7 +219,22 @@ class MoneroMMGenTX:
def src_wallet_idx(self):
return int(self.data.source.split(':')[0])
def get_info(self,indent=''):
def get_info_oneline(self,indent='',cols=None):
d = self.data
return self.oneline_fs.format(
a = yellow(d.network),
b = d.seed_id.hl(),
c = make_timestr(d.submit_time if d.submit_time is not None else d.create_time),
d = orange(self.file_id),
e = purple(capfirst(d.op.ljust(8))),
f = red('{}:{}'.format(d.source.wallet,d.source.account).ljust(6)),
g = red('{}:{}'.format(d.dest.wallet,d.dest.account).ljust(6)) if d.dest else cyan('ext '),
h = d.amount.fmt( color=True, iwidth=4, prec=12 ),
j = d.dest_address.fmt(width=cols-95,color=True) if cols else d.dest_address.hl(),
x = '->'
)
def get_info(self,indent='',cols=None):
d = self.data
pmt_id = d.dest_address.parsed.payment_id
fs = '\n'.join(list_gen(
@ -584,6 +600,7 @@ class MoneroWalletOps:
'sweep',
'relay',
'txview',
'txlist',
'label',
'sign',
'submit',
@ -1819,10 +1836,15 @@ class MoneroWalletOps:
die(1,'Exiting at user request')
class txview(base):
view_method = 'get_info'
opts = ('watch_only','autosign')
hdr = ''
col_hdr = ''
footer = ''
cols = None
do_umount = False
async def main(self):
async def main(self,cols=None):
if self.cfg.autosign:
asi = get_autosign_obj(self.cfg,'xmr')
files = [f for f in asi.xmr_tx_dir.iterdir() if f.name.endswith('.'+MoneroMMGenTX.Submitted.ext)]
@ -1836,5 +1858,43 @@ class MoneroWalletOps:
if self.cfg.autosign:
asi.do_umount()
self.cfg._util.stdout_or_pager(
'\n'.join(tx.get_info() for tx in txs)
(self.hdr if len(files) > 1 else '')
+ self.col_hdr
+ '\n'.join(getattr(tx,self.view_method)(cols=cols) for tx in txs)
+ self.footer
)
class txlist(txview):
view_method = 'get_info_oneline'
add_nl = True
footer = '\n'
@property
def hdr(self):
return ('SUBMITTED ' if self.cfg.autosign else '') + 'MONERO TRANSACTIONS\n'
@property
def col_hdr(self):
return MoneroMMGenTX.View.oneline_fs.format(
a = 'Network',
b = 'Seed ID',
c = 'Submitted' if self.cfg.autosign else 'Date',
d = 'TxID',
e = 'Type',
f = 'Src',
g = 'Dest',
h = ' Amount',
j = 'Dest Address',
x = '',
) + '\n'
async def main(self):
if self.cfg.pager:
cols = None
else:
from .term import get_terminal_size
cols = self.cfg.columns or get_terminal_size().width
if cols < 106:
die(1, 'A terminal at least 106 columns wide is required to display this output'
+ ' (or use --columns or --pager)' )
await super().main(cols=cols)

View file

@ -34,6 +34,7 @@ class TestSuiteMisc(TestSuiteBase):
cmd_group = (
('rpc_backends', 'RPC backends'),
('xmrwallet_txview', "'mmgen-xmrwallet' txview"),
('xmrwallet_txlist', "'mmgen-xmrwallet' txlist"),
('coin_daemon_info', "'examples/coin-daemon-info.py'"),
('term_echo', "term.set('echo')"),
('term_cleanup', 'term.register_cleanup()'),
@ -47,17 +48,23 @@ class TestSuiteMisc(TestSuiteBase):
t = self.spawn_chk('mmgen-tool',[f'--rpc-backend={b}','daemon_version'],extra_desc=f'({b})')
return t
def xmrwallet_txview(self):
def xmrwallet_txview(self,op='txview'):
files = get_file_with_ext('test/ref/monero','tx',no_dot=True,delete=False,return_list=True)
t = self.spawn( f'mmgen-xmrwallet', ['txview'] + files )
t = self.spawn( f'mmgen-xmrwallet', [op] + files )
res = strip_ansi_escapes(t.read()).replace('\r','')
for s in (
'Amount: 0.74 XMR',
'Dest: 56VQ9M6k',
):
assert s in res, f'{s} not in {res}'
if op == 'txview':
for s in (
'Amount: 0.74 XMR',
'Dest: 56VQ9M6k',
):
assert s in res, f'{s} not in {res}'
elif op == 'txlist':
assert re.search( '3EBD06-.*D94583-.*8BFA29-', res, re.DOTALL )
return t
def xmrwallet_txlist(self):
return self.xmrwallet_txview(op='txlist')
def coin_daemon_info(self):
start_test_daemons('ltc','eth')
t = self.spawn(f'examples/coin-daemon-info.py',['btc','ltc','eth'],cmd_dir='.')

View file

@ -78,6 +78,7 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
('export_key_images', 'exporting signed key images from Alice’s offline wallets'),
('import_key_images', 'importing signed key images into Alice’s online wallets'),
('list_wallets', 'listing Alice’s wallets and checking balance'),
('txlist', 'listing Alice’s submitted transactions'),
)
def __init__(self,trunner,cfgs,spawn):
@ -358,3 +359,13 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
assert after + '\n' == fmt(chk), f'\n{after}\n!=\n{fmt(chk)}'
return t
def txlist(self):
t = self.spawn( 'mmgen-xmrwallet', self.autosign_opts + ['txlist'] )
t.match_expect_list([
'SUBMITTED',
'Network','Submitted',
'Transfer 1:0','-> ext',
'Transfer 1:0','-> ext'
])
return t