mm-balance 0.2.2__py3-none-any.whl → 0.2.4__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
@@ -5,7 +5,7 @@ import pkgutil
5
5
  from typing import Annotated
6
6
 
7
7
  import typer
8
- from mm_std import PrintFormat, fatal
8
+ from mm_std import PrintFormat, fatal, pretty_print_toml
9
9
 
10
10
  from mm_balance.config import Config
11
11
  from mm_balance.constants import NETWORKS
@@ -27,7 +27,9 @@ def version_callback(value: bool) -> None:
27
27
  def example_callback(value: bool) -> None:
28
28
  if value:
29
29
  data = pkgutil.get_data(__name__, "config/example.toml")
30
- typer.echo(data)
30
+ if data is None:
31
+ fatal("Example config not found")
32
+ pretty_print_toml(data.decode("utf-8"))
31
33
  raise typer.Exit
32
34
 
33
35
 
@@ -47,8 +47,8 @@ addresses = "group: binance_eth"
47
47
  ticker = "USDC"
48
48
  network = "aptos"
49
49
  comment = "swap.thala.apt"
50
- token_address = "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDC"
51
- token_decimals = 6
50
+ token = "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDC"
51
+ decimals = 6
52
52
  addresses = "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af"
53
53
 
54
54
 
mm_balance/config.py CHANGED
@@ -20,8 +20,8 @@ class Group(BaseConfig):
20
20
  comment: str = ""
21
21
  ticker: Annotated[str, StringConstraints(to_upper=True)]
22
22
  network: Network
23
- token_address: str | None = None # If None, it's a native token, for example ETH
24
- token_decimals: int | None = None
23
+ token: str | None = None # Token address. If None, it's a native token, for example ETH
24
+ decimals: int | None = None
25
25
  coingecko_id: str | None = None
26
26
  addresses: Annotated[list[str], BeforeValidator(Validators.addresses(unique=True))]
27
27
  share: Decimal = Decimal(1)
@@ -36,10 +36,10 @@ class Group(BaseConfig):
36
36
 
37
37
  @model_validator(mode="after")
38
38
  def final_validator(self) -> Self:
39
- if self.token_address is None:
40
- self.token_address = detect_token_address(self.ticker, self.network)
41
- if self.token_address is not None and self.network.is_evm_network():
42
- self.token_address = self.token_address.lower()
39
+ if self.token is None:
40
+ self.token = detect_token_address(self.ticker, self.network)
41
+ if self.token is not None and self.network.is_evm_network():
42
+ self.token = self.token.lower()
43
43
  return self
44
44
 
45
45
  def process_addresses(self, address_groups: list[AddressGroup]) -> None:
@@ -33,7 +33,7 @@ def print_prices(config: Config, prices: Prices) -> None:
33
33
  rows = []
34
34
  for ticker, price in prices.items():
35
35
  rows.append(
36
- [ticker, format_number(round(price, config.settings.round_ndigits), config.settings.format_number_separator, "$")]
36
+ [ticker, format_number(price, config.settings.format_number_separator, "$", config.settings.round_ndigits)]
37
37
  )
38
38
  print_table("Prices", ["coin", "usd"], rows)
39
39
 
@@ -3,7 +3,9 @@ from decimal import Decimal
3
3
  from rich.progress import BarColumn, MofNCompleteColumn, Progress, TaskID, TextColumn
4
4
 
5
5
 
6
- def format_number(value: Decimal, separator: str, extra: str | None = None) -> str:
6
+ def format_number(value: Decimal, separator: str, extra: str | None = None, round_ndigits: int | None = None) -> str:
7
+ if round_ndigits is not None and value > 0:
8
+ value = round(value, round_ndigits)
7
9
  str_value = f"{value:,}".replace(",", separator)
8
10
  if extra == "$":
9
11
  return "$" + str_value
mm_balance/result.py CHANGED
@@ -7,6 +7,7 @@ from mm_std import Ok
7
7
  from mm_balance.config import Config, Group
8
8
  from mm_balance.constants import USD_STABLECOINS, Network
9
9
  from mm_balance.price import Prices
10
+ from mm_balance.utils import round_decimal
10
11
  from mm_balance.workers import Task, Workers
11
12
 
12
13
 
@@ -106,7 +107,7 @@ def _create_group_result(config: Config, group: Group, tasks: list[Task], prices
106
107
  coin_value = task.balance.ok
107
108
  usd_value = Decimal(0)
108
109
  if group.ticker in prices:
109
- usd_value = round(coin_value * prices[group.ticker], config.settings.round_ndigits)
110
+ usd_value = round_decimal(coin_value * prices[group.ticker], config.settings.round_ndigits)
110
111
  balance = Balance(balance=coin_value, usd_value=usd_value)
111
112
  balance_sum += balance.balance
112
113
  usd_sum += balance.usd_value
mm_balance/rpc/btc.py CHANGED
@@ -4,11 +4,12 @@ from mm_btc.blockstream import BlockstreamClient
4
4
  from mm_std import Ok, Result
5
5
 
6
6
  from mm_balance.constants import RETRIES_BALANCE
7
+ from mm_balance.utils import scale_and_round
7
8
 
8
9
 
9
10
  def get_balance(address: str, proxies: list[str], round_ndigits: int) -> Result[Decimal]:
10
11
  return (
11
12
  BlockstreamClient(proxies=proxies, attempts=RETRIES_BALANCE)
12
13
  .get_confirmed_balance(address)
13
- .and_then(lambda b: Ok(round(Decimal(b / 100_000_000), round_ndigits)))
14
+ .and_then(lambda b: Ok(scale_and_round(b, 8, round_ndigits)))
14
15
  )
mm_balance/rpc/evm.py CHANGED
@@ -4,6 +4,7 @@ from mm_eth import erc20, rpc
4
4
  from mm_std import Ok, Result
5
5
 
6
6
  from mm_balance.constants import RETRIES_BALANCE, RETRIES_DECIMALS, TIMEOUT_BALANCE, TIMEOUT_DECIMALS
7
+ from mm_balance.utils import scale_and_round
7
8
 
8
9
 
9
10
  def get_balance(
@@ -20,7 +21,7 @@ def get_balance(
20
21
  )
21
22
  else:
22
23
  res = rpc.eth_get_balance(nodes, wallet, proxies=proxies, attempts=RETRIES_BALANCE, timeout=TIMEOUT_BALANCE)
23
- return res.and_then(lambda b: Ok(round(Decimal(b / 10**decimals), round_ndigits)))
24
+ return res.and_then(lambda b: Ok(scale_and_round(b, decimals, round_ndigits)))
24
25
 
25
26
 
26
27
  def get_token_decimals(nodes: list[str], token_address: str, proxies: list[str]) -> Result[int]:
mm_balance/rpc/solana.py CHANGED
@@ -4,6 +4,7 @@ from mm_sol import balance, token
4
4
  from mm_std import Ok, Result
5
5
 
6
6
  from mm_balance.constants import RETRIES_BALANCE, RETRIES_DECIMALS, TIMEOUT_BALANCE, TIMEOUT_DECIMALS
7
+ from mm_balance.utils import scale_and_round
7
8
 
8
9
 
9
10
  def get_balance(
@@ -17,8 +18,7 @@ def get_balance(
17
18
  res = balance.get_token_balance_with_retries(
18
19
  nodes, wallet, token, retries=RETRIES_BALANCE, timeout=TIMEOUT_BALANCE, proxies=proxies
19
20
  )
20
-
21
- return res.and_then(lambda b: Ok(round(Decimal(b / 10**decimals), round_ndigits)))
21
+ return res.and_then(lambda b: Ok(scale_and_round(b, decimals, round_ndigits)))
22
22
 
23
23
 
24
24
  def get_token_decimals(nodes: list[str], token_address: str, proxies: list[str]) -> Result[int]:
@@ -18,12 +18,12 @@ def get_token_decimals(config: Config) -> TokenDecimals:
18
18
 
19
19
  for group in config.groups:
20
20
  # token_decimals is already known
21
- if group.token_decimals is not None:
22
- result[group.network][group.token_address] = group.token_decimals
21
+ if group.decimals is not None:
22
+ result[group.network][group.token] = group.decimals
23
23
  continue
24
24
 
25
25
  # get token_decimals for known native tokens
26
- if group.token_address is None:
26
+ if group.token is None:
27
27
  if group.network.is_evm_network():
28
28
  result[group.network][None] = 18
29
29
  elif group.network == NETWORK_SOLANA:
@@ -36,18 +36,18 @@ def get_token_decimals(config: Config) -> TokenDecimals:
36
36
 
37
37
  # get token_decimals via RPC
38
38
  # TODO: group.token_address must be in normalized form, otherwise it can be different for the same token
39
- if group.token_address in result[group.network]:
39
+ if group.token in result[group.network]:
40
40
  continue # don't request for a token_decimals twice
41
41
 
42
42
  nodes = config.nodes[group.network]
43
43
  if group.network.is_evm_network():
44
- res = evm.get_token_decimals(nodes, group.token_address, proxies)
44
+ res = evm.get_token_decimals(nodes, group.token, proxies)
45
45
  elif group.network == NETWORK_SOLANA:
46
- res = solana.get_token_decimals(nodes, group.token_address, proxies)
46
+ res = solana.get_token_decimals(nodes, group.token, proxies)
47
47
  else:
48
- fatal(f"unsupported network: {group.network}. Cant get token decimals for {group.token_address}")
48
+ fatal(f"unsupported network: {group.network}. Cant get token decimals for {group.token}")
49
49
  if isinstance(res, Err):
50
- fatal(f"can't get decimals for token {group.ticker} / {group.token_address}, error={res.err}")
51
- result[group.network][group.token_address] = res.ok
50
+ fatal(f"can't get decimals for token {group.ticker} / {group.token}, error={res.err}")
51
+ result[group.network][group.token] = res.ok
52
52
 
53
53
  return result
mm_balance/utils.py CHANGED
@@ -8,3 +8,15 @@ def fnumber(value: Decimal, separator: str, extra: str | None = None) -> str:
8
8
  if extra == "%":
9
9
  return str_value + "%"
10
10
  return str_value
11
+
12
+
13
+ def scale_and_round(value: int, decimals: int, round_ndigits: int) -> Decimal:
14
+ if value == 0:
15
+ return Decimal(0)
16
+ return round(Decimal(value / 10**decimals), round_ndigits)
17
+
18
+
19
+ def round_decimal(value: Decimal, round_ndigits: int) -> Decimal:
20
+ if value == Decimal(0):
21
+ return Decimal(0)
22
+ return round(value, round_ndigits)
mm_balance/workers.py CHANGED
@@ -28,7 +28,7 @@ class Workers:
28
28
  self.progress_bar_task: dict[Network, TaskID] = {}
29
29
 
30
30
  for idx, group in enumerate(config.groups):
31
- task_list = [Task(group_index=idx, wallet_address=a, token_address=group.token_address) for a in group.addresses]
31
+ task_list = [Task(group_index=idx, wallet_address=a, token_address=group.token) for a in group.addresses]
32
32
  self.tasks[group.network].extend(task_list)
33
33
 
34
34
  for network in config.networks():
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mm-balance
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Requires-Python: >=3.12
5
5
  Requires-Dist: mm-aptos==0.2.0
6
6
  Requires-Dist: mm-btc==0.3.0
7
- Requires-Dist: mm-eth==0.3.1
8
- Requires-Dist: mm-sol==0.3.1
7
+ Requires-Dist: mm-eth==0.5.3
8
+ Requires-Dist: mm-sol==0.5.1
9
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=AHaD6w97H8ru8nnQv2dcqh9v-d9BVirnlsClbLyHf6M,3796
3
+ mm_balance/config.py,sha256=gywHNWEQL1xeG778cuca5aBoXElLIfoGle3xxW6m_0U,4564
4
+ mm_balance/constants.py,sha256=kqG2zuwv0l-PzDHIrMJVQpfQWiXjr2DsqGPcKmqNJLo,2334
5
+ mm_balance/price.py,sha256=DzvcQngS6wgi_4YWoXxGvOuOkwJvUbN0KI8DeIxbB5A,1494
6
+ mm_balance/result.py,sha256=2bgK4PqS_uFGkYMj6LBiMRh6jRtzsKIkB5csZo0mAEQ,4584
7
+ mm_balance/token_decimals.py,sha256=N3YppB2F3J_OuNkawpAHLVD-4MRCoVjBI01_OoRg5sY,2201
8
+ mm_balance/utils.py,sha256=_UMX3TV350Sr222tAnxGUf0R5McpwloNTQC-U-xiuHc,636
9
+ mm_balance/workers.py,sha256=eg0Ve1xVu3Kd_thfVmPsp6tEdJsYYvs1ipXiu5rKItY,3758
10
+ mm_balance/config/example.toml,sha256=f3Jr40ziOCv_Txf-BysS89c9r7uS-IYHuvwbQ-iftUs,1802
11
+ mm_balance/output/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ mm_balance/output/utils.py,sha256=zyN9igdaXGY_vKfc-3dJ13mH1T7JDke3AeB4MY_3AsA,842
13
+ mm_balance/output/formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ mm_balance/output/formats/json_format.py,sha256=japDhWBVaZ9Znwrhi6BLsUEyn2zyNVxPFYhH7SiILb8,893
15
+ mm_balance/output/formats/table_format.py,sha256=QtWq6ETIccfBTw-9SPypeZrX2zfZwpoCFi_Qe_qOLAA,4751
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=wBMxUjbqdQipVsTFVkj4tk7loErA2czLVfvG8vjFLeE,493
19
+ mm_balance/rpc/evm.py,sha256=LaU2csGL-VlQauCiTX_WFnstvTyZLMP5gDw2LyV53m8,1048
20
+ mm_balance/rpc/solana.py,sha256=10rJ4eEr9sfEfhXx-X2R7bdJ5dL7bVMwHHfJ4R3QR7U,1071
21
+ mm_balance-0.2.4.dist-info/METADATA,sha256=Qw5u6BzDKrcp7ZvP55NIWQx_PjpNVWuZt4wCsenugaM,225
22
+ mm_balance-0.2.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ mm_balance-0.2.4.dist-info/entry_points.txt,sha256=rSnP0ZW1a3ACNwTWM7T53CmOycKbzhG43m2_wseENng,50
24
+ mm_balance-0.2.4.dist-info/RECORD,,
@@ -1,24 +0,0 @@
1
- mm_balance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- mm_balance/cli.py,sha256=KYEfz1ztFpXAxOWlQMJ0rWGnAdkGkvTgVS53pm6YxCw,3683
3
- mm_balance/config.py,sha256=3qEg9xGCoH6WX91dlmjXVVhkCjJf8KFOmfqE8NgSc64,4603
4
- mm_balance/constants.py,sha256=kqG2zuwv0l-PzDHIrMJVQpfQWiXjr2DsqGPcKmqNJLo,2334
5
- mm_balance/price.py,sha256=DzvcQngS6wgi_4YWoXxGvOuOkwJvUbN0KI8DeIxbB5A,1494
6
- mm_balance/result.py,sha256=WsVLbf54cCJ76rIM2zHaOCQXMfZZMczdg8rlC2tDGWY,4533
7
- mm_balance/token_decimals.py,sha256=7XL_x_1ZIhp_cr1TvXwnqLqINUWFGo0j5_5lWuxmwpE,2277
8
- mm_balance/utils.py,sha256=bngYS2WFIakGZO31_ey4MPsllvDhgOxkAnGiXqom3J4,286
9
- mm_balance/workers.py,sha256=vEmmUI-ioMOv1C_Jcz0rnzI3vn7BaVWFnyXddteJkoA,3766
10
- mm_balance/config/example.toml,sha256=15Bjk_zkbhx9CqFgx1kbb2cRSBY9-kPKrej7N_8ulTk,1816
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=japDhWBVaZ9Znwrhi6BLsUEyn2zyNVxPFYhH7SiILb8,893
15
- mm_balance/output/formats/table_format.py,sha256=o_3MGOb0Ug9sqfaR61JDucSEtmFF22KlJoqpFWRuFu8,4758
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=iGDoO7HXP6reLI0bWm0UhEl7-UFZTo5xCWNzFngbITw,458
19
- mm_balance/rpc/evm.py,sha256=ewlMmRrcXKlky3DPNbnUBTVwnvyw7N9iCZLsCX2V14w,1007
20
- mm_balance/rpc/solana.py,sha256=c756415rlhQkHsVsqxHcA7wIaSM64IqyxMohjz8IGhY,1031
21
- mm_balance-0.2.2.dist-info/METADATA,sha256=Ck93hoOiO3Jq7kIHym9IN0XYMolvaYw6dGrhm_8II7I,225
22
- mm_balance-0.2.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
- mm_balance-0.2.2.dist-info/entry_points.txt,sha256=rSnP0ZW1a3ACNwTWM7T53CmOycKbzhG43m2_wseENng,50
24
- mm_balance-0.2.2.dist-info/RECORD,,