mm-balance 0.1.19__py3-none-any.whl → 0.2.0__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,25 +1,29 @@
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 Self, cast
5
+ from typing import Annotated, Self
7
6
 
8
7
  import pydash
9
- from mm_std import BaseConfig, PrintFormat, fatal, hr
10
- from pydantic import Field, field_validator, model_validator
8
+ from mm_crypto_utils import ConfigValidators
9
+ from mm_std import BaseConfig, PrintFormat, fatal
10
+ from pydantic import BeforeValidator, Field, StringConstraints, model_validator
11
11
 
12
12
  from mm_balance.constants import DEFAULT_NODES, TOKEN_ADDRESS, Network
13
13
 
14
14
 
15
+ class Validators(ConfigValidators):
16
+ pass
17
+
18
+
15
19
  class Group(BaseConfig):
16
20
  comment: str = ""
17
- ticker: str
21
+ ticker: Annotated[str, StringConstraints(to_upper=True)]
18
22
  network: Network
19
23
  token_address: str | None = None # If None, it's a native token, for example ETH
20
24
  token_decimals: int | None = None
21
25
  coingecko_id: str | None = None
22
- addresses: list[str] = Field(default_factory=list)
26
+ addresses: Annotated[list[str], BeforeValidator(Validators.addresses(unique=True))]
23
27
  share: Decimal = Decimal(1)
24
28
 
25
29
  @property
@@ -30,20 +34,6 @@ class Group(BaseConfig):
30
34
  result += " / " + self.network
31
35
  return result
32
36
 
33
- @field_validator("ticker", mode="after")
34
- def ticker_validator(cls, v: str) -> str:
35
- return v.upper()
36
-
37
- @field_validator("addresses", mode="before")
38
- def to_list_validator(cls, v: str | list[str] | None) -> list[str]:
39
- return cls.to_list_str_validator(v, unique=True, remove_comments=True, split_line=True)
40
-
41
- # @model_validator(mode="before")
42
- # def before_all(cls, data: Any) -> Any:
43
- # if "network" not in data:
44
- # data["network"] = detect_network(data["coin"])
45
- # return data
46
-
47
37
  @model_validator(mode="after")
48
38
  def final_validator(self) -> Self:
49
39
  if self.token_address is None:
@@ -65,27 +55,25 @@ class Group(BaseConfig):
65
55
 
66
56
  class AddressGroup(BaseConfig):
67
57
  name: str
68
- addresses: list[str]
58
+ addresses: Annotated[list[str], BeforeValidator(ConfigValidators.addresses(unique=True))]
69
59
 
70
- @field_validator("addresses", mode="before")
71
- def to_list_validator(cls, v: str | list[str] | None) -> list[str]:
72
- return cls.to_list_str_validator(v, unique=True, remove_comments=True, split_line=True)
73
-
74
-
75
- class Config(BaseConfig):
76
- groups: list[Group] = Field(alias="coins")
77
- addresses: list[AddressGroup] = Field(default_factory=list)
78
60
 
79
- proxies_url: str | None = None
80
- proxies: list[str] = Field(default_factory=list)
61
+ class Settings(BaseConfig):
62
+ proxies: Annotated[list[str], Field(default_factory=list), BeforeValidator(Validators.proxies())]
81
63
  round_ndigits: int = 4
82
- nodes: dict[Network, list[str]] = Field(default_factory=dict)
83
64
  print_format: PrintFormat = PrintFormat.TABLE
84
65
  price: bool = True
85
66
  skip_empty: bool = False # don't print the address with an empty balance
86
67
  print_debug: bool = False # print debug info: nodes, token_decimals
87
- format_number_separator: str = "," # as thousands separators
68
+ format_number_separator: str = "," # as thousands separators
69
+
70
+
71
+ class Config(BaseConfig):
72
+ groups: list[Group] = Field(alias="coins")
73
+ addresses: list[AddressGroup] = Field(default_factory=list)
74
+ nodes: dict[Network, list[str]] = Field(default_factory=dict)
88
75
  workers: dict[Network, int] = Field(default_factory=dict)
76
+ settings: Settings = Field(default_factory=Settings) # type: ignore[arg-type]
89
77
 
90
78
  def has_share(self) -> bool:
91
79
  return any(g.share != Decimal(1) for g in self.groups)
@@ -95,12 +83,6 @@ class Config(BaseConfig):
95
83
 
96
84
  @model_validator(mode="after")
97
85
  def final_validator(self) -> Self:
98
- # load from proxies_url
99
- if self.proxies_url is not None:
100
- self.proxies = get_proxies(self.proxies_url)
101
- elif os.getenv("MM_BALANCE_PROXIES_URL"):
102
- self.proxies = get_proxies(cast(str, os.getenv("MM_BALANCE_PROXIES_URL")))
103
-
104
86
  # load addresses from address_group
105
87
  for group in self.groups:
106
88
  group.process_addresses(self.addresses)
@@ -123,17 +105,6 @@ def detect_token_address(ticker: str, network: Network) -> str | None:
123
105
  return TOKEN_ADDRESS[network].get(ticker)
124
106
 
125
107
 
126
- def get_proxies(proxies_url: str) -> list[str]:
127
- try:
128
- res = hr(proxies_url)
129
- if res.is_error():
130
- fatal(f"Can't get proxies: {res.error}")
131
- proxies = [p.strip() for p in res.body.splitlines() if p.strip()]
132
- return pydash.uniq(proxies)
133
- except Exception as err:
134
- fatal(f"Can't get proxies: {err}")
135
-
136
-
137
108
  def get_address_group_by_name(address_groups: list[AddressGroup], name: str) -> AddressGroup | None:
138
109
  return pydash.find(address_groups, lambda g: g.name == name)
139
110
 
@@ -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/btc.py CHANGED
@@ -10,7 +10,5 @@ def get_balance(address: str, proxies: list[str], round_ndigits: int) -> Result[
10
10
  return (
11
11
  BlockstreamClient(proxies=proxies, attempts=RETRIES_BALANCE)
12
12
  .get_confirmed_balance(address)
13
- .and_then(
14
- lambda b: Ok(round(Decimal(b / 100_000_000), round_ndigits)),
15
- )
13
+ .and_then(lambda b: Ok(round(Decimal(b / 100_000_000), round_ndigits)))
16
14
  )
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
@@ -1,8 +1,8 @@
1
1
  from dataclasses import dataclass
2
2
  from decimal import Decimal
3
- from typing import TYPE_CHECKING
4
3
 
5
4
  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,9 +10,6 @@ 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
-
16
13
 
17
14
  @dataclass
18
15
  class Task:
@@ -27,7 +24,7 @@ class Workers:
27
24
  self.config = config
28
25
  self.token_decimals = token_decimals
29
26
  self.tasks: dict[Network, list[Task]] = {network: [] for network in config.networks()}
30
- 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)
31
28
  self.progress_bar_task: dict[Network, TaskID] = {}
32
29
 
33
30
  for idx, group in enumerate(config.groups):
@@ -66,8 +63,8 @@ class Workers:
66
63
 
67
64
  def _get_balance(self, network: Network, wallet_address: str, token_address: str | None) -> Result[Decimal]:
68
65
  nodes = self.config.nodes[network]
69
- round_ndigits = self.config.round_ndigits
70
- proxies = self.config.proxies
66
+ round_ndigits = self.config.settings.round_ndigits
67
+ proxies = self.config.settings.proxies
71
68
  token_decimals = self.token_decimals[network][token_address]
72
69
 
73
70
  if network.is_evm_network():
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: mm-balance
3
+ Version: 0.2.0
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.0
8
+ Requires-Dist: mm-sol==0.3.0
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=wuNiy8RBoFhisx4ZvT7CAXDvvz4aU52kr4vXFnXNvGI,4381
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=RuZQfizuPgX0F9MQdVffDfKrCOJxJE48iPbM9HT96wk,1786
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.0.dist-info/METADATA,sha256=eG5IbPKRNnqBK_go58psO14Go5FUAAWWsHE4xBjgyak,225
22
+ mm_balance-0.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ mm_balance-0.2.0.dist-info/entry_points.txt,sha256=rSnP0ZW1a3ACNwTWM7T53CmOycKbzhG43m2_wseENng,50
24
+ mm_balance-0.2.0.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,9 +0,0 @@
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
@@ -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=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,,