mm-balance 0.1.20__py3-none-any.whl → 0.2.1__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
@@ -19,7 +19,7 @@ app = typer.Typer(no_args_is_help=True, pretty_exceptions_enable=False, add_comp
19
19
 
20
20
  def example_callback(value: bool) -> None:
21
21
  if value:
22
- data = pkgutil.get_data(__name__, "config/example.yml")
22
+ data = pkgutil.get_data(__name__, "config/example.toml")
23
23
  typer.echo(data)
24
24
  raise typer.Exit
25
25
 
@@ -37,6 +37,7 @@ def cli(
37
37
  print_format: Annotated[PrintFormat | None, typer.Option("--format", "-f", help="Print format.")] = None,
38
38
  skip_empty: Annotated[bool | None, typer.Option("--skip-empty", "-s", help="Skip empty balances.")] = None,
39
39
  debug: Annotated[bool | None, typer.Option("--debug", "-d", help="Print debug info.")] = None,
40
+ print_config: Annotated[bool | None, typer.Option("--config", "-c", help="Print config and exit.")] = None,
40
41
  price: Annotated[bool | None, typer.Option("--price/--no-price", help="Print prices.")] = None,
41
42
  _example: Annotated[bool | None, typer.Option("--example", callback=example_callback, help="Print a config example.")] = None,
42
43
  _networks: Annotated[
@@ -46,36 +47,38 @@ def cli(
46
47
  zip_password = "" # nosec
47
48
  if config_path.name.endswith(".zip"):
48
49
  zip_password = getpass.getpass("zip password")
49
- config = Config.read_config_or_exit(config_path, zip_password=zip_password)
50
+ config = Config.read_toml_config_or_exit(config_path, zip_password=zip_password)
51
+ if print_config:
52
+ config.print_and_exit()
50
53
 
51
54
  if print_format is not None:
52
- config.print_format = print_format
55
+ config.settings.print_format = print_format
53
56
  if debug is not None:
54
- config.print_debug = debug
57
+ config.settings.print_debug = debug
55
58
  if skip_empty is not None:
56
- config.skip_empty = skip_empty
59
+ config.settings.skip_empty = skip_empty
57
60
  if price is not None:
58
- config.price = price
61
+ config.settings.price = price
59
62
 
60
- if config.print_debug and config.print_format is PrintFormat.TABLE:
63
+ if config.settings.print_debug and config.settings.print_format is PrintFormat.TABLE:
61
64
  table_format.print_nodes(config)
62
65
  table_format.print_proxy_count(config)
63
66
 
64
67
  token_decimals = get_token_decimals(config)
65
- if config.print_debug and config.print_format is PrintFormat.TABLE:
68
+ if config.settings.print_debug and config.settings.print_format is PrintFormat.TABLE:
66
69
  table_format.print_token_decimals(token_decimals)
67
70
 
68
- prices = get_prices(config) if config.price else Prices()
69
- if config.print_format is PrintFormat.TABLE:
71
+ prices = get_prices(config) if config.settings.price else Prices()
72
+ if config.settings.print_format is PrintFormat.TABLE:
70
73
  table_format.print_prices(config, prices)
71
74
 
72
75
  workers = Workers(config, token_decimals)
73
76
  workers.process()
74
77
 
75
78
  result = create_balances_result(config, prices, workers)
76
- if config.print_format is PrintFormat.TABLE:
79
+ if config.settings.print_format is PrintFormat.TABLE:
77
80
  table_format.print_result(config, result, workers)
78
- elif config.print_format is PrintFormat.JSON:
81
+ elif config.settings.print_format is PrintFormat.JSON:
79
82
  json_format.print_result(config, token_decimals, prices, workers, result)
80
83
  else:
81
84
  fatal("Unsupported print format")
@@ -0,0 +1,83 @@
1
+ [[coins]]
2
+ ticker = "SOL"
3
+ network = "solana"
4
+ addresses = "2ojv9BAiHUrvsm9gxDe7fJSzbNZSJcxZvf8dqmWGHG8S" # binance
5
+
6
+ [[coins]]
7
+ ticker = "USDT"
8
+ network = "solana"
9
+ addresses = "2ojv9BAiHUrvsm9gxDe7fJSzbNZSJcxZvf8dqmWGHG8S" # binance
10
+
11
+ [[coins]]
12
+ ticker = "BTC"
13
+ network = "bitcoin"
14
+ comment = "coldwallets"
15
+ addresses = """
16
+ 34xp4vRoCGJym3xR7yCVPFHoCNxv4Twseo # binance
17
+ bc1qgdjqv0av3q56jvd82tkdjpy7gdp9ut8tlqmgrpmv24sq90ecnvqqjwvw97 # bitfinex
18
+ bc1ql49ydapnjafl5t2cp9zqpjwe6pdgmxy98859v2 # robinhood
19
+ """
20
+ share = 0.1
21
+
22
+ [[coins]]
23
+ ticker = "ETH"
24
+ network = "ethereum"
25
+ comment = "okx"
26
+ addresses = "okx_eth"
27
+
28
+ [[coins]]
29
+ ticker = "USDT"
30
+ network = "ethereum"
31
+ comment = "okx"
32
+ addresses = "okx_eth"
33
+
34
+ [[coins]]
35
+ ticker = "ETH"
36
+ network = "ethereum"
37
+ comment = "binance"
38
+ addresses = "binance_eth"
39
+
40
+ [[coins]]
41
+ ticker = "USDT"
42
+ network = "ethereum"
43
+ comment = "binance"
44
+ addresses = "binance_eth"
45
+
46
+ [[coins]]
47
+ ticker = "USDC"
48
+ network = "aptos"
49
+ comment = "swap.thala.apt"
50
+ token_address = "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDC"
51
+ token_decimals = 6
52
+ addresses = "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af"
53
+
54
+ [[addresses]]
55
+ name = "okx_eth"
56
+ addresses = """
57
+ 0xf59869753f41db720127ceb8dbb8afaf89030de4
58
+ 0x65a0947ba5175359bb457d3b34491edf4cbf7997
59
+ 0xe9172daf64b05b26eb18f07ac8d6d723acb48f99
60
+ 0x4d19c0a5357bc48be0017095d3c871d9afc3f21d
61
+ """
62
+
63
+ [[addresses]]
64
+ name = "binance_eth"
65
+ addresses = """
66
+ 0xf977814e90da44bfa03b6295a0616a897441acec
67
+ 0x47ac0fb4f2d84898e4d9e7b4dab3c24507a6d503
68
+ """
69
+
70
+
71
+ [settings] # all records are optional
72
+ round_ndigits = 4
73
+ price = true
74
+ skip_empty = false
75
+ print_debug = false
76
+ print_format = "table" # table, json
77
+ format_number_separator = ","
78
+ proxies = """
79
+ # env_url: MM_BALANCE_PROXIES_URL
80
+ # socks5://usr:pass@site.com:1234
81
+ # http://site.com:1234
82
+ """
83
+
mm_balance/config.py CHANGED
@@ -1,11 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
- import os
4
3
  from decimal import Decimal
5
4
  from pathlib import Path
6
- from typing import Annotated, Self, cast
5
+ from typing import Annotated, Self
7
6
 
8
- import mm_crypto_utils
9
7
  import pydash
10
8
  from mm_crypto_utils import ConfigValidators
11
9
  from mm_std import BaseConfig, PrintFormat, fatal
@@ -14,6 +12,10 @@ from pydantic import BeforeValidator, Field, StringConstraints, model_validator
14
12
  from mm_balance.constants import DEFAULT_NODES, TOKEN_ADDRESS, Network
15
13
 
16
14
 
15
+ class Validators(ConfigValidators):
16
+ pass
17
+
18
+
17
19
  class Group(BaseConfig):
18
20
  comment: str = ""
19
21
  ticker: Annotated[str, StringConstraints(to_upper=True)]
@@ -21,7 +23,7 @@ class Group(BaseConfig):
21
23
  token_address: str | None = None # If None, it's a native token, for example ETH
22
24
  token_decimals: int | None = None
23
25
  coingecko_id: str | None = None
24
- addresses: Annotated[list[str], BeforeValidator(ConfigValidators.addresses(unique=True))]
26
+ addresses: Annotated[list[str], BeforeValidator(Validators.addresses(unique=True))]
25
27
  share: Decimal = Decimal(1)
26
28
 
27
29
  @property
@@ -41,14 +43,24 @@ class Group(BaseConfig):
41
43
  return self
42
44
 
43
45
  def process_addresses(self, address_groups: list[AddressGroup]) -> None:
44
- addresses: list[str] = []
45
- for address in self.addresses:
46
- if address_group := pydash.find(address_groups, lambda g: g.name == address): # noqa: B023
47
- addresses.extend(address_group.addresses)
46
+ result = []
47
+ for line in self.addresses:
48
+ if line.startswith("file:"):
49
+ path = Path(line.removeprefix("file:").strip()).expanduser()
50
+ if path.is_file():
51
+ result += path.read_text().strip().splitlines()
52
+ else:
53
+ fatal(f"File with addresses not found: {path}")
54
+ elif line.startswith("group:"):
55
+ group_name = line.removeprefix("group:").strip()
56
+ address_group = next((ag for ag in address_groups if ag.name == group_name), None)
57
+ if address_group is None:
58
+ raise ValueError(f"Address group not found: {group_name}")
59
+ result += address_group.addresses
48
60
  else:
49
- # TODO: check address is valid
50
- addresses.append(address)
51
- self.addresses = pydash.uniq(process_file_addresses(addresses))
61
+ result.append(line)
62
+ # TODO: check address is valid. There is network info in the group
63
+ self.addresses = pydash.uniq(result)
52
64
 
53
65
 
54
66
  class AddressGroup(BaseConfig):
@@ -56,20 +68,22 @@ class AddressGroup(BaseConfig):
56
68
  addresses: Annotated[list[str], BeforeValidator(ConfigValidators.addresses(unique=True))]
57
69
 
58
70
 
59
- class Config(BaseConfig):
60
- groups: list[Group] = Field(alias="coins")
61
- addresses: list[AddressGroup] = Field(default_factory=list)
62
-
63
- proxies_url: str | None = None
64
- proxies: list[str] = Field(default_factory=list)
71
+ class Settings(BaseConfig):
72
+ proxies: Annotated[list[str], Field(default_factory=list), BeforeValidator(Validators.proxies())]
65
73
  round_ndigits: int = 4
66
- nodes: dict[Network, list[str]] = Field(default_factory=dict)
67
74
  print_format: PrintFormat = PrintFormat.TABLE
68
75
  price: bool = True
69
76
  skip_empty: bool = False # don't print the address with an empty balance
70
77
  print_debug: bool = False # print debug info: nodes, token_decimals
71
- format_number_separator: str = "," # as thousands separators
78
+ format_number_separator: str = "," # as thousands separators
79
+
80
+
81
+ class Config(BaseConfig):
82
+ groups: list[Group] = Field(alias="coins")
83
+ addresses: list[AddressGroup] = Field(default_factory=list)
84
+ nodes: dict[Network, list[str]] = Field(default_factory=dict)
72
85
  workers: dict[Network, int] = Field(default_factory=dict)
86
+ settings: Settings = Field(default_factory=Settings) # type: ignore[arg-type]
73
87
 
74
88
  def has_share(self) -> bool:
75
89
  return any(g.share != Decimal(1) for g in self.groups)
@@ -79,12 +93,6 @@ class Config(BaseConfig):
79
93
 
80
94
  @model_validator(mode="after")
81
95
  def final_validator(self) -> Self:
82
- # load from proxies_url
83
- if self.proxies_url is not None:
84
- self.proxies += mm_crypto_utils.fetch_proxies_or_fatal(self.proxies_url)
85
- elif os.getenv("MM_BALANCE_PROXIES_URL"):
86
- self.proxies += mm_crypto_utils.fetch_proxies_or_fatal(cast(str, os.getenv("MM_BALANCE_PROXIES_URL")))
87
-
88
96
  # load addresses from address_group
89
97
  for group in self.groups:
90
98
  group.process_addresses(self.addresses)
@@ -105,21 +113,3 @@ class Config(BaseConfig):
105
113
  def detect_token_address(ticker: str, network: Network) -> str | None:
106
114
  if network in TOKEN_ADDRESS:
107
115
  return TOKEN_ADDRESS[network].get(ticker)
108
-
109
-
110
- def get_address_group_by_name(address_groups: list[AddressGroup], name: str) -> AddressGroup | None:
111
- return pydash.find(address_groups, lambda g: g.name == name)
112
-
113
-
114
- def process_file_addresses(addresses: list[str]) -> list[str]:
115
- result = []
116
- for address in addresses:
117
- if address.startswith("file://"):
118
- path = Path(address.removeprefix("file://"))
119
- if path.is_file():
120
- result.extend(path.read_text().strip().splitlines())
121
- else:
122
- fatal(f"File with addresses not found: {path}")
123
- else:
124
- result.append(address)
125
- return result
@@ -9,11 +9,11 @@ from mm_balance.workers import Workers
9
9
 
10
10
  def print_result(config: Config, token_decimals: TokenDecimals, prices: Prices, workers: Workers, result: BalancesResult) -> None:
11
11
  data: dict[str, object] = {}
12
- if config.print_debug:
12
+ if config.settings.print_debug:
13
13
  data["nodes"] = config.nodes
14
14
  data["token_decimals"] = token_decimals
15
- data["proxies"] = len(config.proxies)
16
- if config.price:
15
+ data["proxies"] = len(config.settings.proxies)
16
+ if config.settings.price:
17
17
  data["prices"] = prices
18
18
 
19
19
  data["groups"] = result.groups
@@ -18,7 +18,7 @@ def print_nodes(config: Config) -> None:
18
18
 
19
19
 
20
20
  def print_proxy_count(config: Config) -> None:
21
- print_table("Proxies", ["count"], [[len(config.proxies)]])
21
+ print_table("Proxies", ["count"], [[len(config.settings.proxies)]])
22
22
 
23
23
 
24
24
  def print_token_decimals(token_decimals: TokenDecimals) -> None:
@@ -29,10 +29,12 @@ def print_token_decimals(token_decimals: TokenDecimals) -> None:
29
29
 
30
30
 
31
31
  def print_prices(config: Config, prices: Prices) -> None:
32
- if config.price:
32
+ if config.settings.price:
33
33
  rows = []
34
34
  for ticker, price in prices.items():
35
- rows.append([ticker, format_number(round(price, config.round_ndigits), config.format_number_separator, "$")])
35
+ rows.append(
36
+ [ticker, format_number(round(price, config.settings.round_ndigits), config.settings.format_number_separator, "$")]
37
+ )
36
38
  print_table("Prices", ["coin", "usd"], rows)
37
39
 
38
40
 
@@ -64,19 +66,19 @@ def _print_total(config: Config, total: Total, is_share_total: bool) -> None:
64
66
 
65
67
  rows = []
66
68
  for ticker, balance in total.coin_balances.items():
67
- balance_str = format_number(balance, config.format_number_separator)
69
+ balance_str = format_number(balance, config.settings.format_number_separator)
68
70
  row = [ticker, balance_str]
69
- if config.price:
70
- usd_value_str = format_number(total.coin_usd_values[ticker], config.format_number_separator, "$")
71
+ if config.settings.price:
72
+ usd_value_str = format_number(total.coin_usd_values[ticker], config.settings.format_number_separator, "$")
71
73
  portfolio_share = total.portfolio_share[ticker]
72
74
  row += [usd_value_str, f"{portfolio_share}%"]
73
75
  rows.append(row)
74
76
 
75
- if config.price:
77
+ if config.settings.price:
76
78
  headers += ["usd", "portfolio_share"]
77
79
  if total.stablecoin_sum > 0:
78
- rows.append(["stablecoin_sum", format_number(total.stablecoin_sum, config.format_number_separator, "$")])
79
- rows.append(["total_usd_sum", format_number(total.total_usd_sum, config.format_number_separator, "$")])
80
+ rows.append(["stablecoin_sum", format_number(total.stablecoin_sum, config.settings.format_number_separator, "$")])
81
+ rows.append(["total_usd_sum", format_number(total.total_usd_sum, config.settings.format_number_separator, "$")])
80
82
 
81
83
  print_table(table_name, headers, rows)
82
84
 
@@ -92,28 +94,28 @@ def _print_group(config: Config, group: GroupResult) -> None:
92
94
  if isinstance(address.balance, str):
93
95
  rows.append([address.address, address.balance])
94
96
  else:
95
- if config.skip_empty and address.balance.balance == Decimal(0):
97
+ if config.settings.skip_empty and address.balance.balance == Decimal(0):
96
98
  continue
97
- balance_str = format_number(address.balance.balance, config.format_number_separator)
99
+ balance_str = format_number(address.balance.balance, config.settings.format_number_separator)
98
100
  row = [address.address, balance_str]
99
- if config.price:
100
- usd_value_str = format_number(address.balance.usd_value, config.format_number_separator, "$")
101
+ if config.settings.price:
102
+ usd_value_str = format_number(address.balance.usd_value, config.settings.format_number_separator, "$")
101
103
  row.append(usd_value_str)
102
104
  rows.append(row)
103
105
 
104
- sum_row = ["sum", format_number(group.balance_sum, config.format_number_separator)]
105
- if config.price:
106
- sum_row.append(format_number(group.usd_sum, config.format_number_separator, "$"))
106
+ sum_row = ["sum", format_number(group.balance_sum, config.settings.format_number_separator)]
107
+ if config.settings.price:
108
+ sum_row.append(format_number(group.usd_sum, config.settings.format_number_separator, "$"))
107
109
  rows.append(sum_row)
108
110
 
109
111
  if group.share < Decimal(1):
110
- sum_share_str = format_number(group.balance_sum_share, config.format_number_separator)
112
+ sum_share_str = format_number(group.balance_sum_share, config.settings.format_number_separator)
111
113
  sum_share_row = [f"sum_share, {group.share}", sum_share_str]
112
- if config.price:
113
- sum_share_row.append(format_number(group.usd_sum_share, config.format_number_separator, "$"))
114
+ if config.settings.price:
115
+ sum_share_row.append(format_number(group.usd_sum_share, config.settings.format_number_separator, "$"))
114
116
  rows.append(sum_share_row)
115
117
 
116
118
  table_headers = ["address", "balance"]
117
- if config.price:
119
+ if config.settings.price:
118
120
  table_headers += ["usd"]
119
121
  print_table(group_name, table_headers, rows)
mm_balance/price.py CHANGED
@@ -30,7 +30,7 @@ def get_prices(config: Config) -> Prices:
30
30
 
31
31
  url = f"https://api.coingecko.com/api/v3/simple/price?ids={','.join(coingecko_map.values())}&vs_currencies=usd"
32
32
  for _ in range(RETRIES_COINGECKO_PRICES):
33
- res = hr(url, proxy=random_str_choice(config.proxies))
33
+ res = hr(url, proxy=random_str_choice(config.settings.proxies))
34
34
  if res.code != 200:
35
35
  continue
36
36
 
mm_balance/result.py CHANGED
@@ -106,7 +106,7 @@ def _create_group_result(config: Config, group: Group, tasks: list[Task], prices
106
106
  coin_value = task.balance.ok
107
107
  usd_value = Decimal(0)
108
108
  if group.ticker in prices:
109
- usd_value = round(coin_value * prices[group.ticker], config.round_ndigits)
109
+ usd_value = round(coin_value * prices[group.ticker], config.settings.round_ndigits)
110
110
  balance = Balance(balance=coin_value, usd_value=usd_value)
111
111
  balance_sum += balance.balance
112
112
  usd_sum += balance.usd_value
mm_balance/rpc/solana.py CHANGED
@@ -1,7 +1,6 @@
1
1
  from decimal import Decimal
2
2
 
3
- from mm_solana import balance
4
- from mm_solana import token as solana_token
3
+ from mm_sol import balance, token
5
4
  from mm_std import Ok, Result
6
5
 
7
6
  from mm_balance.constants import RETRIES_BALANCE, RETRIES_DECIMALS, TIMEOUT_BALANCE, TIMEOUT_DECIMALS
@@ -11,9 +10,11 @@ def get_balance(
11
10
  nodes: list[str], wallet: str, token: str | None, decimals: int, proxies: list[str], round_ndigits: int
12
11
  ) -> Result[Decimal]:
13
12
  if token is None:
14
- res = balance.get_balance_with_retries(nodes, wallet, retries=RETRIES_BALANCE, timeout=TIMEOUT_BALANCE, proxies=proxies)
13
+ res = balance.get_sol_balance_with_retries(
14
+ nodes, wallet, retries=RETRIES_BALANCE, timeout=TIMEOUT_BALANCE, proxies=proxies
15
+ )
15
16
  else:
16
- res = solana_token.get_balance_with_retries(
17
+ res = balance.get_token_balance_with_retries(
17
18
  nodes, wallet, token, retries=RETRIES_BALANCE, timeout=TIMEOUT_BALANCE, proxies=proxies
18
19
  )
19
20
 
@@ -21,6 +22,6 @@ def get_balance(
21
22
 
22
23
 
23
24
  def get_token_decimals(nodes: list[str], token_address: str, proxies: list[str]) -> Result[int]:
24
- return solana_token.get_decimals_with_retries(
25
+ return token.get_decimals_with_retries(
25
26
  nodes, token_address, retries=RETRIES_DECIMALS, timeout=TIMEOUT_DECIMALS, proxies=proxies
26
27
  )
@@ -14,7 +14,7 @@ class TokenDecimals(dict[Network, dict[str | None, int]]): # {network: {None: 1
14
14
 
15
15
  def get_token_decimals(config: Config) -> TokenDecimals:
16
16
  result = TokenDecimals(config.networks())
17
- proxies = config.proxies
17
+ proxies = config.settings.proxies
18
18
 
19
19
  for group in config.groups:
20
20
  # token_decimals is already known
mm_balance/workers.py CHANGED
@@ -24,7 +24,7 @@ class Workers:
24
24
  self.config = config
25
25
  self.token_decimals = token_decimals
26
26
  self.tasks: dict[Network, list[Task]] = {network: [] for network in config.networks()}
27
- self.progress_bar = utils.create_progress_bar(config.print_format is not PrintFormat.TABLE)
27
+ self.progress_bar = utils.create_progress_bar(config.settings.print_format is not PrintFormat.TABLE)
28
28
  self.progress_bar_task: dict[Network, TaskID] = {}
29
29
 
30
30
  for idx, group in enumerate(config.groups):
@@ -63,8 +63,8 @@ class Workers:
63
63
 
64
64
  def _get_balance(self, network: Network, wallet_address: str, token_address: str | None) -> Result[Decimal]:
65
65
  nodes = self.config.nodes[network]
66
- round_ndigits = self.config.round_ndigits
67
- proxies = self.config.proxies
66
+ round_ndigits = self.config.settings.round_ndigits
67
+ proxies = self.config.settings.proxies
68
68
  token_decimals = self.token_decimals[network][token_address]
69
69
 
70
70
  if network.is_evm_network():
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: mm-balance
3
+ Version: 0.2.1
4
+ Requires-Python: >=3.12
5
+ Requires-Dist: mm-aptos==0.2.0
6
+ Requires-Dist: mm-btc==0.3.0
7
+ Requires-Dist: mm-eth==0.3.1
8
+ Requires-Dist: mm-sol==0.3.1
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=glOveB7bhcmuHBZvKZpmO1iMB1S21E6TnIIwuB25jUo,3398
3
+ mm_balance/config.py,sha256=4zz1hOdob4bronkzLxR9XRuj614OlWcXd5hjqCaRimc,4260
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=vj5-jDB_V3I0-lSuEByI10P_3o0DIhHYH1QzJu8WVrg,1788
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.1.dist-info/METADATA,sha256=r7KoFJHCD1PNDFC5pmrU7SsdA9YU1uf5Dr7ohPezchs,225
22
+ mm_balance-0.2.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ mm_balance-0.2.1.dist-info/entry_points.txt,sha256=rSnP0ZW1a3ACNwTWM7T53CmOycKbzhG43m2_wseENng,50
24
+ mm_balance-0.2.1.dist-info/RECORD,,
@@ -1,74 +0,0 @@
1
- coins:
2
- - ticker: SOL
3
- network: solana
4
- addresses:
5
- - 2ojv9BAiHUrvsm9gxDe7fJSzbNZSJcxZvf8dqmWGHG8S # binance
6
-
7
- - ticker: USDT
8
- network: solana
9
- addresses:
10
- - 2ojv9BAiHUrvsm9gxDe7fJSzbNZSJcxZvf8dqmWGHG8S # binance
11
-
12
- - ticker: BTC
13
- network: bitcoin
14
- comment: coldwallets
15
- addresses: |
16
- 34xp4vRoCGJym3xR7yCVPFHoCNxv4Twseo # binance
17
- bc1qgdjqv0av3q56jvd82tkdjpy7gdp9ut8tlqmgrpmv24sq90ecnvqqjwvw97 # bitfinex
18
- bc1ql49ydapnjafl5t2cp9zqpjwe6pdgmxy98859v2 # robinhood
19
- share: 0.1 # 10%
20
-
21
- - ticker: ETH
22
- network: ethereum
23
- comment: okx
24
- addresses: okx_eth
25
-
26
- - ticker: USDT
27
- network: ethereum
28
- comment: okx
29
- addresses: okx_eth
30
-
31
- - ticker: ETH
32
- network: ethereum
33
- comment: binance
34
- addresses: binance_eth
35
-
36
- - ticker: USDT
37
- network: ethereum
38
- comment: binance
39
- addresses: binance_eth
40
-
41
- - ticker: USDC
42
- comment: swap.thala.apt
43
- network: aptos
44
- token_address: 0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDC
45
- token_decimals: 6
46
- addresses: "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af" # for a single line it's necessary to use quotes
47
-
48
-
49
- addresses:
50
- - name: okx_eth
51
- addresses: |
52
- 0xf59869753f41db720127ceb8dbb8afaf89030de4
53
- 0x65a0947ba5175359bb457d3b34491edf4cbf7997
54
- 0xe9172daf64b05b26eb18f07ac8d6d723acb48f99
55
- 0x4d19c0a5357bc48be0017095d3c871d9afc3f21d
56
-
57
- - name: binance_eth
58
- addresses: |
59
- 0xf977814e90da44bfa03b6295a0616a897441acec
60
- 0x47ac0fb4f2d84898e4d9e7b4dab3c24507a6d503
61
-
62
- ##Optional settings:
63
- #proxies_url: https://site.com/api/proxies # get proxies from this url
64
- #proxies:
65
- #- http://123.123.123.121
66
- #- http://123.123.123.122
67
- #- http://123.123.123.123
68
- #- http://123.123.123.124
69
- #round_ndigits: 4
70
- #price: yes
71
- #skip_empty: no
72
- #print_debug: no
73
- #print_format: table # table, json
74
- #format_number_separator: ","
@@ -1,10 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: mm-balance
3
- Version: 0.1.20
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-crypto-utils==0.0.13
8
- Requires-Dist: mm-eth==0.2.5
9
- Requires-Dist: mm-solana==0.2.4
10
- Requires-Dist: typer>=0.15.1
@@ -1,24 +0,0 @@
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=7dB_8MrefufIi32-ubgiUxjacmeKERGNIbc1yXNw4ec,4578
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=U9oQOkYtg83tbzCdhs-RqrqeX9JAY1H_AW65gLytxMU,3739
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=iGDoO7HXP6reLI0bWm0UhEl7-UFZTo5xCWNzFngbITw,458
19
- mm_balance/rpc/evm.py,sha256=ewlMmRrcXKlky3DPNbnUBTVwnvyw7N9iCZLsCX2V14w,1007
20
- mm_balance/rpc/solana.py,sha256=Lwl5Otqy48g4LWfz9uN7_rkICKUIYJvf88PbIAnfMdc,1051
21
- mm_balance-0.1.20.dist-info/METADATA,sha256=rUfrIh7wO8EWYVsDHysHw0yX202FfCpmGHK9qm_R_nA,268
22
- mm_balance-0.1.20.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
- mm_balance-0.1.20.dist-info/entry_points.txt,sha256=rSnP0ZW1a3ACNwTWM7T53CmOycKbzhG43m2_wseENng,50
24
- mm_balance-0.1.20.dist-info/RECORD,,