mm-balance 0.1.17__py3-none-any.whl → 0.1.19__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
mm_balance/cli.py CHANGED
@@ -46,7 +46,7 @@ def cli(
46
46
  zip_password = "" # nosec
47
47
  if config_path.name.endswith(".zip"):
48
48
  zip_password = getpass.getpass("zip password")
49
- config = Config.read_config(config_path, zip_password=zip_password)
49
+ config = Config.read_config_or_exit(config_path, zip_password=zip_password)
50
50
 
51
51
  if print_format is not None:
52
52
  config.print_format = print_format
mm_balance/constants.py CHANGED
@@ -1,5 +1,3 @@
1
- from typing import Any
2
-
3
1
  from pydantic import GetCoreSchemaHandler
4
2
  from pydantic_core import CoreSchema, core_schema
5
3
 
@@ -11,11 +9,13 @@ TIMEOUT_DECIMALS = 5
11
9
 
12
10
 
13
11
  class Network(str):
12
+ __slots__ = ()
13
+
14
14
  def is_evm_network(self) -> bool:
15
15
  return self in [NETWORK_ETHEREUM, NETWORK_ARBITRUM_ONE, NETWORK_OP_MAINNET] or self.startswith("evm-")
16
16
 
17
17
  @classmethod
18
- def __get_pydantic_core_schema__(cls, _source_type: Any, handler: GetCoreSchemaHandler) -> CoreSchema:
18
+ def __get_pydantic_core_schema__(cls, _source_type: object, handler: GetCoreSchemaHandler) -> CoreSchema:
19
19
  return core_schema.no_info_after_validator_function(cls, handler(str))
20
20
 
21
21
 
File without changes
@@ -7,7 +7,7 @@ def format_number(value: Decimal, separator: str, extra: str | None = None) -> s
7
7
  str_value = f"{value:,}".replace(",", separator)
8
8
  if extra == "$":
9
9
  return "$" + str_value
10
- elif extra == "%":
10
+ if extra == "%":
11
11
  return str_value + "%"
12
12
  return str_value
13
13
 
mm_balance/price.py CHANGED
@@ -1,14 +1,15 @@
1
+ from collections import defaultdict
1
2
  from decimal import Decimal
2
3
 
3
4
  import pydash
4
- from mm_std import fatal, hr
5
+ from mm_std import hr
5
6
  from mm_std.random_ import random_str_choice
6
7
 
7
8
  from mm_balance.config import Config, Group
8
9
  from mm_balance.constants import RETRIES_COINGECKO_PRICES, TICKER_TO_COINGECKO_ID
9
10
 
10
11
 
11
- class Prices(dict[str, Decimal]):
12
+ class Prices(defaultdict[str, Decimal]):
12
13
  """
13
14
  A Prices class representing a mapping from coin names to their prices.
14
15
 
@@ -20,29 +21,28 @@ class Prices(dict[str, Decimal]):
20
21
  def get_prices(config: Config) -> Prices:
21
22
  result = Prices()
22
23
 
23
- coins = pydash.uniq([group.ticker for group in config.groups])
24
- coingecko_ids = pydash.uniq([get_coingecko_id(group) for group in config.groups])
24
+ coingecko_map: dict[str, str] = {} # ticker -> coingecko_id
25
25
 
26
- url = f"https://api.coingecko.com/api/v3/simple/price?ids={",".join(coingecko_ids)}&vs_currencies=usd"
26
+ for group in config.groups:
27
+ coingecko_id = get_coingecko_id(group)
28
+ if coingecko_id:
29
+ coingecko_map[group.ticker] = coingecko_id
30
+
31
+ url = f"https://api.coingecko.com/api/v3/simple/price?ids={','.join(coingecko_map.values())}&vs_currencies=usd"
27
32
  for _ in range(RETRIES_COINGECKO_PRICES):
28
33
  res = hr(url, proxy=random_str_choice(config.proxies))
29
34
  if res.code != 200:
30
35
  continue
31
36
 
32
- for idx, coin in enumerate(coins):
33
- if coingecko_ids[idx] in res.json:
34
- result[coin] = Decimal(str(pydash.get(res.json, f"{coingecko_ids[idx]}.usd")))
35
- else:
36
- fatal("Can't get price for {coin} from coingecko, coingecko_id={coingecko_ids[idx]}")
37
+ for ticker, coingecko_id in coingecko_map.items():
38
+ if coingecko_id in res.json:
39
+ result[ticker] = Decimal(str(pydash.get(res.json, f"{coingecko_id}.usd")))
40
+ break
37
41
 
38
42
  return result
39
43
 
40
44
 
41
- def get_coingecko_id(group: Group) -> str:
45
+ def get_coingecko_id(group: Group) -> str | None:
42
46
  if group.coingecko_id:
43
47
  return group.coingecko_id
44
- coingecko_id = TICKER_TO_COINGECKO_ID.get(group.ticker)
45
- if coingecko_id:
46
- return coingecko_id
47
-
48
- fatal(f"Can't get coingecko_id for {group.ticker}. Please add coingecko_id to the config.")
48
+ return TICKER_TO_COINGECKO_ID.get(group.ticker)
mm_balance/result.py CHANGED
@@ -102,17 +102,16 @@ def _create_group_result(config: Config, group: Group, tasks: list[Task], prices
102
102
  balance: Balance | str
103
103
  if task.balance is None:
104
104
  balance = "balance is None! Something went wrong."
105
+ elif isinstance(task.balance, Ok):
106
+ coin_value = task.balance.ok
107
+ usd_value = Decimal(0)
108
+ if group.ticker in prices:
109
+ usd_value = round(coin_value * prices[group.ticker], config.round_ndigits)
110
+ balance = Balance(balance=coin_value, usd_value=usd_value)
111
+ balance_sum += balance.balance
112
+ usd_sum += balance.usd_value
105
113
  else:
106
- if isinstance(task.balance, Ok):
107
- coin_value = task.balance.ok
108
- usd_value = Decimal(0)
109
- if group.ticker in prices:
110
- usd_value = round(coin_value * prices[group.ticker], config.round_ndigits)
111
- balance = Balance(balance=coin_value, usd_value=usd_value)
112
- balance_sum += balance.balance
113
- usd_sum += balance.usd_value
114
- else:
115
- balance = task.balance.err
114
+ balance = task.balance.err
116
115
  addresses.append(AddressBalance(address=task.wallet_address, balance=balance))
117
116
 
118
117
  balance_sum_share = balance_sum * group.share
mm_balance/rpc/aptos.py CHANGED
@@ -10,7 +10,7 @@ def get_balance(
10
10
  nodes: list[str], wallet: str, token: str | None, decimals: int, proxies: list[str], round_ndigits: int
11
11
  ) -> Result[Decimal]:
12
12
  if token is None:
13
- token = "0x1::aptos_coin::AptosCoin" # nosec
13
+ token = "0x1::aptos_coin::AptosCoin" # noqa: S105 # nosec
14
14
  return balance.get_decimal_balance_with_retries(
15
15
  RETRIES_BALANCE,
16
16
  nodes,
@@ -28,9 +28,7 @@ def get_token_decimals(config: Config) -> TokenDecimals:
28
28
  result[group.network][None] = 18
29
29
  elif group.network == NETWORK_SOLANA:
30
30
  result[group.network][None] = 9
31
- elif group.network == NETWORK_BITCOIN:
32
- result[group.network][None] = 8
33
- elif group.network == NETWORK_APTOS:
31
+ elif group.network in (NETWORK_BITCOIN, NETWORK_APTOS):
34
32
  result[group.network][None] = 8
35
33
  else:
36
34
  fatal(f"Can't get token decimals for native token on network: {group.network}")
mm_balance/utils.py CHANGED
@@ -5,6 +5,6 @@ def fnumber(value: Decimal, separator: str, extra: str | None = None) -> str:
5
5
  str_value = f"{value:,}".replace(",", separator)
6
6
  if extra == "$":
7
7
  return "$" + str_value
8
- elif extra == "%":
8
+ if extra == "%":
9
9
  return str_value + "%"
10
10
  return str_value
mm_balance/workers.py CHANGED
@@ -1,8 +1,8 @@
1
1
  from dataclasses import dataclass
2
2
  from decimal import Decimal
3
+ from typing import TYPE_CHECKING
3
4
 
4
5
  from mm_std import ConcurrentTasks, PrintFormat, Result
5
- from rich.progress import TaskID
6
6
 
7
7
  from mm_balance.config import Config
8
8
  from mm_balance.constants import NETWORK_APTOS, NETWORK_BITCOIN, NETWORK_SOLANA, Network
@@ -10,6 +10,9 @@ from mm_balance.output import utils
10
10
  from mm_balance.rpc import aptos, btc, evm, solana
11
11
  from mm_balance.token_decimals import TokenDecimals
12
12
 
13
+ if TYPE_CHECKING:
14
+ from rich.progress import TaskID
15
+
13
16
 
14
17
  @dataclass
15
18
  class Task:
@@ -20,7 +23,7 @@ class Task:
20
23
 
21
24
 
22
25
  class Workers:
23
- def __init__(self, config: Config, token_decimals: TokenDecimals):
26
+ def __init__(self, config: Config, token_decimals: TokenDecimals) -> None:
24
27
  self.config = config
25
28
  self.token_decimals = token_decimals
26
29
  self.tasks: dict[Network, list[Task]] = {network: [] for network in config.networks()}
@@ -49,9 +52,7 @@ class Workers:
49
52
  def get_errors(self) -> list[Task]:
50
53
  result = []
51
54
  for network in self.tasks:
52
- for task in self.tasks[network]:
53
- if task.balance is not None and task.balance.is_err():
54
- result.append(task)
55
+ result.extend([task for task in self.tasks[network] if task.balance is not None and task.balance.is_err()])
55
56
  return result
56
57
 
57
58
  def _process_network(self, network: Network) -> None:
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: mm-balance
3
+ Version: 0.1.19
4
+ Requires-Python: >=3.12
5
+ Requires-Dist: mm-aptos==0.1.5
6
+ Requires-Dist: mm-btc==0.2.1
7
+ Requires-Dist: mm-eth==0.2.3
8
+ Requires-Dist: mm-solana==0.2.3
9
+ Requires-Dist: typer>=0.15.1
@@ -0,0 +1,24 @@
1
+ mm_balance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ mm_balance/cli.py,sha256=7yQ0DiSDVYeG9lFav-PJnVswncWIfpZsj1G7CZvMDmc,3119
3
+ mm_balance/config.py,sha256=LsmfluUFpTfXMvXUUzGQtiZlz1gliiDrDx4c4SqgPws,5383
4
+ mm_balance/constants.py,sha256=kqG2zuwv0l-PzDHIrMJVQpfQWiXjr2DsqGPcKmqNJLo,2334
5
+ mm_balance/price.py,sha256=9pK2Iy44zTcHIlrja5wC_jV03Q7bJr-S8joNzEsyUl0,1485
6
+ mm_balance/result.py,sha256=rwCSnuyK-u4mz1QmQucFKLC2-vpkSoXfFxbu0MScp9g,4524
7
+ mm_balance/token_decimals.py,sha256=5VZyx29euGtE2KIStQjh6xCcVg1qQweFAykUZU6vkRU,2268
8
+ mm_balance/utils.py,sha256=bngYS2WFIakGZO31_ey4MPsllvDhgOxkAnGiXqom3J4,286
9
+ mm_balance/workers.py,sha256=HujTVy_XxXbFLnZdLh1RjN0q9ziwaRRrQspffBSSLQU,3795
10
+ mm_balance/config/example.yml,sha256=7n72tHsnUbZ64q856IeKHlmt-7PvtAgZlB8t4AS0NzI,1899
11
+ mm_balance/output/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ mm_balance/output/utils.py,sha256=WUFwshFMKZKdcwRtO21nhxqW78JeLAatDyHPZhdV96A,716
13
+ mm_balance/output/formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ mm_balance/output/formats/json_format.py,sha256=yMkZTA6vOUpLSixF7H4H4lVZKShRs4B9qmUR8L-CRvw,866
15
+ mm_balance/output/formats/table_format.py,sha256=qN1uMF1cyAVOH31Gohoc_a4l9-pWTSZ8WRxBBSAwj54,4539
16
+ mm_balance/rpc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ mm_balance/rpc/aptos.py,sha256=1JCYCqDim4tk1axXscaAJRXPd4J6vV1ABFbwMbPgrL0,641
18
+ mm_balance/rpc/btc.py,sha256=ugp90H7YW0kiXIh98bQWk9mQTW20yE-jBiCpRvfoH-U,481
19
+ mm_balance/rpc/evm.py,sha256=ewlMmRrcXKlky3DPNbnUBTVwnvyw7N9iCZLsCX2V14w,1007
20
+ mm_balance/rpc/solana.py,sha256=Lwl5Otqy48g4LWfz9uN7_rkICKUIYJvf88PbIAnfMdc,1051
21
+ mm_balance-0.1.19.dist-info/METADATA,sha256=V4gmUFJZqkwrVTWctBPk0Ocs8sZ4xRMw3dUhDKn_i6o,229
22
+ mm_balance-0.1.19.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ mm_balance-0.1.19.dist-info/entry_points.txt,sha256=rSnP0ZW1a3ACNwTWM7T53CmOycKbzhG43m2_wseENng,50
24
+ mm_balance-0.1.19.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: mm-balance
3
- Version: 0.1.17
4
- Requires-Python: >=3.12
5
- Requires-Dist: mm-aptos==0.1.4
6
- Requires-Dist: mm-btc==0.2.0
7
- Requires-Dist: mm-eth==0.2.0
8
- Requires-Dist: mm-solana==0.2.0
9
- Requires-Dist: typer>=0.15.1
@@ -1,23 +0,0 @@
1
- mm_balance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- mm_balance/cli.py,sha256=LbOyGiF3IFCl2oBJzAzR-CE7QZWiR-Q-p9wIgfqv_r8,3111
3
- mm_balance/config.py,sha256=LsmfluUFpTfXMvXUUzGQtiZlz1gliiDrDx4c4SqgPws,5383
4
- mm_balance/constants.py,sha256=4C2BxYRY_i83Rba5NOXeLLeA0ZTWR9WD6BeyQwiCj_U,2335
5
- mm_balance/price.py,sha256=f6fYhpPVqZE9hH22ypfYb9m-nfE41LeVIvksEvqmz54,1615
6
- mm_balance/result.py,sha256=fG63HrHXWS3kBLHmefxKsRh9tj53dloamO_nv3xFboM,4576
7
- mm_balance/token_decimals.py,sha256=WAz9wbvwjPJEcQnrLyPAf23eGp89t9oP_xBmaEecEG0,2348
8
- mm_balance/utils.py,sha256=YjQMfyAaLiiprjt9CuNbDQSJrLbRoTkb2rurAb6bHDc,288
9
- mm_balance/workers.py,sha256=PGhLVhYYVm2jIAzIiJQYby_UqW0xsRv-wQJURqOUYxg,3767
10
- mm_balance/config/example.yml,sha256=7n72tHsnUbZ64q856IeKHlmt-7PvtAgZlB8t4AS0NzI,1899
11
- mm_balance/output/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- mm_balance/output/utils.py,sha256=Vp-6ev-9YIa3kGZxKzMdoJZQB_KLUaAdQGvgOxmZtrc,718
13
- mm_balance/output/formats/json_format.py,sha256=yMkZTA6vOUpLSixF7H4H4lVZKShRs4B9qmUR8L-CRvw,866
14
- mm_balance/output/formats/table_format.py,sha256=qN1uMF1cyAVOH31Gohoc_a4l9-pWTSZ8WRxBBSAwj54,4539
15
- mm_balance/rpc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- mm_balance/rpc/aptos.py,sha256=6hKGKTs2DPQMa4RmPXzfvjCFjPjN8wjJhRRI6HdI9GM,628
17
- mm_balance/rpc/btc.py,sha256=ugp90H7YW0kiXIh98bQWk9mQTW20yE-jBiCpRvfoH-U,481
18
- mm_balance/rpc/evm.py,sha256=ewlMmRrcXKlky3DPNbnUBTVwnvyw7N9iCZLsCX2V14w,1007
19
- mm_balance/rpc/solana.py,sha256=Lwl5Otqy48g4LWfz9uN7_rkICKUIYJvf88PbIAnfMdc,1051
20
- mm_balance-0.1.17.dist-info/METADATA,sha256=_CWyma3tHq5bD3f8tbimQLwiysvZzUG3TKwWtHNj4a4,229
21
- mm_balance-0.1.17.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
22
- mm_balance-0.1.17.dist-info/entry_points.txt,sha256=rSnP0ZW1a3ACNwTWM7T53CmOycKbzhG43m2_wseENng,50
23
- mm_balance-0.1.17.dist-info/RECORD,,