create.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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. xmrwallet.ops.create: Monero wallet ops for the MMGen Suite
  12. """
  13. from pathlib import Path
  14. from ...util import msg, msg_r, gmsg, pp_msg, die
  15. from ...addrlist import ViewKeyAddrList
  16. from .wallet import OpWallet
  17. class OpCreate(OpWallet):
  18. stem = 'creat'
  19. wallet_exists = False
  20. opts = ('restore_height',)
  21. def check_uopts(self):
  22. if self.cfg.restore_height != 'current':
  23. if int(self.cfg.restore_height or 0) < 0:
  24. die(1, f'{self.cfg.restore_height}: invalid value for --restore-height (less than zero)')
  25. if self.cfg.compat:
  26. self.cfg.wallet_dir.mkdir(parents=True, exist_ok=True)
  27. async def process_wallet(self, d, fn, last):
  28. msg_r('') # for pexpect
  29. if self.cfg.restore_height == 'current':
  30. restore_height = self.get_coin_daemon_rpc().call_raw('get_height')['height']
  31. else:
  32. restore_height = self.cfg.restore_height
  33. if self.cfg.watch_only:
  34. ret = self.c.call(
  35. 'generate_from_keys',
  36. filename = fn.name,
  37. password = d.wallet_passwd,
  38. address = d.addr,
  39. viewkey = d.viewkey,
  40. restore_height = restore_height)
  41. else:
  42. from ...xmrseed import xmrseed
  43. ret = self.c.call(
  44. 'restore_deterministic_wallet',
  45. filename = fn.name,
  46. password = d.wallet_passwd,
  47. seed = xmrseed().fromhex(d.sec.wif, tostr=True),
  48. restore_height = restore_height,
  49. language = 'English')
  50. pp_msg(ret) if self.cfg.debug else msg(f' Address: {ret["address"]}')
  51. return True
  52. class OpCreateOffline(OpCreate):
  53. def __init__(self, cfg, uarg_tuple):
  54. super().__init__(cfg, uarg_tuple)
  55. gmsg('\nCreating viewkey-address file for watch-only wallets')
  56. vkal = ViewKeyAddrList(
  57. cfg = self.cfg,
  58. proto = self.proto,
  59. infile = None,
  60. addr_idxs = self.uargs.wallets,
  61. seed = self.seed_src.seed,
  62. skip_chksum_msg = True)
  63. vkf = vkal.file
  64. # before writing viewkey-address file, shred any old ones in the directory:
  65. do_write = True
  66. for f in Path(self.asi.xmr_dir).iterdir():
  67. if f.name == vkf.filename:
  68. do_write = False
  69. elif f.name.endswith(vkf.ext):
  70. from ...fileutil import shred_file
  71. msg(f'Shredding old viewkey-address file ‘{f}’')
  72. shred_file(self.cfg, f, iterations=15)
  73. if do_write:
  74. vkf.write(outdir=self.asi.xmr_dir)
  75. else:
  76. msg(f'Viewkey-address file ‘{vkf.filename}’ already exists, skipping creation')