xmrwallet, cmdtest xmrwallet: fixes and cleanups
This commit is contained in:
parent
c87cfa7d00
commit
524b3515ab
5 changed files with 61 additions and 44 deletions
|
|
@ -288,7 +288,7 @@ class Signable:
|
|||
spec = None ),
|
||||
)
|
||||
obj = await m.main(f, wallet_idx, restart_daemon=self.need_daemon_restart(m,wallet_idx))
|
||||
obj.write()
|
||||
obj.write(quiet=not obj.data.sign)
|
||||
self.action_desc = 'imported and signed' if obj.data.sign else 'imported'
|
||||
return obj
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ help.xmrwallet: xmrwallet help notes for MMGen suite
|
|||
"""
|
||||
|
||||
def help(proto,cfg):
|
||||
from ..xmrwallet import xmrwallet_uarg_info as uai
|
||||
|
||||
return """
|
||||
Many operations take an optional ‘wallets’ argument: one or more address
|
||||
|
|
@ -73,7 +74,7 @@ import-key-images - import key images signed by offline wallets into their
|
|||
|
||||
This operation takes a LABEL_SPEC arg with the following format:
|
||||
|
||||
WALLET:ACCOUNT:ADDRESS,"label text"
|
||||
{label_spec}
|
||||
|
||||
where WALLET is a wallet number, ACCOUNT an account index, and ADDRESS an
|
||||
address index.
|
||||
|
|
@ -83,40 +84,40 @@ address index.
|
|||
|
||||
This operation takes a NEW_ADDRESS_SPEC arg with the following format:
|
||||
|
||||
WALLET[:ACCOUNT][,"label text"]
|
||||
{newaddr_spec}
|
||||
|
||||
where WALLET is a wallet number and ACCOUNT an account index. If ACCOUNT is
|
||||
omitted, a new account will be created in the wallet, otherwise a new address
|
||||
will be created in the specified account. An optional label text may be
|
||||
appended to the spec following a comma.
|
||||
where WALLET is a wallet number and ACCOUNT an account index. If ACCOUNT
|
||||
is omitted, a new account will be created in the wallet. Otherwise a new
|
||||
address will be created in the specified account. An optional label text
|
||||
may be appended to the spec following a comma.
|
||||
|
||||
|
||||
‘TRANSFER’ OPERATION NOTES
|
||||
|
||||
The transfer operation takes a TRANSFER_SPEC arg with the following format:
|
||||
|
||||
SOURCE:ACCOUNT:ADDRESS,AMOUNT
|
||||
{transfer_spec}
|
||||
|
||||
where SOURCE is a wallet number; ACCOUNT the source account index; and ADDRESS
|
||||
and AMOUNT the destination Monero address and XMR amount, respectively.
|
||||
where SOURCE is a wallet number, ACCOUNT the source account index, ADDRESS
|
||||
the destination Monero address and AMOUNT the XMR amount to be sent.
|
||||
|
||||
|
||||
‘SWEEP’ OPERATION NOTES
|
||||
|
||||
The sweep operation takes a SWEEP_SPEC arg with the following format:
|
||||
|
||||
SOURCE:ACCOUNT[,DEST]
|
||||
{sweep_spec}
|
||||
|
||||
where SOURCE and DEST are wallet numbers and ACCOUNT an account index.
|
||||
|
||||
If DEST is omitted, a new address will be created in ACCOUNT of SOURCE and
|
||||
all funds from ACCOUNT of SOURCE will be swept into it.
|
||||
If DEST is omitted, a new address will be created in ACCOUNT of SOURCE, and
|
||||
funds from ACCOUNT of SOURCE will be swept into it.
|
||||
|
||||
If DEST is included, all funds from ACCOUNT of SOURCE will be swept into a
|
||||
newly created account in DEST, or the last existing account, if requested
|
||||
by the user.
|
||||
|
||||
The user is prompted before addresses are created or funds are transferred.
|
||||
The user is prompted before addresses are created or funds transferred.
|
||||
|
||||
Note that multiple sweep operations may be required to sweep all the funds
|
||||
in an account.
|
||||
|
|
@ -386,7 +387,7 @@ Start the cloning process by making dump files of your hot wallets’ metadata
|
|||
(accounts, subaddresses and labels). ‘cd’ to the wallet directory (or use
|
||||
--wallet-dir) and execute:
|
||||
|
||||
$ mmgen-xmrwallet dump /path/to/key-address-file.akeys{.mmenc}
|
||||
$ mmgen-xmrwallet dump /path/to/key-address-file.akeys{{.mmenc}}
|
||||
|
||||
If you’ve been transacting with the wallets, you know where their key-address
|
||||
file is along with its encryption password, if any. Supply an additional
|
||||
|
|
@ -397,7 +398,7 @@ to ignore.
|
|||
Do a directory listing to verify that the dump files are present alongside
|
||||
their source wallet files ending with ‘MoneroWallet’. Then execute:
|
||||
|
||||
$ mmgen-xmrwallet --watch-only restore /path/to/key-address-file.akeys{.mmenc}
|
||||
$ mmgen-xmrwallet --watch-only restore /path/to/key-address-file.akeys{{.mmenc}}
|
||||
|
||||
This will create watch-only wallets that “mirror” the old hot wallets and
|
||||
populate them with the metadata saved in the dump files.
|
||||
|
|
@ -445,4 +446,9 @@ Tutorial above.
|
|||
Once you’ve gained proficiency with the autosigning process and feel ready
|
||||
to delete your old hot wallets, make sure to do so securely using ‘shred’,
|
||||
‘wipe’ or some other secure deletion utility.
|
||||
""".strip()
|
||||
""".strip().format(
|
||||
newaddr_spec = uai['newaddr_spec'].annot,
|
||||
label_spec = uai['label_spec'].annot,
|
||||
transfer_spec = uai['transfer_spec'].annot,
|
||||
sweep_spec = uai['sweep_spec'].annot,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -67,11 +67,11 @@ xmrwallet_uargs = namedtuple('xmrwallet_uargs',[
|
|||
xmrwallet_uarg_info = (
|
||||
lambda e,hp: {
|
||||
'daemon': e('HOST:PORT', hp),
|
||||
'tx_relay_daemon': e('HOST:PORT[:PROXY_IP:PROXY_PORT]', rf'({hp})(?::({hp}))?'),
|
||||
'newaddr_spec': e('WALLET_NUM[:ACCOUNT][,"label text"]', r'(\d+)(?::(\d+))?(?:,(.*))?'),
|
||||
'transfer_spec': e('SOURCE_WALLET_NUM:ACCOUNT:ADDRESS,AMOUNT', rf'(\d+):(\d+):([{b58a}]+),([0-9.]+)'),
|
||||
'sweep_spec': e('SOURCE_WALLET_NUM:ACCOUNT[,DEST_WALLET_NUM]', r'(\d+):(\d+)(?:,(\d+))?'),
|
||||
'label_spec': e('WALLET_NUM:ACCOUNT:ADDRESS,"label text"', r'(\d+):(\d+):(\d+),(.*)'),
|
||||
'tx_relay_daemon': e('HOST:PORT[:PROXY_IP:PROXY_PORT]', rf'({hp})(?::({hp}))?'),
|
||||
'newaddr_spec': e('WALLET[:ACCOUNT][,"label text"]', r'(\d+)(?::(\d+))?(?:,(.*))?'),
|
||||
'transfer_spec': e('SOURCE:ACCOUNT:ADDRESS,AMOUNT', rf'(\d+):(\d+):([{b58a}]+),([0-9.]+)'),
|
||||
'sweep_spec': e('SOURCE:ACCOUNT[,DEST]', r'(\d+):(\d+)(?:,(\d+))?'),
|
||||
'label_spec': e('WALLET:ACCOUNT:ADDRESS,"label text"', r'(\d+):(\d+):(\d+),(.*)'),
|
||||
})(
|
||||
namedtuple('uarg_info_entry',['annot','pat']),
|
||||
r'(?:[^:]+):(?:\d+)'
|
||||
|
|
@ -507,7 +507,7 @@ class MoneroWalletOutputsFile:
|
|||
self.name = type(self).__name__
|
||||
self.cfg = cfg
|
||||
|
||||
def write(self,add_suf=''):
|
||||
def write(self, add_suf='', quiet=False):
|
||||
from .fileutil import write_data_to_file
|
||||
write_data_to_file(
|
||||
cfg = self.cfg,
|
||||
|
|
@ -515,7 +515,8 @@ class MoneroWalletOutputsFile:
|
|||
data = self.make_wrapped_data(self.data._asdict()),
|
||||
desc = self.desc,
|
||||
ask_overwrite = False,
|
||||
ignore_opt_outdir = True )
|
||||
quiet = quiet,
|
||||
ignore_opt_outdir = True)
|
||||
|
||||
def get_outfile(self,cfg,wallet_fn):
|
||||
return (
|
||||
|
|
@ -1561,21 +1562,26 @@ class MoneroWalletOps:
|
|||
daemon = wd2 )
|
||||
|
||||
def create_tx(self, h, accts_data):
|
||||
if self.dest is None:
|
||||
dest_acct = self.account
|
||||
if keypress_confirm(self.cfg, f'\nCreate new address for account #{self.account}?'):
|
||||
dest_addr_chk = h.create_new_addr(self.account)
|
||||
elif keypress_confirm(self.cfg, f'Sweep to last existing address of account #{self.account}?'):
|
||||
dest_addr_chk = None
|
||||
else:
|
||||
|
||||
def create_new_addr_maybe(h, account, label=None):
|
||||
if keypress_confirm(self.cfg, f'\nCreate new address for account #{account}?'):
|
||||
return h.create_new_addr(account, label)
|
||||
elif not keypress_confirm(self.cfg, f'Sweep to last existing address of account #{account}?'):
|
||||
die(1,'Exiting at user request')
|
||||
return None
|
||||
|
||||
dest_addr_chk = None
|
||||
|
||||
if self.dest is None: # sweep to same account
|
||||
dest_acct = self.account
|
||||
dest_addr_chk = create_new_addr_maybe(h, self.account)
|
||||
dest_addr, dest_addr_idx = h.get_last_addr(self.account, display=not dest_addr_chk)
|
||||
assert dest_addr_chk in (None, dest_addr), 'dest_addr_chk1'
|
||||
h.print_addrs(accts_data, self.account)
|
||||
else:
|
||||
else: # sweep to wallet
|
||||
h.close_wallet('source')
|
||||
h2 = self.rpc(self, self.dest)
|
||||
h2.open_wallet('destination')
|
||||
h2.get_accts()
|
||||
|
||||
wf = self.get_wallet_fn(self.dest)
|
||||
if keypress_confirm(self.cfg, f'\nCreate new account for wallet {wf.name!r}?'):
|
||||
|
|
@ -1586,13 +1592,14 @@ class MoneroWalletOps:
|
|||
elif keypress_confirm(self.cfg, f'Sweep to last existing account of wallet {wf.name!r}?'):
|
||||
dest_acct, dest_addr_chk = h2.get_last_acct(h2.get_accts()[0])
|
||||
dest_addr, dest_addr_idx = h2.get_last_addr(dest_acct, display=False)
|
||||
assert dest_addr_chk == dest_addr, 'dest_addr_chk2'
|
||||
else:
|
||||
die(1, 'Exiting at user request')
|
||||
|
||||
h2.close_wallet('destination')
|
||||
h.open_wallet('source', refresh=False)
|
||||
|
||||
assert dest_addr_chk in (None, dest_addr), 'dest_addr_chk'
|
||||
|
||||
msg(f'\n Creating {self.name} transaction...')
|
||||
return (h, h.make_sweep_tx(self.account, dest_acct, dest_addr_idx, dest_addr))
|
||||
|
||||
|
|
@ -1603,6 +1610,11 @@ class MoneroWalletOps:
|
|||
else:
|
||||
return f' to new account in wallet {self.dest.idx}'
|
||||
|
||||
def check_account_exists(self, accts_data, idx):
|
||||
max_acct = len(accts_data['subaddress_accounts']) - 1
|
||||
if self.account > max_acct:
|
||||
die(2, f'{self.account}: requested account index out of bounds (>{max_acct})')
|
||||
|
||||
async def main(self):
|
||||
|
||||
gmsg(
|
||||
|
|
@ -1614,9 +1626,7 @@ class MoneroWalletOps:
|
|||
h.open_wallet('source')
|
||||
accts_data = h.get_accts()[0]
|
||||
|
||||
max_acct = len(accts_data['subaddress_accounts']) - 1
|
||||
if self.account > max_acct:
|
||||
die(2, f'{self.account}: requested account index out of bounds (>{max_acct})')
|
||||
self.check_account_exists(accts_data, self.account)
|
||||
|
||||
h.print_addrs(accts_data,self.account)
|
||||
|
||||
|
|
|
|||
|
|
@ -527,7 +527,7 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
tx_relay_parm = None,
|
||||
no_relay = False,
|
||||
return_amt = False,
|
||||
reuse_acct = False,
|
||||
use_existing = False,
|
||||
add_opts = [],
|
||||
add_desc = None,
|
||||
do_ret = False):
|
||||
|
|
@ -557,12 +557,13 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
return t
|
||||
|
||||
if op == 'sweep':
|
||||
desc = 'address' if re.match(r'.*:\d+$', arg2) else 'account'
|
||||
t.expect(
|
||||
r'Create new {} .* \(y/N\): '.format(('address','account')[',' in arg2]),
|
||||
('y','n')[reuse_acct],
|
||||
rf'Create new {desc} .* \(y/N\): ',
|
||||
('y','n')[use_existing],
|
||||
regex=True )
|
||||
if reuse_acct:
|
||||
t.expect( r'to last existing account .* \(y/N\): ','y', regex=True )
|
||||
if use_existing:
|
||||
t.expect(rf'to last existing {desc} .* \(y/N\): ', 'y', regex=True)
|
||||
|
||||
if return_amt:
|
||||
amt = XMRAmt(strip_ansi_escapes(t.expect_getend('Amount: ')).replace('XMR','').strip())
|
||||
|
|
@ -656,7 +657,7 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
send_amt = self.do_op(
|
||||
'sweep','alice','2:1,3', # '2:1,3'
|
||||
no_relay = True,
|
||||
reuse_acct = True,
|
||||
use_existing = True,
|
||||
add_desc = f'TX #{i+1}',
|
||||
return_amt = True )
|
||||
ok()
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class unit_tests:
|
|||
vs('1:2,3:4', "('1', '2', '3', '4')"),
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
vmsg('')
|
||||
for k,v in uarg_info.items():
|
||||
vmsg(f' {k}')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue