mm-eth 0.1.5__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.
Files changed (45) hide show
  1. mm_eth/abi.py +3 -3
  2. mm_eth/account.py +1 -1
  3. mm_eth/anvil.py +2 -2
  4. mm_eth/erc20.py +8 -7
  5. mm_eth/rpc.py +8 -8
  6. mm_eth/solc.py +2 -3
  7. mm_eth/tx.py +3 -5
  8. mm_eth/utils.py +11 -16
  9. mm_eth/vault.py +5 -5
  10. mm_eth-0.2.1.dist-info/METADATA +7 -0
  11. mm_eth-0.2.1.dist-info/RECORD +18 -0
  12. {mm_eth-0.1.5.dist-info → mm_eth-0.2.1.dist-info}/WHEEL +1 -1
  13. mm_eth/abi/zksync.json +0 -2092
  14. mm_eth/cli/__init__.py +0 -0
  15. mm_eth/cli/calcs.py +0 -88
  16. mm_eth/cli/cli.py +0 -237
  17. mm_eth/cli/cli_helpers.py +0 -195
  18. mm_eth/cli/cli_utils.py +0 -148
  19. mm_eth/cli/cmd/__init__.py +0 -0
  20. mm_eth/cli/cmd/balance_cmd.py +0 -59
  21. mm_eth/cli/cmd/balances_cmd.py +0 -121
  22. mm_eth/cli/cmd/call_contract_cmd.py +0 -44
  23. mm_eth/cli/cmd/config_example_cmd.py +0 -9
  24. mm_eth/cli/cmd/deploy_cmd.py +0 -41
  25. mm_eth/cli/cmd/encode_input_data_cmd.py +0 -10
  26. mm_eth/cli/cmd/mnemonic_cmd.py +0 -27
  27. mm_eth/cli/cmd/node_cmd.py +0 -47
  28. mm_eth/cli/cmd/private_key_cmd.py +0 -10
  29. mm_eth/cli/cmd/rpc_cmd.py +0 -81
  30. mm_eth/cli/cmd/send_contract_cmd.py +0 -247
  31. mm_eth/cli/cmd/solc_cmd.py +0 -25
  32. mm_eth/cli/cmd/token_cmd.py +0 -29
  33. mm_eth/cli/cmd/transfer_erc20_cmd.py +0 -275
  34. mm_eth/cli/cmd/transfer_eth_cmd.py +0 -252
  35. mm_eth/cli/cmd/vault_cmd.py +0 -16
  36. mm_eth/cli/config_examples/balances.yml +0 -15
  37. mm_eth/cli/config_examples/call_contract.yml +0 -5
  38. mm_eth/cli/config_examples/transfer_erc20.yml +0 -26
  39. mm_eth/cli/config_examples/transfer_eth.yml +0 -24
  40. mm_eth/cli/validators.py +0 -84
  41. mm_eth/services/__init__.py +0 -0
  42. mm_eth/zksync.py +0 -203
  43. mm_eth-0.1.5.dist-info/METADATA +0 -9
  44. mm_eth-0.1.5.dist-info/RECORD +0 -49
  45. mm_eth-0.1.5.dist-info/entry_points.txt +0 -2
@@ -1,59 +0,0 @@
1
- from mm_std import Err, Ok, print_json, print_plain
2
-
3
- from mm_eth import erc20, rpc
4
- from mm_eth.cli import cli_helpers
5
- from mm_eth.cli.cli import PrintFormat
6
- from mm_eth.cli.cli_utils import public_rpc_url
7
- from mm_eth.utils import from_wei_str
8
-
9
-
10
- def run(rpc_url: str, wallet_address: str, token_address: str | None, wei: bool, print_format: PrintFormat) -> None:
11
- rpc_url = public_rpc_url(rpc_url)
12
- json_result: dict[str, object] = {}
13
-
14
- # nonce
15
- nonce = rpc.eth_get_transaction_count(rpc_url, wallet_address).ok_or_err()
16
- print_plain(f"nonce: {nonce}", print_format)
17
- json_result["nonce"] = nonce
18
-
19
- # balance
20
- balance_res = rpc.eth_get_balance(rpc_url, wallet_address)
21
- if isinstance(balance_res, Ok):
22
- if wei:
23
- balance = str(balance_res.ok)
24
- else:
25
- balance = from_wei_str(balance_res.ok, "eth")
26
- else:
27
- balance = balance_res.err
28
- print_plain(f"eth_balance: {balance}", print_format)
29
- json_result["eth_balance"] = balance
30
-
31
- if token_address is not None:
32
- # token decimal
33
- decimals_res = erc20.get_decimals(rpc_url, token_address)
34
- if isinstance(decimals_res, Err):
35
- cli_helpers.fatal(f"can't get token decimals: {decimals_res.err}")
36
- decimals = decimals_res.ok
37
- print_plain(f"token_decimal: {decimals}", print_format)
38
- json_result["token_decimal"] = decimals
39
-
40
- # token symbol
41
- symbol_res = erc20.get_symbol(rpc_url, token_address)
42
- if isinstance(symbol_res, Err):
43
- cli_helpers.fatal(f"can't get token symbol: {symbol_res.err}")
44
- symbol = symbol_res.ok
45
- print_plain(f"token_symbol: {symbol}", print_format)
46
- json_result["token_symbol"] = symbol
47
-
48
- # token balance
49
- balance_res = erc20.get_balance(rpc_url, token_address, wallet_address)
50
- if isinstance(balance_res, Err):
51
- cli_helpers.fatal(f"can't get token balance: {balance_res.err}")
52
- if wei:
53
- balance = str(balance_res.ok)
54
- else:
55
- balance = from_wei_str(balance_res.ok, "t", decimals=decimals)
56
- print_plain(f"token_balance: {balance}", print_format)
57
- json_result["token_balance"] = balance
58
-
59
- print_json(json_result, print_format)
@@ -1,121 +0,0 @@
1
- from dataclasses import dataclass
2
-
3
- from mm_std import Err, Ok, fatal, json_dumps
4
- from pydantic import BaseModel, Field, field_validator
5
- from rich.console import Console
6
- from rich.live import Live
7
- from rich.table import Table
8
-
9
- from mm_eth import erc20, rpc
10
- from mm_eth.cli import cli_utils, validators
11
- from mm_eth.utils import from_token_wei_str, from_wei_str
12
-
13
-
14
- class Config(BaseModel):
15
- addresses: list[str]
16
- tokens: list[str] = Field(default_factory=list)
17
- nodes: list[str]
18
- round_ndigits: int = 5
19
-
20
- @field_validator("nodes", mode="before")
21
- def nodes_validator(cls, v: str | list[str] | None) -> list[str]:
22
- return validators.nodes_validator(v)
23
-
24
- @field_validator("tokens", "addresses", mode="before")
25
- def addresses_validator(cls, v: str | list[str] | None) -> list[str]:
26
- return validators.addresses_validator(v)
27
-
28
-
29
- @dataclass
30
- class Token:
31
- address: str
32
- decimals: int
33
- symbol: str
34
-
35
-
36
- def run(config_path: str, print_config: bool, wei: bool, show_nonce: bool) -> None:
37
- config = cli_utils.read_config(Config, config_path)
38
- if print_config:
39
- console = Console()
40
- console.print_json(json_dumps(config.model_dump()))
41
- exit(0)
42
-
43
- tokens = _get_tokens_info(config)
44
-
45
- table = Table(title="balances")
46
- table.add_column("address")
47
- if show_nonce:
48
- table.add_column("nonce")
49
- table.add_column("wei" if wei else "eth")
50
- for t in tokens:
51
- table.add_column(t.symbol)
52
-
53
- base_sum = 0
54
- token_sum: dict[str, int] = {t.address: 0 for t in tokens}
55
- with Live(table, refresh_per_second=0.5):
56
- for address in config.addresses:
57
- row = [address]
58
- if show_nonce:
59
- row.append(str(rpc.eth_get_transaction_count(config.nodes, address, attempts=5).ok_or_err()))
60
-
61
- base_balance_res = rpc.eth_get_balance(config.nodes, address, attempts=5)
62
- if isinstance(base_balance_res, Ok):
63
- base_sum += base_balance_res.ok
64
- if wei:
65
- row.append(str(base_balance_res.ok))
66
- else:
67
- row.append(
68
- from_wei_str(base_balance_res.ok, "eth", round_ndigits=config.round_ndigits, print_unit_name=False),
69
- )
70
- else:
71
- row.append(base_balance_res.err)
72
-
73
- for t in tokens:
74
- token_balance_res = erc20.get_balance(config.nodes, t.address, address, attempts=5)
75
- if isinstance(token_balance_res, Ok):
76
- token_sum[t.address] += token_balance_res.ok
77
- if wei:
78
- row.append(str(token_balance_res.ok))
79
- else:
80
- row.append(
81
- from_token_wei_str(
82
- token_balance_res.ok,
83
- decimals=t.decimals,
84
- round_ndigits=config.round_ndigits,
85
- ),
86
- )
87
- else:
88
- row.append(token_balance_res.err)
89
-
90
- table.add_row(*row)
91
-
92
- sum_row = ["sum"]
93
- if show_nonce:
94
- sum_row.append("")
95
- if wei:
96
- sum_row.append(str(base_sum))
97
- for t in tokens:
98
- sum_row.append(str(token_sum[t.address]))
99
- else:
100
- sum_row.append(from_wei_str(base_sum, "eth", round_ndigits=config.round_ndigits, print_unit_name=False))
101
- for t in tokens:
102
- sum_row.append(from_token_wei_str(token_sum[t.address], t.decimals, round_ndigits=config.round_ndigits))
103
- table.add_row(*sum_row)
104
-
105
-
106
- def _get_tokens_info(config: Config) -> list[Token]:
107
- result: list[Token] = []
108
- for address in config.tokens:
109
- decimals_res = erc20.get_decimals(config.nodes, address, attempts=5)
110
- if isinstance(decimals_res, Err):
111
- fatal(f"can't get token {address} decimals: {decimals_res.err}")
112
- decimal = decimals_res.ok
113
-
114
- symbols_res = erc20.get_symbol(config.nodes, address, attempts=5)
115
- if isinstance(symbols_res, Err):
116
- fatal(f"can't get token {address} symbol: {symbols_res.err}")
117
- symbol = symbols_res.ok
118
-
119
- result.append(Token(address=address, decimals=decimal, symbol=symbol))
120
-
121
- return result
@@ -1,44 +0,0 @@
1
- import json
2
- from logging import fatal
3
-
4
- from mm_std import Err, print_json, print_plain
5
- from pydantic import StrictStr
6
-
7
- from mm_eth import abi, rpc
8
- from mm_eth.cli import cli_utils
9
-
10
-
11
- class Config(cli_utils.BaseConfig):
12
- contract_address: StrictStr
13
- function_signature: str
14
- function_args: StrictStr = "[]"
15
- outputs_types: str | None = None
16
- node: str
17
-
18
-
19
- def run(config_path: str, print_config: bool) -> None:
20
- config = cli_utils.read_config(Config, config_path)
21
- if print_config:
22
- print_json(config.model_dump())
23
- exit(0)
24
-
25
- input_data = abi.encode_function_input_by_signature(
26
- config.function_signature,
27
- json.loads(config.function_args.replace("'", '"')),
28
- )
29
- res = rpc.eth_call(config.node, config.contract_address, input_data)
30
- if isinstance(res, Err):
31
- return fatal(f"error: {res.err}")
32
-
33
- result = res.ok
34
- if config.outputs_types is not None:
35
- decode_res = abi.decode_data(_get_types(config.outputs_types), result)
36
- if len(decode_res) == 1:
37
- result = decode_res[0]
38
- else:
39
- result = str(decode_res)
40
- print_plain(result)
41
-
42
-
43
- def _get_types(data: str) -> list[str]:
44
- return [t.strip() for t in data.split(",") if t.strip()]
@@ -1,9 +0,0 @@
1
- from pathlib import Path
2
-
3
- from mm_std import print_plain
4
-
5
-
6
- def run(command: str) -> None:
7
- command = command.replace("-", "_")
8
- example_file = Path(Path(__file__).parent.absolute(), "../config_examples", f"{command}.yml")
9
- print_plain(example_file.read_text())
@@ -1,41 +0,0 @@
1
- import yaml
2
- from mm_std import print_json
3
- from pydantic import StrictStr
4
-
5
- from mm_eth import account, deploy
6
- from mm_eth.cli import cli_helpers, cli_utils
7
- from mm_eth.cli.cli_utils import BaseConfig
8
-
9
-
10
- class Config(BaseConfig):
11
- private_key: StrictStr
12
- nonce: int | None = None
13
- gas: StrictStr
14
- max_fee_per_gas: str
15
- max_priority_fee_per_gas: str
16
- value: str | None = None
17
- contract_bin: StrictStr
18
- constructor_types: StrictStr = "[]"
19
- constructor_values: StrictStr = "[]"
20
- chain_id: int
21
- node: str
22
-
23
-
24
- def run(config_path: str, *, print_config: bool) -> None:
25
- config = cli_utils.read_config(Config, config_path)
26
- if print_config:
27
- print_json(config.model_dump(exclude={"private_key"}))
28
- exit(0)
29
-
30
- constructor_types = yaml.full_load(config.constructor_types)
31
- constructor_values = yaml.full_load(config.constructor_values)
32
-
33
- sender_address = account.private_to_address(config.private_key)
34
- if sender_address is None:
35
- cli_utils.fatal("private address is wrong")
36
-
37
- nonce = cli_helpers.get_nonce(config.node, sender_address)
38
- if nonce is None:
39
- cli_utils.fatal("can't get nonce")
40
-
41
- deploy.get_deploy_contract_data(config.contract_bin, constructor_types, constructor_values)
@@ -1,10 +0,0 @@
1
- import json
2
-
3
- from mm_std import print_plain
4
-
5
- from mm_eth import abi
6
-
7
-
8
- def run(function_signature: str, args_str: str) -> None:
9
- args_str = args_str.replace("'", '"')
10
- print_plain(abi.encode_function_input_by_signature(function_signature, json.loads(args_str)))
@@ -1,27 +0,0 @@
1
- from pathlib import Path
2
- from typing import Any
3
-
4
- from mm_std import print_json
5
-
6
- from mm_eth.account import generate_accounts, generate_mnemonic
7
-
8
-
9
- def run(mnemonic: str, passphrase: str, limit: int, print_path: bool, path_prefix: str, save_file: str) -> None: # nosec
10
- result: dict[str, Any] = {}
11
- if not mnemonic:
12
- mnemonic = generate_mnemonic()
13
- result["mnemonic"] = mnemonic
14
- if passphrase:
15
- result["passphrase"] = passphrase
16
- result["accounts"] = []
17
- for acc in generate_accounts(mnemonic=mnemonic, passphrase=passphrase, limit=limit, path_prefix=path_prefix):
18
- new_account = {"address": acc.address, "private": acc.private_key}
19
- if print_path:
20
- new_account["path"] = acc.path
21
- result["accounts"].append(new_account)
22
- print_json(result)
23
-
24
- if save_file:
25
- with open(Path(save_file).expanduser(), "w") as f:
26
- for account in result["accounts"]:
27
- f.write(f"{account['address']}\t{account['private']}\n")
@@ -1,47 +0,0 @@
1
- from mm_std import Ok, PrintFormat, print_json, print_plain
2
- from rich.live import Live
3
- from rich.table import Table
4
-
5
- from mm_eth import rpc
6
- from mm_eth.utils import from_wei_str, name_network
7
-
8
-
9
- def run(urls: list[str], print_format: PrintFormat, proxy: str | None) -> None:
10
- json_result: dict[str, object] = {}
11
- table = Table(title="nodes")
12
- if print_format == PrintFormat.TABLE:
13
- table.add_column("url")
14
- table.add_column("chain_id")
15
- table.add_column("chain_name")
16
- table.add_column("block_number")
17
- table.add_column("base_fee")
18
-
19
- with Live(table, refresh_per_second=0.5):
20
- for url in urls:
21
- chain_id_res = rpc.eth_chain_id(url, timeout=10, proxies=proxy)
22
- chain_id = chain_id_res.ok_or_err()
23
- chain_name = ""
24
- if isinstance(chain_id_res, Ok):
25
- chain_name = name_network(chain_id_res.ok)
26
- block_number = rpc.eth_block_number(url, timeout=10, proxies=proxy).ok_or_err()
27
- base_fee = rpc.get_base_fee_per_gas(url, timeout=10, proxies=proxy).map_or_else(
28
- lambda err: err,
29
- lambda ok: from_wei_str(ok, "gwei"),
30
- )
31
-
32
- json_result[url] = {
33
- "chain_id": chain_id,
34
- "chain_name": chain_name,
35
- "block_number": block_number,
36
- "base_fee": base_fee,
37
- }
38
- if print_format == PrintFormat.TABLE:
39
- table.add_row(url, str(chain_id), chain_name, str(block_number), base_fee)
40
- print_plain(f"url: {url}", print_format)
41
- print_plain(f"chain_id: {chain_id}", print_format)
42
- print_plain(f"chain_name: {chain_name}", print_format)
43
- print_plain(f"block_number: {block_number}", print_format)
44
- print_plain(f"base_fee: {base_fee}", print_format)
45
- print_plain("", print_format)
46
-
47
- print_json(json_result, print_format)
@@ -1,10 +0,0 @@
1
- from mm_std import fatal, print_plain
2
-
3
- from mm_eth import account
4
-
5
-
6
- def run(private_key: str) -> None:
7
- try:
8
- print_plain(account.private_to_address(private_key))
9
- except Exception as e:
10
- fatal(f"wrong private key: {e}")
mm_eth/cli/cmd/rpc_cmd.py DELETED
@@ -1,81 +0,0 @@
1
- import json
2
- from typing import cast
3
-
4
- from mm_std import fatal, hr, print_console, str_starts_with_any
5
- from rich import print_json
6
-
7
- from mm_eth.cli.cli_utils import public_rpc_url
8
-
9
-
10
- def run(rpc_url: str, method: str, params: str, hex2dec: bool) -> None:
11
- rpc_url = public_rpc_url(rpc_url)
12
- if not method:
13
- return list_all_methods()
14
- if not str_starts_with_any(rpc_url, ["http://", "https://"]):
15
- fatal(f"invalid rpc_url: {rpc_url}")
16
- params = params.replace("'", '"')
17
- data = {"jsonrpc": "2.0", "method": method, "params": parse_method_params(method, params), "id": 1}
18
- res = hr(rpc_url, method="POST", params=data, json_params=True)
19
- if res.json:
20
- print_json(data=res.json)
21
- result_value: str = res.json.get("result", "")
22
- if hex2dec and result_value.startswith(("0x", "0X")):
23
- print_console("hex2dec", int(result_value, 16))
24
- else:
25
- fatal(str(res))
26
-
27
-
28
- def parse_method_params(method: str, params_str: str) -> list[object]:
29
- if params_str.startswith("["):
30
- params = json.loads(params_str)
31
- else:
32
- params = params_str.split()
33
- if method in ["eth_getBalance", "eth_getTransactionCount", "eth_getCode"] and len(params) == 1:
34
- params.append("latest")
35
- return cast(list[object], params)
36
-
37
-
38
- def list_all_methods() -> None:
39
- all_methods = """
40
- web3_clientVersion
41
- web3_sha3
42
- net_version
43
- net_listening
44
- net_peerCount
45
- eth_protocolVersion
46
- eth_syncing
47
- eth_chainId
48
- eth_gasPrice
49
- eth_accounts
50
- eth_blockNumber
51
- eth_getBalance
52
- eth_getStorageAt
53
- eth_getTransactionCount
54
- eth_getBlockTransactionCountByHash
55
- eth_getBlockTransactionCountByNumber
56
- eth_getUncleCountByBlockHash
57
- eth_getUncleCountByBlockNumber
58
- eth_getCode
59
- eth_sign
60
- eth_signTransaction
61
- eth_sendTransaction
62
- eth_sendRawTransaction
63
- eth_call
64
- eth_estimateGas
65
- eth_getBlockByHash
66
- eth_getBlockByNumber
67
- eth_getTransactionByHash
68
- eth_getTransactionByBlockHashAndIndex
69
- eth_getTransactionByBlockNumberAndIndex
70
- eth_getTransactionReceipt
71
- eth_getUncleByBlockHashAndIndex
72
- eth_getUncleByBlockNumberAndIndex
73
- eth_newFilter
74
- eth_newBlockFilter
75
- eth_newPendingTransactionFilter
76
- eth_uninstallFilter
77
- eth_getFilterChanges
78
- eth_getFilterLogs
79
- eth_getLogs
80
- """.strip()
81
- print_console(all_methods)