mmgen-xmrwallet: new label operation

This commit is contained in:
The MMGen Project 2023-03-26 12:48:45 +00:00
commit 333cbcf3ac
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
4 changed files with 105 additions and 3 deletions

View file

@ -1 +1 @@
13.3.dev39
13.3.dev40

View file

@ -32,6 +32,7 @@ opts_data = {
'[opts] create <xmr_keyaddrfile> [wallets]',
'[opts] sync <xmr_keyaddrfile> [wallets]',
'[opts] list <xmr_keyaddrfile> [wallets]',
'[opts] label <xmr_keyaddrfile> LABEL_SPEC',
'[opts] new <xmr_keyaddrfile> NEW_ADDRESS_SPEC',
'[opts] transfer <xmr_keyaddrfile> TRANSFER_SPEC',
'[opts] sweep <xmr_keyaddrfile> SWEEP_SPEC',
@ -80,6 +81,7 @@ plain HTTP is not supported.
create - create wallet for all or specified addresses in key-address file
sync - sync wallet for all or specified addresses in key-address file
list - same as 'sync', but also list detailed address info for accounts
label - set a label for an address
new - create a new account in a wallet, or a new address in an account
transfer - transfer specified XMR amount from specified wallet:account to
specified address
@ -99,6 +101,16 @@ in the specified key-address file, each corresponding to a Monero wallet
to be created, synced or listed. If omitted, all wallets are operated upon.
'LABEL' OPERATION NOTES
This operation takes a LABEL_SPEC arg with the following format:
WALLET:ACCOUNT:ADDRESS,"label text"
where WALLET is a wallet number, ACCOUNT an account index, and ADDRESS an
address index.
'NEW' OPERATION NOTES
This operation takes a NEW_ADDRESS_SPEC arg with the following format:
@ -231,7 +243,7 @@ elif op in ('create','sync','list'):
opts.usage()
if cmd_args:
wallets = cmd_args[0]
elif op in ('new','transfer','sweep'):
elif op in ('new','transfer','sweep','label'):
if len(cmd_args) != 1:
opts.usage()
spec = cmd_args[0]

View file

@ -42,6 +42,7 @@ xmrwallet_uarg_info = (
'newaddr_spec': e('WALLET_NUM[:ACCOUNT][,"label text"]', rf'(\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"', rf'(\d+):(\d+):(\d+),(.*)'),
})(
namedtuple('uarg_info_entry',['annot','pat']),
r'(?:[^:]+):(?:\d+)'
@ -237,7 +238,7 @@ class MoneroMMGenTX:
class MoneroWalletOps:
ops = ('create','sync','list','new','transfer','sweep','relay','txview')
ops = ('create','sync','list','new','transfer','sweep','relay','txview','label')
opts = (
'wallet_dir',
'daemon',
@ -508,6 +509,7 @@ class MoneroWalletOps:
e['label'],
e['used']
))
return ret
def create_new_addr(self,account,label=None):
msg_r('\n Creating new address: ')
@ -531,6 +533,13 @@ class MoneroWalletOps:
msg(' ' + cyan(addr))
return ( addr, len(ret) - 1 )
def set_label(self,account,address_idx,label):
return self.c.call(
'label_address',
index = { 'major': account, 'minor': address_idx },
label = label
)
def make_transfer_tx(self,account,addr,amt):
res = self.c.call(
'transfer',
@ -788,6 +797,9 @@ class MoneroWalletOps:
self.amount = self.proto.coin_amt(m[4])
elif self.name == 'new':
self.label = strip_quotes(m[3])
elif self.name == 'label':
self.address_idx = int(m[3])
self.label = strip_quotes(m[4])
class sweep(spec):
name = 'sweep'
@ -933,6 +945,61 @@ class MoneroWalletOps:
msg('')
class label(spec):
name = 'label'
spec_id = 'label_spec'
spec_key = ( (1,'source'), )
opts = ()
async def main(self):
gmsg('\n{} label for wallet {}, account #{}, address #{}'.format(
'Setting' if self.label else 'Removing',
self.source.idx,
self.account,
self.address_idx
))
h = self.rpc(self,self.source)
h.open_wallet('source')
accts_data = h.get_accts()[0]
max_acct = len(accts_data['subaddress_accounts']) - 1
if self.account > max_acct:
die(1,f'{self.account}: requested account index out of bounds (>{max_acct})')
ret = h.print_addrs(accts_data,self.account)
if self.address_idx > len(ret['addresses']) - 1:
die(1,'{}: requested address index out of bounds (>{})'.format(
self.account,
len(ret['addresses']) - 1 ))
addr = ret['addresses'][self.address_idx]
msg('\n {} {}\n {} {}\n {} {}'.format(
'Address: ',
cyan(addr['address'][:15] + '...'),
'Existing label:',
pink(addr['label']) if addr['label'] else '[none]',
'New label: ',
pink(self.label) if self.label else '[none]' ))
if addr['label'] == self.label:
ymsg('\nLabel is unchanged, operation cancelled')
elif keypress_confirm(' {} label?'.format('Set' if self.label else 'Remove')):
h.set_label( self.account, self.address_idx, self.label )
accts_data = h.get_accts(print=False)[0]
ret = h.print_addrs(accts_data,self.account)
new_label = ret['addresses'][self.address_idx]['label']
if new_label != self.label:
ymsg(f'Warning: new label {new_label!r} does not match requested value!')
return False
else:
msg(cyan('\nLabel successfully {}'.format('set' if self.label else 'removed')))
else:
ymsg('\nOperation cancelled by user request')
class relay(base):
name = 'relay'
opts = ('tx_relay_daemon',)

View file

@ -49,6 +49,7 @@ class TestSuiteXMRWallet(TestSuiteBase):
('daemon_version', 'checking daemon version'),
('gen_kafiles', 'generating key-address files'),
('create_wallets_miner', 'creating Monero wallets (Miner)'),
('set_label_miner', 'setting an address label (Miner, primary account)'),
('mine_initial_coins', 'mining initial coins'),
('create_wallets_alice', 'creating Monero wallets (Alice)'),
('fund_alice', 'sending funds'),
@ -58,6 +59,8 @@ class TestSuiteXMRWallet(TestSuiteBase):
('new_account_alice_label', 'creating a new account (Alice, with label)'),
('new_address_alice', 'creating a new address (Alice)'),
('new_address_alice_label', 'creating a new address (Alice, with label)'),
('remove_label_alice', 'removing an address label (Alice, subaddress)'),
('set_label_alice', 'setting an address label (Alice, subaddress)'),
('sync_wallets_selected', 'syncing selected wallets'),
('sweep_to_address_proxy', 'sweeping to new address (via TX relay + proxy)'),
@ -374,6 +377,26 @@ class TestSuiteXMRWallet(TestSuiteBase):
random_txs = self.dfl_random_txs
)
def set_label_miner(self):
return self.set_label_user( 'miner', '1:0:0,"Miner’s new primary account label [1:0:0]"' )
def remove_label_alice(self):
return self.set_label_user( 'alice', '4:2:2,""' )
def set_label_alice(self):
return self.set_label_user( 'alice', '4:2:2,"Alice’s new subaddress label [4:2:2]"' )
def set_label_user(self,user,label_spec):
data = self.users[user]
cmd_opts = [f'--wallet-dir={data.udir}', f'--daemon=localhost:{data.md.rpc_port}']
t = self.spawn(
'mmgen-xmrwallet',
self.extra_opts + cmd_opts + ['label', data.kafile, label_spec]
)
t.expect('(y/N): ','y')
t.expect(['successfully set','successfully removed'])
return t
def sync_wallets_all(self):
return self.sync_wallets('alice',add_opts=['--rescan-blockchain'])