wallet.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. """
  19. tool.wallet: Wallet routines for the 'mmgen-tool' utility
  20. """
  21. from .common import tool_cmd_base
  22. from ..subseed import SubSeedList
  23. from ..seedsplit import MasterShareIdx
  24. from ..wallet import Wallet
  25. class tool_cmd(tool_cmd_base):
  26. "key, address or subseed generation from an MMGen wallet"
  27. def __init__(self, cfg, *, cmdname=None, proto=None, mmtype=None):
  28. self.need_proto = cmdname in ('gen_key', 'gen_addr')
  29. super().__init__(cfg, cmdname=cmdname, proto=proto, mmtype=mmtype)
  30. def _get_seed_file(self, wallet):
  31. from ..fileutil import get_seed_file
  32. return get_seed_file(
  33. cfg = self.cfg,
  34. wallets = [wallet] if wallet else [],
  35. nargs = 1)
  36. def get_subseed(self, subseed_idx: str, *, wallet=''):
  37. "get the Seed ID of a single subseed by Subseed Index for default or specified wallet"
  38. self.cfg._set_quiet(True)
  39. return Wallet(self.cfg, fn=self._get_seed_file(wallet)).seed.subseed(subseed_idx).sid
  40. def get_subseed_by_seed_id(self, seed_id: str, *, wallet='', last_idx=SubSeedList.dfl_len):
  41. "get the Subseed Index of a single subseed by Seed ID for default or specified wallet"
  42. self.cfg._set_quiet(True)
  43. ret = Wallet(
  44. self.cfg,
  45. fn = self._get_seed_file(wallet)).seed.subseed_by_seed_id(seed_id, last_idx=last_idx)
  46. return ret.ss_idx if ret else None
  47. def list_subseeds(self, subseed_idx_range: str, *, wallet=''):
  48. "list a range of subseed Seed IDs for default or specified wallet"
  49. self.cfg._set_quiet(True)
  50. from ..subseed import SubSeedIdxRange
  51. return Wallet(self.cfg, fn=self._get_seed_file(wallet)).seed.subseeds.format(
  52. *SubSeedIdxRange(subseed_idx_range))
  53. def list_shares(self,
  54. share_count: int,
  55. *,
  56. id_str = 'default',
  57. master_share: f'(min:1, max:{MasterShareIdx.max_val}, 0=no master share)' = 0,
  58. wallet = ''):
  59. "list the Seed IDs of the shares resulting from a split of default or specified wallet"
  60. self.cfg._set_quiet(True)
  61. return Wallet(
  62. self.cfg,
  63. fn = self._get_seed_file(wallet)).seed.split(
  64. share_count,
  65. id_str = id_str,
  66. master_idx = master_share).format()
  67. def gen_key(self, mmgen_addr: str, *, wallet=''):
  68. "generate a single WIF key for specified MMGen address from default or specified wallet"
  69. return self._gen_keyaddr(mmgen_addr, 'wif', wallet=wallet)
  70. def gen_addr(self, mmgen_addr: str, *, wallet=''):
  71. "generate a single MMGen address from default or specified wallet"
  72. return self._gen_keyaddr(mmgen_addr, 'addr', wallet=wallet)
  73. def _gen_keyaddr(self, mmgen_addr, target, *, wallet=''):
  74. from ..addr import MMGenID
  75. from ..addrlist import AddrList, AddrIdxList
  76. addr = MMGenID(self.proto, mmgen_addr)
  77. self.cfg._set_quiet(True)
  78. ss = Wallet(self.cfg, fn=self._get_seed_file(wallet))
  79. if ss.seed.sid != addr.sid:
  80. from ..util import die
  81. die(1, f'Seed ID of requested address ({addr.sid}) does not match wallet ({ss.seed.sid})')
  82. d = AddrList(
  83. cfg = self.cfg,
  84. proto = self.proto,
  85. seed = ss.seed,
  86. addr_idxs = AddrIdxList(fmt_str=str(addr.idx)),
  87. mmtype = addr.mmtype,
  88. skip_chksum = True).data[0]
  89. return {'wif': d.sec.wif, 'addr': d.addr}[target]