mmgen-xmrwallet: new ‘sweep_all’ operation
This operation sweeps balances of all addresses in an account, as opposed to ‘sweep’, which sweeps the balance of a single randomly chosen address. For accounts having only one address with a balance, the two operations are identical.
This commit is contained in:
parent
ea0f32e3df
commit
fc7e3c8302
5 changed files with 37 additions and 45 deletions
|
|
@ -1 +1 @@
|
|||
14.1.dev27
|
||||
14.1.dev28
|
||||
|
|
|
|||
|
|
@ -48,7 +48,8 @@ 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
|
||||
sweep - sweep funds in specified wallet:account to new address in same
|
||||
account or new account in another wallet
|
||||
account, or new or specified account in another wallet
|
||||
sweep_all - same as above, but sweep balances of all addresses in the account
|
||||
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
|
||||
|
|
@ -102,9 +103,10 @@ 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
|
||||
‘SWEEP’ AND ‘SWEEP_ALL’ OPERATION NOTES
|
||||
|
||||
The sweep operation takes a SWEEP_SPEC arg with the following format:
|
||||
The sweep and sweep_all operations take a SWEEP_SPEC arg with the following
|
||||
format:
|
||||
|
||||
{sweep_spec}
|
||||
|
||||
|
|
@ -123,8 +125,9 @@ swept into ACCOUNT of DEST.
|
|||
|
||||
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.
|
||||
With ‘sweep’, if the source account has more than one address with a balance,
|
||||
the balance of a single randomly chosen address will be swept. To sweep the
|
||||
balances of all addresses in an account, use ‘sweep_all’.
|
||||
|
||||
|
||||
‘SUBMIT’ AND ‘RELAY’ OPERATION NOTES
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ opts_data = {
|
|||
'[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',
|
||||
'[opts] sweep | sweep_all [xmr_keyaddrfile] SWEEP_SPEC',
|
||||
'[opts] submit [TX_file]',
|
||||
'[opts] relay <TX_file>',
|
||||
'[opts] resubmit | abort (for use with --autosign only)',
|
||||
|
|
@ -139,7 +139,7 @@ elif op in ('create','sync','list','view','listview','dump','restore'): # kafile
|
|||
if len(cmd_args) > 1:
|
||||
cfg._opts.usage()
|
||||
wallets = cmd_args.pop(0) if cmd_args else None
|
||||
elif op in ('new','transfer','sweep','label'):
|
||||
elif op in ('new', 'transfer', 'sweep', 'sweep_all', 'label'):
|
||||
if len(cmd_args) != 1:
|
||||
cfg._opts.usage()
|
||||
spec = cmd_args[0]
|
||||
|
|
|
|||
|
|
@ -217,7 +217,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}'
|
||||
oneline_fs = '{a:7} {b:8} {c:19} {d:13} {e:9} {f:6} {x:2} {g:6} {h:17} {j}'
|
||||
chksum_nchars = 6
|
||||
xmrwallet_tx_data = namedtuple('xmrwallet_tx_data',[
|
||||
'op',
|
||||
|
|
@ -254,7 +254,7 @@ class MoneroMMGenTX:
|
|||
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))),
|
||||
e = purple(d.op.replace('_', ' ').title().ljust(9)),
|
||||
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 ),
|
||||
|
|
@ -640,6 +640,7 @@ class MoneroWalletOps:
|
|||
'new',
|
||||
'transfer',
|
||||
'sweep',
|
||||
'sweep_all',
|
||||
'relay',
|
||||
'txview',
|
||||
'txlist',
|
||||
|
|
@ -663,6 +664,7 @@ class MoneroWalletOps:
|
|||
'new',
|
||||
'transfer',
|
||||
'sweep',
|
||||
'sweep_all',
|
||||
'dump',
|
||||
'restore' )
|
||||
|
||||
|
|
@ -1138,11 +1140,13 @@ class MoneroWalletOps:
|
|||
unsigned_txset = res['unsigned_txset'] if self.cfg.watch_only else None,
|
||||
)
|
||||
|
||||
def make_sweep_tx(self,account,dest_acct,dest_addr_idx,addr):
|
||||
def make_sweep_tx(self, account, dest_acct, dest_addr_idx, addr, addrs_data):
|
||||
res = self.c.call(
|
||||
'sweep_all',
|
||||
address = addr,
|
||||
account_index = account,
|
||||
subaddr_indices = list(range(len(addrs_data[account]['addresses'])))
|
||||
if self.parent.name == 'sweep_all' else [],
|
||||
priority = self.cfg.priority or None,
|
||||
do_not_relay = True,
|
||||
get_tx_hex = True,
|
||||
|
|
@ -1546,7 +1550,7 @@ class MoneroWalletOps:
|
|||
else:
|
||||
return s # None or empty string
|
||||
|
||||
if self.name == 'sweep':
|
||||
if self.name in ('sweep', 'sweep_all'):
|
||||
self.dest_acct = None if m[4] is None else int(m[4])
|
||||
elif self.name == 'transfer':
|
||||
self.dest_addr = CoinAddr(self.proto,m[3])
|
||||
|
|
@ -1592,7 +1596,7 @@ class MoneroWalletOps:
|
|||
cfg = self.cfg,
|
||||
daemon = wd2 )
|
||||
|
||||
def create_tx(self, h, accts_data):
|
||||
def create_tx(self, h, accts_data, addrs_data):
|
||||
|
||||
def create_new_addr_maybe(h, account, label=None):
|
||||
if keypress_confirm(self.cfg, f'\nCreate new address for account #{account}?'):
|
||||
|
|
@ -1657,7 +1661,7 @@ class MoneroWalletOps:
|
|||
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))
|
||||
return (h, h.make_sweep_tx(self.account, dest_acct, dest_addr_idx, dest_addr, addrs_data))
|
||||
|
||||
@property
|
||||
def add_desc(self):
|
||||
|
|
@ -1682,13 +1686,13 @@ class MoneroWalletOps:
|
|||
h = self.rpc(self,self.source)
|
||||
|
||||
h.open_wallet('source')
|
||||
accts_data = h.get_accts()[0]
|
||||
accts_data, addrs_data = h.get_accts()
|
||||
|
||||
self.check_account_exists(accts_data, self.account)
|
||||
|
||||
h.print_addrs(accts_data,self.account)
|
||||
|
||||
h, new_tx = self.create_tx(h, accts_data)
|
||||
h, new_tx = self.create_tx(h, accts_data, addrs_data)
|
||||
|
||||
msg('\n' + new_tx.get_info(indent=' '))
|
||||
|
||||
|
|
@ -1715,6 +1719,9 @@ class MoneroWalletOps:
|
|||
else:
|
||||
die(1,'\nExiting at user request')
|
||||
|
||||
class sweep_all(sweep):
|
||||
stem = 'sweep'
|
||||
|
||||
class transfer(sweep):
|
||||
stem = 'transferr'
|
||||
spec_id = 'transfer_spec'
|
||||
|
|
@ -1724,7 +1731,7 @@ class MoneroWalletOps:
|
|||
def add_desc(self):
|
||||
return f': {self.amount} XMR to {self.dest_addr}'
|
||||
|
||||
def create_tx(self, h, accts_data):
|
||||
def create_tx(self, h, accts_data, addrs_data):
|
||||
msg(f'\n Creating {self.name} transaction...')
|
||||
return (h, h.make_transfer_tx(self.account, self.dest_addr, self.amount))
|
||||
|
||||
|
|
|
|||
|
|
@ -528,7 +528,6 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
arg2,
|
||||
tx_relay_parm = None,
|
||||
no_relay = False,
|
||||
return_amt = False,
|
||||
use_existing = False,
|
||||
add_opts = [],
|
||||
add_desc = None,
|
||||
|
|
@ -558,7 +557,7 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
if op == 'sign':
|
||||
return t
|
||||
|
||||
if op == 'sweep':
|
||||
if op in ('sweep', 'sweep_all'):
|
||||
desc = 'address' if re.match(r'.*:\d+$', arg2) else 'account'
|
||||
t.expect(
|
||||
rf'Create new {desc} .* \(y/N\): ',
|
||||
|
|
@ -567,9 +566,6 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
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())
|
||||
|
||||
dtype = 'unsigned' if data.autosign else 'signed'
|
||||
t.expect(f'Save {dtype} transaction? (y/N): ','y')
|
||||
t.written_to_file(f'{dtype.capitalize()} transaction')
|
||||
|
|
@ -580,7 +576,7 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
|
||||
t.read()
|
||||
|
||||
return t if do_ret else amt if return_amt else t.ok()
|
||||
return t if do_ret else t.ok()
|
||||
|
||||
def sweep_to_wallet(self):
|
||||
self.do_op('sweep', 'alice', '1:0,2')
|
||||
|
|
@ -657,29 +653,15 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
return await self.mine_chk('alice',2,1,lambda x: x.ub > 0.9,'unlocked balance > 0.9')
|
||||
|
||||
async def sweep_create_and_send(self):
|
||||
bal = XMRAmt('0')
|
||||
get_file_with_ext(self.users['alice'].udir, 'sigtx', delete_all=True)
|
||||
|
||||
self.do_op('sweep_all', 'alice', '2:1,3', no_relay=True, use_existing=True)
|
||||
ok()
|
||||
|
||||
self.relay_tx(f'--tx-relay-daemon={self.tx_relay_daemon_parm}')
|
||||
|
||||
min_bal = XMRAmt('0.9')
|
||||
|
||||
for i in range(4):
|
||||
if i:
|
||||
ok()
|
||||
get_file_with_ext(self.users['alice'].udir,'sigtx',delete_all=True)
|
||||
send_amt = self.do_op(
|
||||
'sweep','alice','2:1,3', # '2:1,3'
|
||||
no_relay = True,
|
||||
use_existing = True,
|
||||
add_desc = f'TX #{i+1}',
|
||||
return_amt = True )
|
||||
ok()
|
||||
self.relay_tx(f'--tx-relay-daemon={self.tx_relay_daemon_parm}',add_desc=f'send amt: {send_amt} XMR')
|
||||
await self.mine_chk('alice',2,1,lambda x: 'chk_bal_chg','balance has changed')
|
||||
ok()
|
||||
bal_info = await self.mine_chk('alice',3,0,lambda x,y=bal: x.ub > y, f'bal > {bal}',return_bal=True)
|
||||
bal += bal_info.ub
|
||||
if bal >= min_bal:
|
||||
return 'ok'
|
||||
|
||||
return False
|
||||
return await self.mine_chk('alice', 3, 0, lambda x: x.ub > min_bal, f'bal > {min_bal}')
|
||||
|
||||
# wallet methods
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue