main_xmrwallet.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #!/usr/bin/env python3
  2. #
  3. # MMGen Wallet, a terminal-based cryptocurrency wallet
  4. # Copyright (C)2013-2025 The MMGen Project <mmgen@tuta.io>
  5. # Licensed under the GNU General Public License, Version 3:
  6. # https://www.gnu.org/licenses
  7. # Public project repositories:
  8. # https://github.com/mmgen/mmgen-wallet
  9. # https://gitlab.com/mmgen/mmgen-wallet
  10. """
  11. mmgen-xmrwallet: Perform various Monero wallet and transacting operations for
  12. addresses in an MMGen XMR key-address file
  13. """
  14. import asyncio
  15. from .cfg import gc, Config
  16. from .util import die, fmt_dict
  17. from . import xmrwallet
  18. opts_data = {
  19. 'sets': [
  20. ('autosign', True, 'watch_only', True),
  21. ('autosign_mountpoint', bool, 'autosign', True),
  22. ('autosign_mountpoint', bool, 'watch_only', True),
  23. ],
  24. 'text': {
  25. 'desc': """Perform various Monero wallet and transacting operations for
  26. addresses in an MMGen XMR key-address file""",
  27. 'usage2': [
  28. '[opts] create | sync | list | view | listview | dump-json | dump | restore [xmr_keyaddrfile] [wallets]',
  29. '[opts] label [xmr_keyaddrfile] LABEL_SPEC',
  30. '[opts] new [xmr_keyaddrfile] NEW_ADDRESS_SPEC',
  31. '[opts] transfer [xmr_keyaddrfile] TRANSFER_SPEC',
  32. '[opts] sweep | sweep_all [xmr_keyaddrfile] SWEEP_SPEC',
  33. '[opts] submit [TX_file]',
  34. '[opts] relay <TX_file>',
  35. '[opts] resubmit | abort (for use with --autosign only)',
  36. '[opts] txview | txlist [TX_file] ...',
  37. '[opts] export-outputs | export-outputs-sign | import-key-images [wallets]',
  38. ],
  39. 'options': """
  40. -h, --help Print this help message
  41. --, --longhelp Print help message for long (global) options
  42. -a, --autosign Use appropriate outdir and other params for
  43. autosigning operations (implies --watch-only).
  44. When this option is in effect, filename argu-
  45. ments must be omitted, as files are located
  46. automatically.
  47. -c, --compat Adjust configuration for compatibility with
  48. the mmgen-tx{{create,sign,send}} family of
  49. commands. Currently equivalent to
  50. ‘-w {tw_dir}’
  51. -f, --priority=N Specify an integer priority ‘N’ for inclusion
  52. of a transaction in the blockchain (higher
  53. number means higher fee). Valid parameters:
  54. {tp}. If option
  55. is omitted, the default priority will be used
  56. -F, --full-address Print addresses in full instead of truncating
  57. -m, --autosign-mountpoint=P Specify the autosign mountpoint (defaults to
  58. ‘/mnt/mmgen_autosign’, implies --autosign)
  59. -b, --rescan-blockchain Rescan the blockchain if wallet fails to sync
  60. -d, --outdir=D Save transaction files to directory 'D'
  61. instead of the working directory
  62. -D, --daemon=H:P Connect to the monerod at {dhp}
  63. -e, --skip-empty-accounts Skip display of empty accounts in wallets
  64. where applicable
  65. -E, --skip-empty-addresses Skip display of used empty addresses in
  66. wallets where applicable
  67. -k, --use-internal-keccak-module Force use of the internal keccak module
  68. -p, --hash-preset=P Use scrypt hash preset 'P' for password
  69. hashing (default: '{gc.dfl_hash_preset}')
  70. -P, --rescan-spent Perform a rescan of spent outputs. Used only
  71. with the ‘export-outputs-sign’ operation
  72. -R, --tx-relay-daemon=H:P[:H:P] Relay transactions via a monerod specified by
  73. {rdhp}
  74. -r, --restore-height=H Scan from height 'H' when creating wallets.
  75. Use special value ‘current’ to create empty
  76. wallet at current blockchain height.
  77. -R, --no-relay Save transaction to file instead of relaying
  78. -s, --no-start-wallet-daemon Don’t start the wallet daemon at startup
  79. -S, --no-stop-wallet-daemon Don’t stop the wallet daemon at exit
  80. -W, --watch-only Create or operate on watch-only wallets
  81. -w, --wallet-dir=D Output or operate on wallets in directory 'D'
  82. instead of the working directory
  83. -U, --wallet-rpc-user=user Wallet RPC username (currently: {cfg.monero_wallet_rpc_user!r})
  84. -P, --wallet-rpc-password=pass Wallet RPC password (currently: [scrubbed])
  85. """,
  86. 'notes': """
  87. {xmrwallet_help}
  88. """
  89. },
  90. 'code': {
  91. 'options': lambda cfg, help_notes, s: s.format(
  92. dhp = xmrwallet.uarg_info['daemon'].annot,
  93. rdhp = xmrwallet.uarg_info['tx_relay_daemon'].annot,
  94. cfg = cfg,
  95. gc = gc,
  96. tw_dir = help_notes('tw_dir'),
  97. tp = fmt_dict(xmrwallet.tx_priorities, fmt='equal_compact')
  98. ),
  99. 'notes': lambda help_mod, s: s.format(
  100. xmrwallet_help = help_mod('xmrwallet')
  101. )
  102. }
  103. }
  104. cfg = Config(opts_data=opts_data, init_opts={'coin':'xmr'})
  105. cmd_args = cfg._args
  106. if cmd_args and cfg.autosign and (
  107. cmd_args[0].replace('-', '_') in (
  108. xmrwallet.kafile_arg_ops
  109. + ('export_outputs', 'export_outputs_sign', 'import_key_images', 'txview', 'txlist')
  110. )
  111. or len(cmd_args) == 1 and cmd_args[0] in ('submit', 'resubmit', 'abort')
  112. ):
  113. cmd_args.insert(1, None)
  114. if len(cmd_args) < 2:
  115. cfg._usage()
  116. usr_op = cmd_args.pop(0)
  117. op = usr_op.replace('-', '_')
  118. infile = cmd_args.pop(0)
  119. wallets = spec = None
  120. match op:
  121. case 'relay' | 'submit' | 'resubmit' | 'abort':
  122. if len(cmd_args) != 0:
  123. cfg._usage()
  124. case 'txview' | 'txlist':
  125. infile = [infile] + cmd_args
  126. case 'create' | 'sync' | 'list' | 'view' | 'listview' | 'dump_json' | 'dump' | 'restore':
  127. if len(cmd_args) > 1:
  128. cfg._usage()
  129. wallets = cmd_args.pop(0) if cmd_args else None
  130. case 'new' | 'transfer' | 'sweep' | 'sweep_all' | 'label':
  131. if len(cmd_args) != 1:
  132. cfg._usage()
  133. spec = cmd_args[0]
  134. case 'export_outputs' | 'export_outputs_sign' | 'import_key_images':
  135. if not cfg.autosign:
  136. die(1, f'--autosign must be used with command {usr_op!r}')
  137. if len(cmd_args) > 1:
  138. cfg._usage()
  139. wallets = cmd_args.pop(0) if cmd_args else None
  140. case _:
  141. die(1, f'{usr_op!r}: unrecognized operation')
  142. m = xmrwallet.op(op, cfg, infile, wallets, spec=spec)
  143. if asyncio.run(m.main()):
  144. m.post_main_success()
  145. else:
  146. m.post_main_failure()