mmgen-txsend: new process_tx() function: tx.online: cleanups

This commit is contained in:
The MMGen Project 2026-02-01 09:11:08 +00:00
commit 392b3700af
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
8 changed files with 69 additions and 50 deletions

View file

@ -17,10 +17,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
mmgen-txbump: Create, and optionally send and sign, a replacement transaction
on supporting networks
mmgen-txbump: Create, and optionally send and sign, a replacement transaction on supported networks
"""
import sys
from .cfg import gc, Config
from .util import msg, msg_r, die, async_run
from .color import green
@ -207,7 +208,7 @@ async def main():
TxKeys(cfg, tx2, seedfiles=seedfiles, keylist=kl, keyaddrlist=kal).keys):
tx4 = await OnlineSignedTX(cfg=cfg, data=tx3.__dict__)
tx4.file.write(ask_write=False)
await tx4.send(cfg, asi if cfg.autosign else None)
sys.exit(await tx4.send(cfg, asi if cfg.autosign else None))
else:
die(2, 'Transaction could not be signed')
else:

View file

@ -20,6 +20,8 @@
mmgen-txdo: Create, sign and send an online MMGen transaction
"""
import sys
from .cfg import gc, Config
from .util import die, fmt_list, async_run
from .subseed import SubSeedIdxRange
@ -192,8 +194,8 @@ async def main():
if tx3:
tx3.file.write(ask_write=False)
tx4 = await SentTX(cfg=cfg, data=tx3.__dict__)
await tx4.send(cfg, asi=None)
return await tx4.send(cfg, asi=None)
else:
die(2, 'Transaction could not be signed')
async_run(cfg, main)
sys.exit(async_run(cfg, main))

View file

@ -110,11 +110,9 @@ def init_autosign(arg):
si = Signable.automount_transaction(asi)
if cfg.abort:
si.shred_abortable() # prompts user, then raises exception or exits
elif post_send_op and (si.unsent or si.unsigned):
die(1, 'Transaction is {}'.format('unsent' if si.unsent else 'unsigned'))
elif post_send_op:
if si.unsent:
die(1, 'Transaction is unsent')
if si.unsigned:
die(1, 'Transaction is unsigned')
if not is_int(arg):
die(2, f'{arg}: invalid transaction index (must be a non-negative integer)')
tx_idx = int(arg)
@ -139,38 +137,28 @@ if not cfg.status:
from .tx import OnlineSignedTX
async def main():
async def process_tx(tx):
global cfg
if cfg.autosign and post_send_op:
tx = await si.get_last_sent(idx=tx_idx)
else:
tx = await OnlineSignedTX(
cfg = cfg,
filename = infile,
automount = cfg.autosign,
quiet_open = True)
cfg._util.vmsg(f'Getting {tx.desc}{tx.infile}')
if tx.is_compat:
return await tx.compat_send()
cfg = Config({'_clone': cfg, 'proto': tx.proto, 'coin': tx.proto.coin})
if cfg.tx_proxy:
from .tx.tx_proxy import check_client
check_client(cfg)
from .rpc import rpc_init
tx.rpc = await rpc_init(cfg)
cfg._util.vmsg(f'Getting {tx.desc}{tx.infile}')
if cfg.mark_sent:
await tx.post_send(asi)
sys.exit(0)
txcfg = Config({'_clone': cfg, 'proto': tx.proto, 'coin': tx.proto.coin})
if not post_send_op:
if cfg.tx_proxy:
from .tx.tx_proxy import check_client
check_client(txcfg)
from .rpc import rpc_init
tx.rpc = await rpc_init(txcfg)
if not post_send_op:
if cfg.mark_sent:
await tx.post_send(asi)
return 0
if tx.is_swap and not tx.check_swap_expiry():
die(1, 'Swap quote has expired. Please re-create the transaction')
@ -180,6 +168,16 @@ async def main():
if not cfg.autosign:
tx.file.write(ask_write_default_yes=True)
await tx.send(cfg, asi)
return await tx.send(txcfg, asi)
async_run(cfg, main)
async def main():
if cfg.autosign and post_send_op:
return await process_tx(await si.get_last_sent(idx=tx_idx))
else:
return await process_tx(await OnlineSignedTX(
cfg = cfg,
filename = infile,
automount = cfg.autosign,
quiet_open = True))
sys.exit(async_run(cfg, main))

View file

@ -26,6 +26,7 @@ class Completed(Base):
'network': proto.network})
self.proto = proto
self.filename = filename
self.infile = filename
@cached_property
def compat_tx(self):

View file

@ -15,17 +15,20 @@ proto.xmr.tx.online: Monero online signed transaction class
from .completed import Completed
class OnlineSigned(Completed):
desc = 'signed transaction'
async def compat_send(self):
"""
returns integer exit val to system
"""
from ....xmrwallet import op as xmrwallet_op
op_name = 'daemon' if self.cfg.status else 'submit'
op = xmrwallet_op(op_name, self.cfg, self.filename, None, compat_call=True)
if self.cfg.status:
from ....util import msg, ymsg, suf
from ....util import msg, msg_r, ymsg, suf
ret = 0
txid = self.compat_tx.data.txid
if self.cfg.verbose:
msg(self.compat_tx.get_info())
elif not self.cfg.quiet:
if not (self.cfg.verbose or self.cfg.quiet):
from ....obj import CoinTxID
msg('{} TxID: {}'.format(self.cfg.coin, CoinTxID(txid).hl()))
res = op.dc.call_raw('get_transactions', txs_hashes=[txid])
@ -38,16 +41,19 @@ class OnlineSigned(Completed):
msg('Transaction has {} confirmation{}'.format(confs, suf(confs)))
else:
ymsg('An RPC error occurred while fetching transaction data')
return False
ret = 1
if self.cfg.verbose:
msg_r('\n' + self.compat_tx.get_info())
return ret
else:
await op.restart_wallet_daemon()
return await op.main()
return int(not await op.main())
class Sent(OnlineSigned):
pass
desc = 'sent transaction'
class AutomountOnlineSigned(OnlineSigned):
pass
desc = 'signed automount transaction'
class AutomountSent(AutomountOnlineSigned):
pass
desc = 'sent automount transaction'

View file

@ -12,7 +12,7 @@
tx.online: online signed transaction class
"""
import sys, time, asyncio
import time, asyncio
from ..util import msg, Msg, gmsg, ymsg, make_timestr, die
from ..color import pink, yellow
@ -63,7 +63,9 @@ class OnlineSigned(Signed):
ask_write = False)
async def send(self, cfg, asi):
"""
returns integer exit val to system
"""
status_exitval = None
sent_status = None
all_ok = True
@ -85,9 +87,10 @@ class OnlineSigned(Signed):
if coin_txid := getattr(self, f'coin_txid{idx}', None):
txhex = getattr(self, f'serialized{idx}')
if cfg.status:
cfg._util.qmsg(f'{self.proto.coin} TxID: {coin_txid.hl()}')
if cfg.verbose:
await self.post_network_send(coin_txid)
else:
cfg._util.qmsg(f'{self.proto.coin} TxID: {coin_txid.hl()}')
status_exitval = await self.status.display(idx=idx)
elif cfg.receipt:
if res := await self.get_receipt(coin_txid, receipt_only=True):
@ -147,7 +150,8 @@ class OnlineSigned(Signed):
if status_exitval is not None:
if cfg.verbose:
self.info.view_with_prompt('View transaction details?', pause=False)
sys.exit(status_exitval)
return status_exitval
return 0
class AutomountOnlineSigned(AutomountSigned, OnlineSigned):
pass

View file

@ -224,7 +224,13 @@ class CmdTestAutosignAutomount(CmdTestAutosignThreaded, CmdTestRegtest):
def alice_txsend5(self):
return self._user_txsend('alice', need_rbf=True)
def _alice_txstatus(self, expect, exit_val=None, need_rbf=False, idx=None):
def _alice_txstatus(
self,
expect,
exit_val = None,
need_rbf = False,
idx = None,
verbose = True):
if need_rbf and not self.proto.cap('rbf'):
return 'skip'
@ -232,11 +238,12 @@ class CmdTestAutosignAutomount(CmdTestAutosignThreaded, CmdTestRegtest):
self.insert_device_online()
t = self.spawn(
'mmgen-txsend',
['--alice', '--autosign', '--status', '--verbose']
['--alice', '--autosign', '--status']
+ (['--verbose'] if verbose else [])
+ ([] if idx is None else [str(idx)]),
no_passthru_opts = ['coin'],
exit_val = exit_val)
t.expect(expect)
t.expect(expect, regex=True)
if not exit_val:
t.expect('view: ', 'n')
t.read()

View file

@ -816,7 +816,7 @@ class CmdTestXMRCompat(CmdTestXMRAutosign):
return self._alice_txstatus(['--quiet'], expect_str='confirmations')
def alice_txstatus3(self):
return self._alice_txstatus(['--verbose'], expect_str='Info for transaction .* confirmations')
return self._alice_txstatus(['--verbose'], expect_str='confirmations.*Info for transaction')
def _alice_txstatus(self, add_opts=[], expect_str=None):
return self._alice_txops(