Coverage for silkaj/money/balance.py: 86%

70 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-04-22 12:04 +0000

1# Copyright 2016-2025 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 

16from typing import Optional 

17 

18import rich_click as click 

19 

20from silkaj import tools, tui 

21from silkaj.auth import auth_method 

22from silkaj.blockchain.tools import get_head_block 

23from silkaj.money import tools as m_tools 

24from silkaj.public_key import gen_pubkey_checksum, is_pubkey_and_check 

25from silkaj.wot import tools as wt 

26 

27 

28@click.command( 

29 "balance", 

30 help="Wallet·s balance·s. Multiple public keys can be passed, then a sum is computed. Also works with the authentication.", 

31) 

32@click.argument("pubkeys", nargs=-1) 

33@click.pass_context 

34def balance_cmd(ctx: click.Context, pubkeys: str) -> None: 

35 if not tools.has_account_defined(exit_error=False): 

36 # check input pubkeys 

37 if not pubkeys: 

38 ctx.fail("You should specify one or many pubkeys") 

39 pubkeys_list = [] 

40 wrong_pubkeys = False 

41 for input_pubkey in pubkeys: 

42 checked_pubkey = is_pubkey_and_check(input_pubkey) 

43 if checked_pubkey: 

44 pubkey = str(checked_pubkey) 

45 else: 

46 pubkey = input_pubkey 

47 wrong_pubkeys = True 

48 click.echo(f"ERROR: pubkey {pubkey} has a wrong format") 

49 if pubkey in pubkeys_list: 

50 ctx.fail( 

51 f"Pubkey {gen_pubkey_checksum(pubkey)} was specified many times", 

52 ) 

53 pubkeys_list.append(pubkey) 

54 if wrong_pubkeys: 

55 ctx.fail("Please check the pubkeys format reported above.") 

56 

57 total = [0, 0] 

58 for pubkey in pubkeys_list: 

59 inputs_balance = m_tools.get_amount_from_pubkey(pubkey) 

60 show_amount_from_pubkey(pubkey, inputs_balance) 

61 total[0] += inputs_balance[0] 

62 total[1] += inputs_balance[1] 

63 if len(pubkeys_list) > 1: 

64 show_amount_from_pubkey("Total", total) 

65 else: 

66 key = auth_method() 

67 pubkey = key.pubkey 

68 show_amount_from_pubkey(pubkey, m_tools.get_amount_from_pubkey(pubkey)) 

69 

70 

71def show_amount_from_pubkey(label: str, inputs_balance: list[int]) -> None: 

72 """ 

73 Shows the balance of a pubkey. 

74 `label` can be either a pubkey or "Total". 

75 """ 

76 totalAmountInput = inputs_balance[0] 

77 balance = inputs_balance[1] 

78 currency_symbol = tools.get_currency_symbol() 

79 ud_value = m_tools.get_ud_value() 

80 average = get_average() 

81 member = None 

82 

83 # if `pubkey` is a pubkey, get pubkey:checksum and uid 

84 if label != "Total": 

85 member = wt.is_member(label) 

86 label = gen_pubkey_checksum(label) 

87 # display balance table 

88 display = [] 

89 display.append(["Balance of pubkey", label]) 

90 

91 if member: 

92 display.append(["User identifier", member["uid"]]) 

93 

94 if totalAmountInput - balance != 0: 

95 m_tools.display_amount( 

96 display, 

97 "Blockchain", 

98 balance, 

99 ud_value, 

100 currency_symbol, 

101 ) 

102 m_tools.display_amount( 

103 display, 

104 "Pending transaction", 

105 (totalAmountInput - balance), 

106 ud_value, 

107 currency_symbol, 

108 ) 

109 m_tools.display_amount( 

110 display, 

111 "Total balance", 

112 totalAmountInput, 

113 ud_value, 

114 currency_symbol, 

115 ) 

116 if average: 

117 display.append( 

118 [ 

119 "Total relative to M/N", 

120 f"{round(totalAmountInput / average, 2)} x M/N", 

121 ], 

122 ) 

123 

124 table = tui.Table() 

125 table.fill_rows(display) 

126 click.echo(table.draw()) 

127 

128 

129def get_average() -> Optional[int]: 

130 head = get_head_block() 

131 try: 

132 return head["monetaryMass"] / head["membersCount"] 

133 except ZeroDivisionError: 

134 print("The currency reached zero members") 

135 return None