help_notes.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #!/usr/bin/env python3
  2. #
  3. # MMGen Wallet, a terminal-based cryptocurrency wallet
  4. # Copyright (C)2013-2026 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. help: help notes functions for MMGen suite commands
  12. """
  13. # To permit concatenation of blocks of help text in any order, each block (if not empty)
  14. # should start with two newlines and end with one newline.
  15. class help_notes:
  16. def __init__(self, proto, cfg):
  17. self.proto = proto
  18. self.cfg = cfg
  19. def cmd_coin_arg(self):
  20. from ..cfg import gc
  21. match self.proto.coin:
  22. case 'BTC':
  23. return gc.prog_name
  24. case _:
  25. return f'{gc.prog_name} --coin={self.proto.coin.lower()}'
  26. def addrimport_args(self):
  27. match self.proto.base_proto:
  28. case 'Monero':
  29. return '[opts]'
  30. case _:
  31. return '[opts] [MMGen address file]'
  32. def txcreate_args(self):
  33. match self.proto.base_proto:
  34. case 'Bitcoin':
  35. if self.cfg.autosign:
  36. return '[ADDR,AMT ... | DATA_SPEC] ADDR'
  37. else:
  38. return '[ADDR,AMT ... | DATA_SPEC] ADDR [addr file ...]'
  39. case 'Monero':
  40. return '[ADDR,AMT]'
  41. case _:
  42. return 'ADDR,AMT [addr file ...]'
  43. def swaptxcreate_args(self):
  44. return 'COIN1 [AMT CHG_ADDR] COIN2 [ADDR]'
  45. def account_info_desc(self):
  46. return 'unspent outputs' if self.proto.base_proto == 'Bitcoin' else 'account info'
  47. def fee_spec_letters(self, *, use_quotes=False, proto=None):
  48. cu = (proto or self.proto).coin_amt.units
  49. pfx, sfx, sep, conj = (('', '', ',', ' or '), ("‘", "’", "’,‘", "’ or ‘"))[use_quotes]
  50. return pfx + sep.join(u[0] for u in cu[:-1]) + ('', conj)[len(cu)>1] + cu[-1][0] + sfx
  51. def stream_interval(self):
  52. from ..tx.new_swap import get_swap_proto_mod
  53. return get_swap_proto_mod(self.cfg.swap_proto).SwapCfg(self.cfg).si.dfl
  54. def fee_spec_names(self, *, proto=None, linebreak=' '):
  55. cu = (proto or self.proto).coin_amt.units
  56. return (
  57. ', '.join(cu[:-1])
  58. + ('', ' and ')[len(cu)>1]
  59. + cu[-1]
  60. + (f',{linebreak}respectively' if len(cu) > 1 else ''))
  61. def dfl_twname(self):
  62. from ..proto.btc.rpc.local import BitcoinRPCClient
  63. return BitcoinRPCClient.dfl_twname
  64. def tw_dir(self):
  65. from ..tw.ctl import TwCtl
  66. twctl_cls = self.proto.base_proto_subclass(TwCtl, 'tw.ctl')
  67. if hasattr(twctl_cls, 'get_tw_dir'):
  68. return twctl_cls.get_tw_dir(self.cfg, self.proto)
  69. else:
  70. raise ValueError(f'protocol {self.proto.name} does not support tracking wallet with store')
  71. def MasterShareIdx(self):
  72. from ..seedsplit import MasterShareIdx
  73. return MasterShareIdx
  74. def tool_help(self):
  75. from ..tool.help import main_help
  76. return main_help()
  77. def dfl_subseeds(self):
  78. from ..subseed import SubSeedList
  79. return str(SubSeedList.dfl_len)
  80. def dfl_seed_len(self):
  81. from ..seed import Seed
  82. return str(Seed.dfl_len)
  83. def password_formats(self):
  84. from ..passwdlist import PasswordList
  85. pwi_fs = '{:8} {:1} {:26} {:<7} {:<7} {}'
  86. return '\n\n ' + '\n '.join(
  87. [pwi_fs.format('Code', '', 'Description', 'Min Len', 'Max Len', 'Default Len')] +
  88. [pwi_fs.format(k, '-', v.desc, v.min_len, v.max_len, v.dfl_len)
  89. for k, v in PasswordList.pw_info.items()])
  90. def dfl_mmtype(self):
  91. from ..addr import MMGenAddrType
  92. return "'{}' or '{}'".format(self.proto.dfl_mmtype, MMGenAddrType.mmtypes[self.proto.dfl_mmtype].name)
  93. def address_types(self):
  94. from ..addr import MMGenAddrType
  95. return """
  96. ADDRESS TYPES:
  97. Code Type Description
  98. ---- ---- -----------
  99. """ + format('\n '.join(['‘{}’ {:<12} - {}'.format(k, v.name, v.desc)
  100. for k, v in MMGenAddrType.mmtypes.items()])) + '\n'
  101. def fmt_codes(self):
  102. from ..wallet import format_fmt_codes
  103. return """
  104. FMT CODES:
  105. """ + '\n '.join(format_fmt_codes().splitlines()) + '\n'
  106. def coin_id(self):
  107. return self.proto.coin_id
  108. def keygen_backends(self):
  109. from ..keygen import get_backends
  110. from ..addr import MMGenAddrType
  111. backends = get_backends(
  112. MMGenAddrType(self.proto, self.cfg.type or self.proto.dfl_mmtype).pubkey_type
  113. )
  114. return ' '.join('{n}:{k}{t}'.format(n=n, k=k, t=('', ' [default]')[n == 1])
  115. for n, k in enumerate(backends, 1))
  116. def coin_daemon_network_ids(self):
  117. from ..daemon import CoinDaemon
  118. from ..util import fmt_list
  119. return fmt_list(CoinDaemon.get_network_ids(self.cfg), fmt='bare')
  120. def tx_proxies(self):
  121. from ..util import fmt_list
  122. return fmt_list(self.cfg._autoset_opts['tx_proxy'].choices, fmt='fancy')
  123. def rel_fee_desc(self):
  124. if self.proto.has_usr_fee:
  125. from ..tx import BaseTX
  126. return BaseTX(cfg=self.cfg, proto=self.proto).rel_fee_desc
  127. else:
  128. return ''
  129. def gas_limit(self, target):
  130. return """
  131. GAS LIMIT
  132. This option specifies the maximum gas allowance for an Ethereum transaction.
  133. It’s generally of interest only for token transactions or swap transactions
  134. from token assets.
  135. Parameter must be an integer or one of the special values ‘fallback’ (for a
  136. locally computed sane default) or ‘auto’ (for gas estimate via an RPC call,
  137. in the case of a token transaction, or locally computed default, in the case
  138. of a standard transaction). The default is ‘auto’.
  139. """ if target == 'swaptx' or self.proto.base_coin == 'ETH' else ''
  140. def fee(self, all_coins=False):
  141. if not self.proto.has_usr_fee:
  142. return ''
  143. from ..tx import BaseTX
  144. text = """
  145. FEE SPECIFICATION
  146. Transaction fees, both on the command line and at the interactive prompt, may
  147. be specified as either absolute coin amounts, using a plain decimal number, or
  148. as {r}, using an integer followed by {l}, for{s}{u}""".format(
  149. r = BaseTX(cfg=self.cfg, proto=self.proto).rel_fee_desc,
  150. l = self.fee_spec_letters(use_quotes=True),
  151. s = '\n' if self.proto.base_coin == 'ETH' else ' ',
  152. u = self.fee_spec_names())
  153. if all_coins:
  154. from ..protocol import init_proto
  155. eth_proto = init_proto(self.cfg, 'eth', need_amt=True)
  156. return text + (
  157. ' (for\nBitcoin, Litecoin and Bitcoin Cash)'
  158. + ", or {r}, using an integer followed\nby {l}, for {u}".format(
  159. r = BaseTX(cfg=self.cfg, proto=eth_proto).rel_fee_desc,
  160. l = self.fee_spec_letters(use_quotes=True, proto=eth_proto),
  161. u = self.fee_spec_names(proto=eth_proto, linebreak='\n'))
  162. + ' (for Ethereum)\n')
  163. else:
  164. return text + '.\n'
  165. def passwd(self):
  166. return """
  167. PASSPHRASE NOTE:
  168. For passphrases all combinations of whitespace are equal, and leading and
  169. trailing space are ignored. This permits reading passphrase or brainwallet
  170. data from a multi-line file with free spacing and indentation.
  171. """
  172. def brainwallet(self):
  173. return """
  174. BRAINWALLET NOTE:
  175. To thwart dictionary attacks, it’s recommended to use a strong hash preset
  176. with brainwallets. For a brainwallet passphrase to generate the correct
  177. seed, the same seed length and hash preset parameters must always be used.
  178. """