mm-eth 0.5.16__py3-none-any.whl → 0.6.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.
Files changed (46) hide show
  1. mm_eth/abi.py +2 -4
  2. mm_eth/account.py +51 -18
  3. mm_eth/anvil.py +8 -8
  4. mm_eth/cli/calcs.py +1 -16
  5. mm_eth/cli/cli.py +55 -159
  6. mm_eth/cli/cli_utils.py +14 -27
  7. mm_eth/cli/cmd/balance_cmd.py +15 -16
  8. mm_eth/cli/cmd/balances_cmd.py +35 -36
  9. mm_eth/cli/cmd/deploy_cmd.py +9 -11
  10. mm_eth/cli/cmd/node_cmd.py +20 -15
  11. mm_eth/cli/cmd/solc_cmd.py +7 -6
  12. mm_eth/cli/cmd/transfer_cmd.py +210 -128
  13. mm_eth/cli/cmd/wallet/private_key_cmd.py +5 -4
  14. mm_eth/cli/rpc_helpers.py +32 -115
  15. mm_eth/cli/validators.py +13 -16
  16. mm_eth/converters.py +56 -0
  17. mm_eth/erc20.py +6 -224
  18. mm_eth/retry.py +143 -0
  19. mm_eth/rpc.py +226 -428
  20. mm_eth/solc.py +30 -17
  21. mm_eth/tx.py +8 -9
  22. mm_eth/utils.py +0 -224
  23. {mm_eth-0.5.16.dist-info → mm_eth-0.6.0.dist-info}/METADATA +3 -3
  24. mm_eth-0.6.0.dist-info/RECORD +32 -0
  25. mm_eth/async_rpc.py +0 -94
  26. mm_eth/cli/cmd/call_contract_cmd.py +0 -44
  27. mm_eth/cli/cmd/encode_input_data_cmd.py +0 -10
  28. mm_eth/cli/cmd/example_cmd.py +0 -9
  29. mm_eth/cli/cmd/rpc_cmd.py +0 -78
  30. mm_eth/cli/cmd/token_cmd.py +0 -29
  31. mm_eth/cli/cmd/tx_cmd.py +0 -16
  32. mm_eth/cli/cmd/vault_cmd.py +0 -19
  33. mm_eth/cli/examples/balances.toml +0 -18
  34. mm_eth/cli/examples/call_contract.toml +0 -9
  35. mm_eth/cli/examples/transfer.toml +0 -46
  36. mm_eth/cli/print_helpers.py +0 -37
  37. mm_eth/constants.py +0 -1
  38. mm_eth/ens.py +0 -106
  39. mm_eth/ethernodes.py +0 -34
  40. mm_eth/json_encoder.py +0 -15
  41. mm_eth/py.typed +0 -0
  42. mm_eth/rpc_async.py +0 -170
  43. mm_eth/vault.py +0 -38
  44. mm_eth-0.5.16.dist-info/RECORD +0 -49
  45. {mm_eth-0.5.16.dist-info → mm_eth-0.6.0.dist-info}/WHEEL +0 -0
  46. {mm_eth-0.5.16.dist-info → mm_eth-0.6.0.dist-info}/entry_points.txt +0 -0
@@ -1,15 +1,14 @@
1
1
  from dataclasses import dataclass
2
2
  from typing import Annotated
3
3
 
4
- from mm_std import BaseConfig, Err, Ok, fatal
4
+ from mm_std import BaseConfig, fatal
5
5
  from pydantic import BeforeValidator
6
6
  from rich.live import Live
7
7
  from rich.table import Table
8
8
 
9
- from mm_eth import erc20, rpc
9
+ from mm_eth import converters, retry
10
10
  from mm_eth.cli.cli_utils import BaseConfigParams
11
11
  from mm_eth.cli.validators import Validators
12
- from mm_eth.utils import from_token_wei_str, from_wei_str
13
12
 
14
13
 
15
14
  class Config(BaseConfig):
@@ -31,12 +30,12 @@ class BalancesCmdParams(BaseConfigParams):
31
30
  show_nonce: bool
32
31
 
33
32
 
34
- def run(params: BalancesCmdParams) -> None:
33
+ async def run(params: BalancesCmdParams) -> None:
35
34
  config = Config.read_toml_config_or_exit(params.config_path)
36
35
  if params.print_config:
37
36
  config.print_and_exit()
38
37
 
39
- tokens = _get_tokens_info(config)
38
+ tokens = await _get_tokens_info(config)
40
39
 
41
40
  table = Table(title="balances")
42
41
  table.add_column("address")
@@ -52,36 +51,33 @@ def run(params: BalancesCmdParams) -> None:
52
51
  for address in config.addresses:
53
52
  row = [address]
54
53
  if params.show_nonce:
55
- row.append(str(rpc.eth_get_transaction_count(config.nodes, address, attempts=5).ok_or_err()))
54
+ nonce = await retry.eth_get_transaction_count(5, config.nodes, None, address=address)
55
+ row.append(str(nonce.value_or_error()))
56
56
 
57
- base_balance_res = rpc.eth_get_balance(config.nodes, address, attempts=5)
58
- if isinstance(base_balance_res, Ok):
59
- base_sum += base_balance_res.ok
57
+ base_balance_res = await retry.eth_get_balance(5, config.nodes, None, address=address)
58
+ if base_balance_res.is_ok():
59
+ balance = base_balance_res.unwrap()
60
+ base_sum += balance
60
61
  if params.wei:
61
- row.append(str(base_balance_res.ok))
62
+ row.append(str(balance))
62
63
  else:
63
- row.append(
64
- from_wei_str(base_balance_res.ok, "eth", round_ndigits=config.round_ndigits, print_unit_name=False),
65
- )
64
+ row.append(str(converters.from_wei(balance, "eth", round_ndigits=config.round_ndigits)))
66
65
  else:
67
- row.append(base_balance_res.err)
66
+ row.append(base_balance_res.unwrap_error())
68
67
 
69
68
  for t in tokens:
70
- token_balance_res = erc20.get_balance(config.nodes, t.address, address, attempts=5)
71
- if isinstance(token_balance_res, Ok):
72
- token_sum[t.address] += token_balance_res.ok
69
+ token_balance_res = await retry.erc20_balance(5, config.nodes, None, token=t.address, wallet=address)
70
+ if token_balance_res.is_ok():
71
+ token_balance = token_balance_res.unwrap()
72
+ token_sum[t.address] += token_balance
73
73
  if params.wei:
74
- row.append(str(token_balance_res.ok))
74
+ row.append(str(token_balance))
75
75
  else:
76
76
  row.append(
77
- from_token_wei_str(
78
- token_balance_res.ok,
79
- decimals=t.decimals,
80
- round_ndigits=config.round_ndigits,
81
- ),
77
+ str(converters.from_wei(token_balance, "t", round_ndigits=config.round_ndigits, decimals=t.decimals))
82
78
  )
83
79
  else:
84
- row.append(token_balance_res.err)
80
+ row.append(token_balance_res.unwrap_error())
85
81
 
86
82
  table.add_row(*row)
87
83
 
@@ -92,26 +88,29 @@ def run(params: BalancesCmdParams) -> None:
92
88
  sum_row.append(str(base_sum))
93
89
  sum_row.extend([str(token_sum[t.address]) for t in tokens])
94
90
  else:
95
- sum_row.append(from_wei_str(base_sum, "eth", round_ndigits=config.round_ndigits, print_unit_name=False))
91
+ sum_row.append(str(converters.from_wei(base_sum, "eth", round_ndigits=config.round_ndigits)))
96
92
  sum_row.extend(
97
- [from_token_wei_str(token_sum[t.address], t.decimals, round_ndigits=config.round_ndigits) for t in tokens]
93
+ [
94
+ str(converters.from_wei(token_sum[t.address], "t", round_ndigits=config.round_ndigits, decimals=t.decimals))
95
+ for t in tokens
96
+ ]
98
97
  )
99
98
 
100
99
  table.add_row(*sum_row)
101
100
 
102
101
 
103
- def _get_tokens_info(config: Config) -> list[Token]:
102
+ async def _get_tokens_info(config: Config) -> list[Token]:
104
103
  result: list[Token] = []
105
104
  for address in config.tokens:
106
- decimals_res = erc20.get_decimals(config.nodes, address, attempts=5)
107
- if isinstance(decimals_res, Err):
108
- fatal(f"can't get token {address} decimals: {decimals_res.err}")
109
- decimal = decimals_res.ok
110
-
111
- symbols_res = erc20.get_symbol(config.nodes, address, attempts=5)
112
- if isinstance(symbols_res, Err):
113
- fatal(f"can't get token {address} symbol: {symbols_res.err}")
114
- symbol = symbols_res.ok
105
+ decimals_res = await retry.erc20_decimals(5, config.nodes, None, token=address)
106
+ if decimals_res.is_err():
107
+ fatal(f"can't get token {address} decimals: {decimals_res.unwrap_error()}")
108
+ decimal = decimals_res.unwrap()
109
+
110
+ symbols_res = await retry.erc20_symbol(5, config.nodes, None, token=address)
111
+ if symbols_res.is_err():
112
+ fatal(f"can't get token {address} symbol: {symbols_res.unwrap_error()}")
113
+ symbol = symbols_res.unwrap()
115
114
 
116
115
  result.append(Token(address=address, decimals=decimal, symbol=symbol))
117
116
 
@@ -1,9 +1,8 @@
1
1
  import yaml
2
- from mm_std import BaseConfig, fatal
2
+ from mm_std import BaseConfig
3
3
  from pydantic import StrictStr
4
4
 
5
- from mm_eth import account, deploy
6
- from mm_eth.cli import rpc_helpers
5
+ from mm_eth import account, deploy, retry
7
6
  from mm_eth.cli.cli_utils import BaseConfigParams
8
7
 
9
8
 
@@ -22,10 +21,10 @@ class Config(BaseConfig):
22
21
 
23
22
 
24
23
  class DeployCmdParams(BaseConfigParams):
25
- pass
24
+ broadcast: bool = False
26
25
 
27
26
 
28
- def run(cli_params: DeployCmdParams) -> None:
27
+ async def run(cli_params: DeployCmdParams) -> None:
29
28
  config = Config.read_toml_config_or_exit(cli_params.config_path)
30
29
  if cli_params.print_config:
31
30
  config.print_and_exit({"private_key"})
@@ -33,12 +32,11 @@ def run(cli_params: DeployCmdParams) -> None:
33
32
  constructor_types = yaml.full_load(config.constructor_types)
34
33
  constructor_values = yaml.full_load(config.constructor_values)
35
34
 
36
- sender_address = account.private_to_address(config.private_key)
37
- if sender_address is None:
38
- fatal("private address is wrong")
35
+ sender_address = account.private_to_address(config.private_key).unwrap()
39
36
 
40
- nonce = rpc_helpers.get_nonce(config.node, sender_address)
41
- if nonce is None:
42
- fatal("can't get nonce")
37
+ if config.nonce is None:
38
+ config.nonce = (await retry.eth_get_transaction_count(5, config.node, None, address=sender_address)).unwrap(
39
+ "can't get nonce"
40
+ )
43
41
 
44
42
  deploy.get_deploy_contract_data(config.contract_bin, constructor_types, constructor_values)
@@ -1,11 +1,13 @@
1
+ from decimal import Decimal
2
+
3
+ import eth_utils
1
4
  import pydash
2
- from mm_std import Ok, PrintFormat, print_json
5
+ from mm_std import PrintFormat, print_json
3
6
  from pydantic import BaseModel
4
7
  from rich.live import Live
5
8
  from rich.table import Table
6
9
 
7
- from mm_eth import rpc
8
- from mm_eth.utils import from_wei_str, name_network
10
+ from mm_eth import rpc, utils
9
11
 
10
12
 
11
13
  class NodeInfo(BaseModel):
@@ -13,7 +15,7 @@ class NodeInfo(BaseModel):
13
15
  chain_id: int | str
14
16
  chain_name: str
15
17
  block_number: int | str
16
- base_fee: str
18
+ base_fee: str | int | Decimal
17
19
 
18
20
  def table_row(self) -> list[object]:
19
21
  return [self.url, self.chain_id, self.chain_name, self.block_number, self.base_fee]
@@ -40,7 +42,7 @@ class LiveTable:
40
42
  self.live.stop()
41
43
 
42
44
 
43
- def run(urls: list[str], proxy: str | None, print_format: PrintFormat) -> None:
45
+ async def run(urls: list[str], proxy: str | None, print_format: PrintFormat) -> None:
44
46
  urls = pydash.uniq(urls)
45
47
  result = []
46
48
  live_table = LiveTable(
@@ -48,7 +50,7 @@ def run(urls: list[str], proxy: str | None, print_format: PrintFormat) -> None:
48
50
  ignore=print_format != PrintFormat.TABLE,
49
51
  )
50
52
  for url in urls:
51
- node_info = _get_node_info(url, proxy)
53
+ node_info = await _get_node_info(url, proxy)
52
54
  live_table.add_row(*node_info.table_row())
53
55
  result.append(node_info)
54
56
 
@@ -64,15 +66,18 @@ def run(urls: list[str], proxy: str | None, print_format: PrintFormat) -> None:
64
66
  # table.add_row(url, str(chain_id), chain_name, str(block_number), base_fee)
65
67
 
66
68
 
67
- def _get_node_info(url: str, proxy: str | None) -> NodeInfo:
68
- chain_id_res = rpc.eth_chain_id(url, timeout=10, proxies=proxy)
69
- chain_id = chain_id_res.ok_or_err()
69
+ async def _get_node_info(url: str, proxy: str | None) -> NodeInfo:
70
+ chain_id_res = await rpc.eth_chain_id(url, proxy=proxy)
71
+ chain_id = chain_id_res.value_or_error()
70
72
  chain_name = ""
71
- if isinstance(chain_id_res, Ok):
72
- chain_name = name_network(chain_id_res.ok)
73
- block_number = rpc.eth_block_number(url, timeout=10, proxies=proxy).ok_or_err()
74
- base_fee = rpc.get_base_fee_per_gas(url, timeout=10, proxies=proxy).map_or_else(
75
- lambda err: err,
76
- lambda ok: from_wei_str(ok, "gwei"),
73
+ if chain_id_res.is_ok():
74
+ chain_name = utils.name_network(chain_id_res.unwrap())
75
+ block_number = (await rpc.eth_block_number(url, proxy=proxy)).value_or_error()
76
+ base_fee = (
77
+ (await rpc.get_base_fee_per_gas(url, proxy=proxy))
78
+ .map(
79
+ lambda ok: eth_utils.from_wei(ok, "gwei"),
80
+ )
81
+ .value_or_error()
77
82
  )
78
83
  return NodeInfo(url=url, chain_id=chain_id, chain_name=chain_name, block_number=block_number, base_fee=base_fee)
@@ -1,19 +1,20 @@
1
1
  import json
2
+ from pathlib import Path
2
3
 
3
- from mm_std import Err, PrintFormat, fatal, print_json, print_plain
4
+ from mm_std import PrintFormat, fatal, print_json, print_plain
4
5
  from mm_std.fs import get_filename_without_extension
5
6
 
6
7
  from mm_eth.solc import solc
7
8
 
8
9
 
9
- def run(contract_path: str, tmp_dir: str, print_format: PrintFormat) -> None:
10
+ def run(contract_path: Path, tmp_dir: Path, print_format: PrintFormat) -> None:
10
11
  contract_name = get_filename_without_extension(contract_path)
11
12
  res = solc(contract_name, contract_path, tmp_dir)
12
- if isinstance(res, Err):
13
- fatal(res.err)
13
+ if res.is_err():
14
+ fatal(res.unwrap_error())
14
15
 
15
- bin_ = res.ok.bin
16
- abi = res.ok.abi
16
+ bin_ = res.unwrap().bin
17
+ abi = res.unwrap().abi
17
18
 
18
19
  if print_format == PrintFormat.JSON:
19
20
  print_json({"bin": bin_, "abi": json.loads(abi)})