mm-balance 0.2.3__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/config/example.toml +2 -2
- mm_balance/config.py +6 -6
- mm_balance/output/formats/table_format.py +1 -1
- mm_balance/output/utils.py +3 -1
- mm_balance/result.py +2 -1
- mm_balance/rpc/btc.py +2 -1
- mm_balance/rpc/evm.py +2 -1
- mm_balance/rpc/solana.py +2 -2
- mm_balance/token_decimals.py +9 -9
- mm_balance/utils.py +12 -0
- mm_balance/workers.py +1 -1
- {mm_balance-0.2.3.dist-info → mm_balance-0.2.4.dist-info}/METADATA +2 -2
- mm_balance-0.2.4.dist-info/RECORD +24 -0
- mm_balance-0.2.3.dist-info/RECORD +0 -24
- {mm_balance-0.2.3.dist-info → mm_balance-0.2.4.dist-info}/WHEEL +0 -0
- {mm_balance-0.2.3.dist-info → mm_balance-0.2.4.dist-info}/entry_points.txt +0 -0
mm_balance/config/example.toml
CHANGED
|
@@ -47,8 +47,8 @@ addresses = "group: binance_eth"
|
|
|
47
47
|
ticker = "USDC"
|
|
48
48
|
network = "aptos"
|
|
49
49
|
comment = "swap.thala.apt"
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
24
|
-
|
|
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.
|
|
40
|
-
self.
|
|
41
|
-
if self.
|
|
42
|
-
self.
|
|
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(
|
|
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
|
|
mm_balance/output/utils.py
CHANGED
|
@@ -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 =
|
|
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(
|
|
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(
|
|
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]:
|
mm_balance/token_decimals.py
CHANGED
|
@@ -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.
|
|
22
|
-
result[group.network][group.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
51
|
-
result[group.network][group.
|
|
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.
|
|
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.
|
|
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.5.
|
|
7
|
+
Requires-Dist: mm-eth==0.5.3
|
|
8
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=AHaD6w97H8ru8nnQv2dcqh9v-d9BVirnlsClbLyHf6M,3796
|
|
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.3.dist-info/METADATA,sha256=5FAngHypNiHnXLneqRH9E3n1jX45TIdJekZ4uAIKs4M,225
|
|
22
|
-
mm_balance-0.2.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
23
|
-
mm_balance-0.2.3.dist-info/entry_points.txt,sha256=rSnP0ZW1a3ACNwTWM7T53CmOycKbzhG43m2_wseENng,50
|
|
24
|
-
mm_balance-0.2.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|