Coverage for silkaj/cli.py: 100%

85 statements  

« prev     ^ index     » next       coverage.py v7.6.3, created at 2024-10-18 04:28 +0000

1# Copyright 2016-2024 Maël Azimi <m.a@moul.re> 

2# 

3# Silkaj is free software: you can redistribute it and/or modify 

4# it under the terms of the GNU Affero General Public License as published by 

5# the Free Software Foundation, either version 3 of the License, or 

6# (at your option) any later version. 

7# 

8# Silkaj is distributed in the hope that it will be useful, 

9# but WITHOUT ANY WARRANTY; without even the implied warranty of 

10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

11# GNU Affero General Public License for more details. 

12# 

13# You should have received a copy of the GNU Affero General Public License 

14# along with Silkaj. If not, see <https://www.gnu.org/licenses/>. 

15 

16import contextlib 

17import sys 

18from pathlib import Path 

19 

20import rich_click as click 

21from duniterpy.api.endpoint import endpoint as du_endpoint 

22 

23from silkaj import tools, tui 

24from silkaj.about import about 

25from silkaj.auth import generate_auth_file 

26from silkaj.blockchain.blocks import list_blocks 

27from silkaj.blockchain.difficulty import difficulties 

28from silkaj.blockchain.information import currency_info 

29from silkaj.checksum import checksum_command 

30from silkaj.constants import ( 

31 G1_DEFAULT_ENDPOINT, 

32 G1_TEST_DEFAULT_ENDPOINT, 

33 SILKAJ_VERSION, 

34) 

35from silkaj.g1_monetary_license import license_command 

36from silkaj.money.balance import balance_cmd 

37from silkaj.money.history import transaction_history 

38from silkaj.money.transfer import transfer_money 

39from silkaj.wot import revocation 

40from silkaj.wot.certification import certify 

41from silkaj.wot.lookup import lookup_cmd 

42from silkaj.wot.membership import send_membership 

43from silkaj.wot.status import status 

44 

45click.rich_click.SHOW_ARGUMENTS = True 

46click.rich_click.OPTION_GROUPS = { 

47 "silkaj": [ 

48 { 

49 "name": "Basic options", 

50 "options": ["--help", "--version"], 

51 }, 

52 { 

53 "name": "Endpoint and currency specification", 

54 "options": ["--endpoint", "--gtest"], 

55 }, 

56 { 

57 "name": "Authentication", 

58 "options": [ 

59 "--auth-scrypt", 

60 "--nrp", 

61 "--auth-file", 

62 "--auth-seed", 

63 "--auth-wif", 

64 ], 

65 }, 

66 ], 

67} 

68 

69 

70@click.group() 

71@click.help_option("-h", "--help") 

72@click.version_option(SILKAJ_VERSION, "-v", "--version") 

73@click.option( 

74 "--endpoint", 

75 "-ep", 

76 help=f"Default endpoint reaches Ğ1 currency on its official endpoint: \ 

77{tui.endpoint_link(du_endpoint(G1_DEFAULT_ENDPOINT).host)}. \ 

78--endpoint allows to specify a custom endpoint following the format: <host>:<port>/<path>. \ 

79<port> and <path> are optional. In case no port is specified, it defaults to 443.", 

80 cls=tools.MutuallyExclusiveOption, 

81 mutually_exclusive=["gtest"], 

82) 

83@click.option( 

84 "--gtest", 

85 "-gt", 

86 is_flag=True, 

87 help=f"Uses official ĞTest currency endpoint: \ 

88{tui.endpoint_link(du_endpoint(G1_TEST_DEFAULT_ENDPOINT).host)}. \ 

89Note that --endpoint has precedence over --gtest.", 

90 cls=tools.MutuallyExclusiveOption, 

91 mutually_exclusive=["endpoint"], 

92) 

93@click.option( 

94 "--auth-scrypt", 

95 "--scrypt", 

96 is_flag=True, 

97 help="Scrypt authentication: default method", 

98) 

99@click.option("--nrp", help='Scrypt parameters: defaults N,r,p: "4096,16,1"') 

100@click.option( 

101 "--auth-file", 

102 "-af", 

103 type=click.Path(exists=True, dir_okay=False, path_type=Path), 

104 help="Authentication file path", 

105) 

106@click.option( 

107 "--auth-seed", 

108 "--seed", 

109 is_flag=True, 

110 help="Seed hexadecimal authentication", 

111) 

112@click.option( 

113 "--auth-wif", 

114 "--wif", 

115 is_flag=True, 

116 help="WIF and EWIF authentication methods", 

117) 

118@click.option( 

119 "--display", 

120 "-d", 

121 is_flag=True, 

122 help="Display the generated document before sending it", 

123) 

124@click.option( 

125 "--dry-run", 

126 "-n", 

127 is_flag=True, 

128 help="By-pass licence, confirmation. \ 

129Do not send the document, but display it instead", 

130) 

131@click.pass_context 

132def cli( 

133 ctx: click.Context, 

134 endpoint: str, 

135 gtest: bool, 

136 auth_scrypt: bool, 

137 nrp: str, 

138 auth_file: Path, 

139 auth_seed: bool, 

140 auth_wif: bool, 

141 display: bool, 

142 dry_run: bool, 

143) -> None: 

144 if display and dry_run: 

145 sys.exit("ERROR: display and dry-run options can not be used together") 

146 

147 ctx.obj = {} 

148 ctx.ensure_object(dict) 

149 ctx.obj["ENDPOINT"] = endpoint 

150 ctx.obj["GTEST"] = gtest 

151 ctx.obj["AUTH_SCRYPT"] = auth_scrypt 

152 ctx.obj["AUTH_SCRYPT_PARAMS"] = nrp 

153 ctx.obj["AUTH_FILE_PATH"] = auth_file 

154 ctx.obj["AUTH_SEED"] = auth_seed 

155 ctx.obj["AUTH_WIF"] = auth_wif 

156 ctx.obj["DISPLAY_DOCUMENT"] = display 

157 ctx.obj["DRY_RUN"] = dry_run 

158 ctx.help_option_names = ["-h", "--help"] 

159 

160 

161cli.add_command(about) 

162cli.add_command(generate_auth_file) 

163cli.add_command(checksum_command) 

164cli.add_command(license_command) 

165 

166 

167@cli.group("blockchain", help="Blockchain related commands") 

168def blockchain_group() -> None: 

169 pass 

170 

171 

172blockchain_group.add_command(list_blocks) 

173blockchain_group.add_command(difficulties) 

174blockchain_group.add_command(currency_info) 

175 

176 

177@cli.group("money", help="Money management related commands") 

178def money_group() -> None: 

179 pass 

180 

181 

182money_group.add_command(balance_cmd) 

183money_group.add_command(transaction_history) 

184money_group.add_command(transfer_money) 

185 

186 

187@cli.group("wot", help="Web-of-Trust related commands") 

188def wot_group() -> None: 

189 pass 

190 

191 

192wot_group.add_command(certify) 

193with contextlib.suppress(ModuleNotFoundError): 

194 from silkaj.wot.exclusions import exclusions_command 

195 

196 wot_group.add_command(exclusions_command) 

197 

198wot_group.add_command(lookup_cmd) 

199wot_group.add_command(send_membership) 

200wot_group.add_command(status) 

201 

202 

203@wot_group.group( 

204 "revocation", 

205 help="Create, save, verify or publish revocation document.\n\ 

206Subcommands optionally take the path to the revocation document.", 

207) 

208def revocation_group() -> None: 

209 pass 

210 

211 

212revocation_group.add_command(revocation.create) 

213revocation_group.add_command(revocation.verify) 

214revocation_group.add_command(revocation.publish) 

215revocation_group.add_command(revocation.revoke_now)