mm-eth 0.5.0__tar.gz → 0.5.2__tar.gz
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_eth-0.5.0 → mm_eth-0.5.2}/PKG-INFO +3 -2
- mm_eth-0.5.2/README.md +10 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/pyproject.toml +21 -19
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cli.py +12 -12
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cli_utils.py +2 -0
- mm_eth-0.5.2/src/mm_eth/cli/cmd/balance_cmd.py +47 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/example_cmd.py +2 -2
- mm_eth-0.5.2/src/mm_eth/cli/cmd/node_cmd.py +78 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/transfer_cmd.py +7 -5
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/examples/transfer.toml +12 -8
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/cli/cmd/test_node_cmd.py +1 -1
- {mm_eth-0.5.0 → mm_eth-0.5.2}/uv.lock +57 -51
- mm_eth-0.5.0/README.txt +0 -2
- mm_eth-0.5.0/src/mm_eth/cli/cmd/balance_cmd.py +0 -51
- mm_eth-0.5.0/src/mm_eth/cli/cmd/node_cmd.py +0 -47
- {mm_eth-0.5.0 → mm_eth-0.5.2}/.gitignore +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/dict.dic +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/justfile +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/__init__.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/abi.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/account.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/anvil.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/__init__.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/calcs.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/__init__.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/balances_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/call_contract_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/deploy_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/encode_input_data_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/rpc_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/solc_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/token_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/tx_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/vault_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/wallet/__init__.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/wallet/mnemonic_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/cmd/wallet/private_key_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/examples/balances.toml +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/examples/call_contract.toml +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/print_helpers.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/rpc_helpers.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/cli/validators.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/constants.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/deploy.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/ens.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/erc20.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/ethernodes.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/json_encoder.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/py.typed +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/rpc.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/solc.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/tx.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/utils.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/src/mm_eth/vault.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/__init__.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/cli/__init__.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/cli/cmd/__init__.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/cli/cmd/test_balance_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/cli/cmd/test_mnemonic_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/cli/cmd/test_private_key_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/cli/cmd/test_solc_cmd.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/cli/test_calcs.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/conftest.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/contracts/ERC20.sol +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/contracts/abi/ERC20.json +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/test_abi.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/test_account.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/test_ethernodes.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/test_rpc.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/test_tx.py +0 -0
- {mm_eth-0.5.0 → mm_eth-0.5.2}/tests/test_utils.py +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mm-eth
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Requires-Python: >=3.12
|
|
5
|
-
Requires-Dist:
|
|
5
|
+
Requires-Dist: cryptography>=44.0.1
|
|
6
|
+
Requires-Dist: mm-crypto-utils>=0.2.4
|
|
6
7
|
Requires-Dist: typer>=0.15.1
|
|
7
8
|
Requires-Dist: web3~=7.8.0
|
|
8
9
|
Requires-Dist: websocket-client~=1.8.0
|
mm_eth-0.5.2/README.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# mm-eth
|
|
2
|
+
A Python library and cli tool for interacting with EVM blockchains.
|
|
3
|
+
|
|
4
|
+
### Install on Ubuntu
|
|
5
|
+
```shell
|
|
6
|
+
sudo apt update && sudo apt-get install build-essential libgmp3-dev python3-dev -y
|
|
7
|
+
sudo curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
8
|
+
source $HOME/.local/bin/env
|
|
9
|
+
uv tool install mm-eth
|
|
10
|
+
```
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mm-eth"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.2"
|
|
4
4
|
description = ""
|
|
5
5
|
requires-python = ">=3.12"
|
|
6
6
|
dependencies = [
|
|
7
|
-
"mm-crypto-utils>=0.2.
|
|
7
|
+
"mm-crypto-utils>=0.2.4",
|
|
8
8
|
"websocket-client~=1.8.0",
|
|
9
9
|
"web3~=7.8.0",
|
|
10
10
|
"typer>=0.15.1",
|
|
11
|
+
"cryptography>=44.0.1", # remove after mm-crypto-utils update
|
|
11
12
|
]
|
|
12
13
|
[project.scripts]
|
|
13
14
|
mm-eth = "mm_eth.cli.cli:app"
|
|
@@ -20,7 +21,7 @@ build-backend = "hatchling.build"
|
|
|
20
21
|
dev-dependencies = [
|
|
21
22
|
"pytest~=8.3.4",
|
|
22
23
|
"pytest-xdist~=3.6.1",
|
|
23
|
-
"ruff~=0.9.
|
|
24
|
+
"ruff~=0.9.6",
|
|
24
25
|
"pip-audit~=2.8.0",
|
|
25
26
|
"bandit~=1.8.2",
|
|
26
27
|
"mypy~=1.15.0",
|
|
@@ -44,28 +45,29 @@ line-length = 130
|
|
|
44
45
|
target-version = "py313"
|
|
45
46
|
[tool.ruff.lint]
|
|
46
47
|
select = ["ALL"]
|
|
48
|
+
# fixable = ["F401"]
|
|
47
49
|
ignore = [
|
|
48
|
-
"TC",
|
|
49
|
-
"A005",
|
|
50
|
-
"ERA001",
|
|
51
|
-
"PT",
|
|
52
|
-
"D",
|
|
53
|
-
"FIX",
|
|
50
|
+
"TC", # flake8-type-checking, TYPE_CHECKING is dangerous, for example it doesn't work with pydantic
|
|
51
|
+
"A005", # flake8-builtins: stdlib-module-shadowing
|
|
52
|
+
"ERA001", # eradicate: commented-out-code
|
|
53
|
+
"PT", # flake8-pytest-style
|
|
54
|
+
"D", # pydocstyle
|
|
55
|
+
"FIX", # flake8-fixme
|
|
54
56
|
"PLR0911", # pylint: too-many-return-statements
|
|
55
57
|
"PLR0912", # pylint: too-many-branches
|
|
56
58
|
"PLR0913", # pylint: too-many-arguments
|
|
57
59
|
"PLR2004", # pylint: magic-value-comparison
|
|
58
60
|
"PLC0414", # pylint: useless-import-alias
|
|
59
|
-
"FBT",
|
|
60
|
-
"EM",
|
|
61
|
-
"TRY003",
|
|
62
|
-
"C901",
|
|
63
|
-
"BLE001",
|
|
64
|
-
"S311",
|
|
65
|
-
"TD002",
|
|
66
|
-
"TD003",
|
|
67
|
-
"RET503",
|
|
68
|
-
"COM812",
|
|
61
|
+
"FBT", # flake8-boolean-trap
|
|
62
|
+
"EM", # flake8-errmsg
|
|
63
|
+
"TRY003", # tryceratops: raise-vanilla-args
|
|
64
|
+
"C901", # mccabe: complex-structure,
|
|
65
|
+
"BLE001", # flake8-blind-except
|
|
66
|
+
"S311", # bandit: suspicious-non-cryptographic-random-usage
|
|
67
|
+
"TD002", # flake8-todos: missing-todo-author
|
|
68
|
+
"TD003", # flake8-todos: missing-todo-link
|
|
69
|
+
"RET503", # flake8-return: implicit-return
|
|
70
|
+
"COM812", # it's used in ruff formatter
|
|
69
71
|
]
|
|
70
72
|
[tool.ruff.lint.pep8-naming]
|
|
71
73
|
classmethod-decorators = ["field_validator"]
|
|
@@ -53,6 +53,16 @@ def balance_command(
|
|
|
53
53
|
balance_cmd.run(rpc_url, wallet_address, token_address, wei, print_format)
|
|
54
54
|
|
|
55
55
|
|
|
56
|
+
@app.command(name="balances", help="Print base and ERC20 token balances")
|
|
57
|
+
def balances_command(
|
|
58
|
+
config_path: Path,
|
|
59
|
+
print_config: bool = typer.Option(False, "--config", "-c", help="Print config and exit"),
|
|
60
|
+
nonce: bool = typer.Option(False, "--nonce", "-n", help="Print nonce also"),
|
|
61
|
+
wei: bool = typer.Option(False, "--wei", "-w", help="Show balances in WEI"),
|
|
62
|
+
) -> None:
|
|
63
|
+
balances_cmd.run(BalancesCmdParams(config_path=config_path, print_config=print_config, wei=wei, show_nonce=nonce))
|
|
64
|
+
|
|
65
|
+
|
|
56
66
|
@app.command(name="token", help="Get token info")
|
|
57
67
|
def token_command(
|
|
58
68
|
token_address: Annotated[str, typer.Argument()],
|
|
@@ -64,10 +74,10 @@ def token_command(
|
|
|
64
74
|
@app.command(name="node", help="Check RPC url")
|
|
65
75
|
def node_command(
|
|
66
76
|
urls: Annotated[list[str], typer.Argument()],
|
|
67
|
-
print_format: Annotated[PrintFormat, typer.Option("--format", "-f", help="Print format")] = PrintFormat.TABLE,
|
|
68
77
|
proxy: Annotated[str | None, typer.Option("--proxy", "-p", help="Proxy")] = None,
|
|
78
|
+
print_format: Annotated[PrintFormat, typer.Option("--format", "-f", help="Print format")] = PrintFormat.TABLE,
|
|
69
79
|
) -> None:
|
|
70
|
-
node_cmd.run(urls,
|
|
80
|
+
node_cmd.run(urls, proxy, print_format)
|
|
71
81
|
|
|
72
82
|
|
|
73
83
|
@wallet_app.command(name="mnemonic", help="Generate eth accounts based on a mnemonic")
|
|
@@ -185,16 +195,6 @@ def transfer_command(
|
|
|
185
195
|
# )
|
|
186
196
|
|
|
187
197
|
|
|
188
|
-
@app.command(name="balances", help="Print base and ERC20 token balances")
|
|
189
|
-
def balances_command(
|
|
190
|
-
config_path: Path,
|
|
191
|
-
print_config: bool = typer.Option(False, "--config", "-c", help="Print config and exit"),
|
|
192
|
-
nonce: bool = typer.Option(False, "--nonce", "-n", help="Print nonce also"),
|
|
193
|
-
wei: bool = typer.Option(False, "--wei", "-w", help="Show balances in WEI"),
|
|
194
|
-
) -> None:
|
|
195
|
-
balances_cmd.run(BalancesCmdParams(config_path=config_path, print_config=print_config, wei=wei, show_nonce=nonce))
|
|
196
|
-
|
|
197
|
-
|
|
198
198
|
@app.command(name="call-contract", help="Call a method on a contract")
|
|
199
199
|
def call_contract_command(
|
|
200
200
|
config_path: Path,
|
|
@@ -23,6 +23,8 @@ def public_rpc_url(url: str | None) -> str:
|
|
|
23
23
|
match url.lower():
|
|
24
24
|
case "mainnet" | "1":
|
|
25
25
|
return "https://ethereum.publicnode.com"
|
|
26
|
+
case "sepolia" | "11155111":
|
|
27
|
+
return "https://ethereum-sepolia-rpc.publicnode.com"
|
|
26
28
|
case "opbnb" | "204":
|
|
27
29
|
return "https://opbnb-mainnet-rpc.bnbchain.org"
|
|
28
30
|
case "base" | "8453":
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from mm_std import PrintFormat, print_json, print_plain
|
|
2
|
+
|
|
3
|
+
from mm_eth import erc20, rpc
|
|
4
|
+
from mm_eth.cli.cli_utils import public_rpc_url
|
|
5
|
+
from mm_eth.utils import from_wei_str
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def run(rpc_url: str, wallet_address: str, token_address: str | None, wei: bool, print_format: PrintFormat) -> None:
|
|
9
|
+
result: dict[str, object] = {}
|
|
10
|
+
rpc_url = public_rpc_url(rpc_url)
|
|
11
|
+
|
|
12
|
+
# nonce
|
|
13
|
+
result["nonce"] = rpc.eth_get_transaction_count(rpc_url, wallet_address).ok_or_err()
|
|
14
|
+
if print_format == PrintFormat.PLAIN:
|
|
15
|
+
print_plain(f"nonce: {result['nonce']}")
|
|
16
|
+
|
|
17
|
+
# eth balance
|
|
18
|
+
result["eth_balance"] = (
|
|
19
|
+
rpc.eth_get_balance(rpc_url, wallet_address).map(lambda x: str(x) if wei else from_wei_str(x, "eth")).ok_or_err()
|
|
20
|
+
)
|
|
21
|
+
if print_format == PrintFormat.PLAIN:
|
|
22
|
+
print_plain(f"eth_balance: {result['eth_balance']}")
|
|
23
|
+
|
|
24
|
+
if token_address:
|
|
25
|
+
# token decimal
|
|
26
|
+
result["token_decimal"] = erc20.get_decimals(rpc_url, token_address).ok_or_err()
|
|
27
|
+
if print_format == PrintFormat.PLAIN:
|
|
28
|
+
print_plain(f"token_decimal: {result['token_decimal']}")
|
|
29
|
+
|
|
30
|
+
# token symbol
|
|
31
|
+
result["token_symbol"] = erc20.get_symbol(rpc_url, token_address).ok_or_err()
|
|
32
|
+
if print_format == PrintFormat.PLAIN:
|
|
33
|
+
print_plain(f"token_symbol: {result['token_symbol']}")
|
|
34
|
+
|
|
35
|
+
# token balance
|
|
36
|
+
result["token_balance"] = (
|
|
37
|
+
erc20.get_balance(rpc_url, token_address, wallet_address)
|
|
38
|
+
.map(
|
|
39
|
+
lambda x: str(x) if wei or not result["token_decimal"] else from_wei_str(x, "t", decimals=result["token_decimal"]) # type: ignore[arg-type]
|
|
40
|
+
)
|
|
41
|
+
.ok_or_err()
|
|
42
|
+
)
|
|
43
|
+
if print_format == PrintFormat.PLAIN:
|
|
44
|
+
print_plain(f"token_balance: {result['token_balance']}")
|
|
45
|
+
|
|
46
|
+
if print_format == PrintFormat.JSON:
|
|
47
|
+
print_json(data=result)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
|
-
from mm_std import
|
|
3
|
+
from mm_std import pretty_print_toml
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def run(command: str) -> None:
|
|
7
7
|
command = command.replace("-", "_")
|
|
8
8
|
example_file = Path(Path(__file__).parent.absolute(), "../examples", f"{command}.toml")
|
|
9
|
-
|
|
9
|
+
pretty_print_toml(example_file.read_text())
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import pydash
|
|
2
|
+
from mm_std import Ok, PrintFormat, print_json
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
from rich.live import Live
|
|
5
|
+
from rich.table import Table
|
|
6
|
+
|
|
7
|
+
from mm_eth import rpc
|
|
8
|
+
from mm_eth.utils import from_wei_str, name_network
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class NodeInfo(BaseModel):
|
|
12
|
+
url: str
|
|
13
|
+
chain_id: int | str
|
|
14
|
+
chain_name: str
|
|
15
|
+
block_number: int | str
|
|
16
|
+
base_fee: str
|
|
17
|
+
|
|
18
|
+
def table_row(self) -> list[object]:
|
|
19
|
+
return [self.url, self.chain_id, self.chain_name, self.block_number, self.base_fee]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class LiveTable:
|
|
23
|
+
def __init__(self, table: Table, ignore: bool = False) -> None:
|
|
24
|
+
self.ignore = ignore
|
|
25
|
+
if ignore:
|
|
26
|
+
return
|
|
27
|
+
self.table = table
|
|
28
|
+
self.live = Live(table, auto_refresh=False)
|
|
29
|
+
self.live.start()
|
|
30
|
+
|
|
31
|
+
def add_row(self, *args: object) -> None:
|
|
32
|
+
if self.ignore:
|
|
33
|
+
return
|
|
34
|
+
self.table.add_row(*(str(a) for a in args))
|
|
35
|
+
self.live.refresh()
|
|
36
|
+
|
|
37
|
+
def stop(self) -> None:
|
|
38
|
+
if self.ignore:
|
|
39
|
+
return
|
|
40
|
+
self.live.stop()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def run(urls: list[str], proxy: str | None, print_format: PrintFormat) -> None:
|
|
44
|
+
urls = pydash.uniq(urls)
|
|
45
|
+
result = []
|
|
46
|
+
live_table = LiveTable(
|
|
47
|
+
Table("url", "chain_id", "chain_name", "block_number", "base_fee", title="nodes"),
|
|
48
|
+
ignore=print_format != PrintFormat.TABLE,
|
|
49
|
+
)
|
|
50
|
+
for url in urls:
|
|
51
|
+
node_info = _get_node_info(url, proxy)
|
|
52
|
+
live_table.add_row(*node_info.table_row())
|
|
53
|
+
result.append(node_info)
|
|
54
|
+
|
|
55
|
+
live_table.stop()
|
|
56
|
+
|
|
57
|
+
if print_format == PrintFormat.JSON:
|
|
58
|
+
print_json(data=result)
|
|
59
|
+
# print_json(data=result)
|
|
60
|
+
# table = Table(*["url", "chain_id", "chain_name", "block_number", "base_fee"], title="nodes")
|
|
61
|
+
|
|
62
|
+
# with Live(table, refresh_per_second=0.5):
|
|
63
|
+
# for url in urls:
|
|
64
|
+
# table.add_row(url, str(chain_id), chain_name, str(block_number), base_fee)
|
|
65
|
+
|
|
66
|
+
|
|
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()
|
|
70
|
+
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"),
|
|
77
|
+
)
|
|
78
|
+
return NodeInfo(url=url, chain_id=chain_id, chain_name=chain_name, block_number=block_number, base_fee=base_fee)
|
|
@@ -31,7 +31,7 @@ class Config(BaseConfig):
|
|
|
31
31
|
max_fee: Annotated[str, AfterValidator(Validators.valid_eth_expression("base_fee"))]
|
|
32
32
|
priority_fee: Annotated[str, AfterValidator(Validators.valid_eth_expression())]
|
|
33
33
|
max_fee_limit: Annotated[str | None, AfterValidator(Validators.valid_eth_expression())] = None
|
|
34
|
-
|
|
34
|
+
default_value: Annotated[str | None, AfterValidator(Validators.valid_eth_or_token_expression("balance"))] = None
|
|
35
35
|
value_min_limit: Annotated[str | None, AfterValidator(Validators.valid_eth_or_token_expression())] = None
|
|
36
36
|
gas: Annotated[str, AfterValidator(Validators.valid_eth_expression("estimate"))]
|
|
37
37
|
delay: Annotated[str | None, AfterValidator(Validators.valid_calc_decimal_value())] = None # in seconds
|
|
@@ -51,18 +51,20 @@ class Config(BaseConfig):
|
|
|
51
51
|
raise ValueError("private keys are not set for all addresses")
|
|
52
52
|
|
|
53
53
|
for transfer in self.transfers: # If value is not set for a transfer, then set it to the global value of the config.
|
|
54
|
-
if not transfer.value:
|
|
55
|
-
transfer.value = self.
|
|
54
|
+
if not transfer.value and self.default_value:
|
|
55
|
+
transfer.value = self.default_value
|
|
56
56
|
for transfer in self.transfers: # Check all transfers have a value.
|
|
57
57
|
if not transfer.value:
|
|
58
58
|
raise ValueError(f"{transfer.log_prefix}: value is not set")
|
|
59
59
|
|
|
60
60
|
if self.token:
|
|
61
|
-
|
|
61
|
+
if self.default_value:
|
|
62
|
+
Validators.valid_token_expression("balance")(self.default_value)
|
|
62
63
|
if self.value_min_limit:
|
|
63
64
|
Validators.valid_token_expression()(self.value_min_limit)
|
|
64
65
|
else:
|
|
65
|
-
|
|
66
|
+
if self.default_value:
|
|
67
|
+
Validators.valid_eth_expression("balance")(self.default_value)
|
|
66
68
|
if self.value_min_limit:
|
|
67
69
|
Validators.valid_eth_expression()(self.value_min_limit)
|
|
68
70
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# Each line is a transfer instruction, with format: from_address to_address [value]
|
|
2
|
+
# Value is optional. If value is not set, default_value will be used
|
|
3
|
+
# value is an expression that can contain variable 'balance' and 'random' function
|
|
1
4
|
transfers = """
|
|
2
|
-
# from_address to_address value
|
|
3
5
|
0x10fd602Bff689e64D4720D1DCCCD3494f1f16623 0x58487485c3858109f5A37e42546FE87473f79a4b 0.1t # comments are allowed here
|
|
4
6
|
0x97C77B548aE0d4925F5C201220fC6d8996424309 0x7EdF3b8579c21A8820b4C0B8352541c1CE04045f 0.2balance-random(0.1t,0.5t)
|
|
5
|
-
0x10ecB8d838746643E613f6B5218C8e342593225c 0xE19242B72a4833eD86F1b2015d4E59052A2b278b
|
|
7
|
+
0x10ecB8d838746643E613f6B5218C8e342593225c 0xE19242B72a4833eD86F1b2015d4E59052A2b278b
|
|
6
8
|
file: /path/to/other_transfers.txt # transfers from this file will be added
|
|
7
9
|
"""
|
|
8
10
|
|
|
@@ -14,17 +16,19 @@ file: /path/to/other_private_keys.txt
|
|
|
14
16
|
|
|
15
17
|
token = "0x60631C856303731BE4deb81C0303F80B652aA5b4" # If not specified, it ETH transfers
|
|
16
18
|
|
|
17
|
-
max_fee = "1.2base_fee+1gwei+random(1,200)" # supported
|
|
18
|
-
|
|
19
|
-
max_fee_limit = "10.1gwei-random(1,10)" # optional
|
|
19
|
+
max_fee = "1.2base_fee+1gwei+random(1,200)" # 'base_fee' variable is supported
|
|
20
20
|
|
|
21
21
|
priority_fee = "1gwei+random(1,12)"
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
# Don't transfer if max_fee > max_fee_limit, optional
|
|
24
|
+
max_fee_limit = "10.1gwei-random(1,10)"
|
|
25
|
+
|
|
26
|
+
gas = "estimate+random(100,200)-19" # 'estimate' variable is supported
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
# default_value is used if transfer.value is not set in transfers. It's optional.
|
|
29
|
+
default_value = "0.5balance-random(1.5t,3t)+11t" # supported var_name=balance. For ERC20 token use 't' suffix.
|
|
26
30
|
|
|
27
|
-
value_min_limit = "0.5t+random(1,2)-7"
|
|
31
|
+
value_min_limit = "0.5t+random(1,2)-7" # don't transfer if transfer.value is less than this
|
|
28
32
|
|
|
29
33
|
delay = "random(1.123,10)+1" # secs, optional
|
|
30
34
|
|
|
@@ -310,33 +310,37 @@ wheels = [
|
|
|
310
310
|
|
|
311
311
|
[[package]]
|
|
312
312
|
name = "cryptography"
|
|
313
|
-
version = "44.0.
|
|
313
|
+
version = "44.0.1"
|
|
314
314
|
source = { registry = "https://pypi.org/simple" }
|
|
315
315
|
dependencies = [
|
|
316
316
|
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
|
317
317
|
]
|
|
318
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
319
|
-
wheels = [
|
|
320
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
321
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
322
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
323
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
324
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
325
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
326
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
327
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
328
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
329
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
330
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
331
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
332
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
333
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
334
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
335
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
336
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
337
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
338
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
339
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
318
|
+
sdist = { url = "https://files.pythonhosted.org/packages/c7/67/545c79fe50f7af51dbad56d16b23fe33f63ee6a5d956b3cb68ea110cbe64/cryptography-44.0.1.tar.gz", hash = "sha256:f51f5705ab27898afda1aaa430f34ad90dc117421057782022edf0600bec5f14", size = 710819 }
|
|
319
|
+
wheels = [
|
|
320
|
+
{ url = "https://files.pythonhosted.org/packages/72/27/5e3524053b4c8889da65cf7814a9d0d8514a05194a25e1e34f46852ee6eb/cryptography-44.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf688f615c29bfe9dfc44312ca470989279f0e94bb9f631f85e3459af8efc009", size = 6642022 },
|
|
321
|
+
{ url = "https://files.pythonhosted.org/packages/34/b9/4d1fa8d73ae6ec350012f89c3abfbff19fc95fe5420cf972e12a8d182986/cryptography-44.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd7c7e2d71d908dc0f8d2027e1604102140d84b155e658c20e8ad1304317691f", size = 3943865 },
|
|
322
|
+
{ url = "https://files.pythonhosted.org/packages/6e/57/371a9f3f3a4500807b5fcd29fec77f418ba27ffc629d88597d0d1049696e/cryptography-44.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887143b9ff6bad2b7570da75a7fe8bbf5f65276365ac259a5d2d5147a73775f2", size = 4162562 },
|
|
323
|
+
{ url = "https://files.pythonhosted.org/packages/c5/1d/5b77815e7d9cf1e3166988647f336f87d5634a5ccecec2ffbe08ef8dd481/cryptography-44.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:322eb03ecc62784536bc173f1483e76747aafeb69c8728df48537eb431cd1911", size = 3951923 },
|
|
324
|
+
{ url = "https://files.pythonhosted.org/packages/28/01/604508cd34a4024467cd4105887cf27da128cba3edd435b54e2395064bfb/cryptography-44.0.1-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:21377472ca4ada2906bc313168c9dc7b1d7ca417b63c1c3011d0c74b7de9ae69", size = 3685194 },
|
|
325
|
+
{ url = "https://files.pythonhosted.org/packages/c6/3d/d3c55d4f1d24580a236a6753902ef6d8aafd04da942a1ee9efb9dc8fd0cb/cryptography-44.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:df978682c1504fc93b3209de21aeabf2375cb1571d4e61907b3e7a2540e83026", size = 4187790 },
|
|
326
|
+
{ url = "https://files.pythonhosted.org/packages/ea/a6/44d63950c8588bfa8594fd234d3d46e93c3841b8e84a066649c566afb972/cryptography-44.0.1-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:eb3889330f2a4a148abead555399ec9a32b13b7c8ba969b72d8e500eb7ef84cd", size = 3951343 },
|
|
327
|
+
{ url = "https://files.pythonhosted.org/packages/c1/17/f5282661b57301204cbf188254c1a0267dbd8b18f76337f0a7ce1038888c/cryptography-44.0.1-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:8e6a85a93d0642bd774460a86513c5d9d80b5c002ca9693e63f6e540f1815ed0", size = 4187127 },
|
|
328
|
+
{ url = "https://files.pythonhosted.org/packages/f3/68/abbae29ed4f9d96596687f3ceea8e233f65c9645fbbec68adb7c756bb85a/cryptography-44.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6f76fdd6fd048576a04c5210d53aa04ca34d2ed63336d4abd306d0cbe298fddf", size = 4070666 },
|
|
329
|
+
{ url = "https://files.pythonhosted.org/packages/0f/10/cf91691064a9e0a88ae27e31779200b1505d3aee877dbe1e4e0d73b4f155/cryptography-44.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6c8acf6f3d1f47acb2248ec3ea261171a671f3d9428e34ad0357148d492c7864", size = 4288811 },
|
|
330
|
+
{ url = "https://files.pythonhosted.org/packages/38/78/74ea9eb547d13c34e984e07ec8a473eb55b19c1451fe7fc8077c6a4b0548/cryptography-44.0.1-cp37-abi3-win32.whl", hash = "sha256:24979e9f2040c953a94bf3c6782e67795a4c260734e5264dceea65c8f4bae64a", size = 2771882 },
|
|
331
|
+
{ url = "https://files.pythonhosted.org/packages/cf/6c/3907271ee485679e15c9f5e93eac6aa318f859b0aed8d369afd636fafa87/cryptography-44.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:fd0ee90072861e276b0ff08bd627abec29e32a53b2be44e41dbcdf87cbee2b00", size = 3206989 },
|
|
332
|
+
{ url = "https://files.pythonhosted.org/packages/9f/f1/676e69c56a9be9fd1bffa9bc3492366901f6e1f8f4079428b05f1414e65c/cryptography-44.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a2d8a7045e1ab9b9f803f0d9531ead85f90c5f2859e653b61497228b18452008", size = 6643714 },
|
|
333
|
+
{ url = "https://files.pythonhosted.org/packages/ba/9f/1775600eb69e72d8f9931a104120f2667107a0ee478f6ad4fe4001559345/cryptography-44.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8272f257cf1cbd3f2e120f14c68bff2b6bdfcc157fafdee84a1b795efd72862", size = 3943269 },
|
|
334
|
+
{ url = "https://files.pythonhosted.org/packages/25/ba/e00d5ad6b58183829615be7f11f55a7b6baa5a06910faabdc9961527ba44/cryptography-44.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e8d181e90a777b63f3f0caa836844a1182f1f265687fac2115fcf245f5fbec3", size = 4166461 },
|
|
335
|
+
{ url = "https://files.pythonhosted.org/packages/b3/45/690a02c748d719a95ab08b6e4decb9d81e0ec1bac510358f61624c86e8a3/cryptography-44.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:436df4f203482f41aad60ed1813811ac4ab102765ecae7a2bbb1dbb66dcff5a7", size = 3950314 },
|
|
336
|
+
{ url = "https://files.pythonhosted.org/packages/e6/50/bf8d090911347f9b75adc20f6f6569ed6ca9b9bff552e6e390f53c2a1233/cryptography-44.0.1-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4f422e8c6a28cf8b7f883eb790695d6d45b0c385a2583073f3cec434cc705e1a", size = 3686675 },
|
|
337
|
+
{ url = "https://files.pythonhosted.org/packages/e1/e7/cfb18011821cc5f9b21efb3f94f3241e3a658d267a3bf3a0f45543858ed8/cryptography-44.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:72198e2b5925155497a5a3e8c216c7fb3e64c16ccee11f0e7da272fa93b35c4c", size = 4190429 },
|
|
338
|
+
{ url = "https://files.pythonhosted.org/packages/07/ef/77c74d94a8bfc1a8a47b3cafe54af3db537f081742ee7a8a9bd982b62774/cryptography-44.0.1-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2a46a89ad3e6176223b632056f321bc7de36b9f9b93b2cc1cccf935a3849dc62", size = 3950039 },
|
|
339
|
+
{ url = "https://files.pythonhosted.org/packages/6d/b9/8be0ff57c4592382b77406269b1e15650c9f1a167f9e34941b8515b97159/cryptography-44.0.1-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:53f23339864b617a3dfc2b0ac8d5c432625c80014c25caac9082314e9de56f41", size = 4189713 },
|
|
340
|
+
{ url = "https://files.pythonhosted.org/packages/78/e1/4b6ac5f4100545513b0847a4d276fe3c7ce0eacfa73e3b5ebd31776816ee/cryptography-44.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:888fcc3fce0c888785a4876ca55f9f43787f4c5c1cc1e2e0da71ad481ff82c5b", size = 4071193 },
|
|
341
|
+
{ url = "https://files.pythonhosted.org/packages/3d/cb/afff48ceaed15531eab70445abe500f07f8f96af2bb35d98af6bfa89ebd4/cryptography-44.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:00918d859aa4e57db8299607086f793fa7813ae2ff5a4637e318a25ef82730f7", size = 4289566 },
|
|
342
|
+
{ url = "https://files.pythonhosted.org/packages/30/6f/4eca9e2e0f13ae459acd1ca7d9f0257ab86e68f44304847610afcb813dc9/cryptography-44.0.1-cp39-abi3-win32.whl", hash = "sha256:9b336599e2cb77b1008cb2ac264b290803ec5e8e89d618a5e978ff5eb6f715d9", size = 2772371 },
|
|
343
|
+
{ url = "https://files.pythonhosted.org/packages/d2/05/5533d30f53f10239616a357f080892026db2d550a40c393d0a8a7af834a9/cryptography-44.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:e403f7f766ded778ecdb790da786b418a9f2394f36e8cc8b796cc056ab05f44f", size = 3207303 },
|
|
340
344
|
]
|
|
341
345
|
|
|
342
346
|
[[package]]
|
|
@@ -713,21 +717,22 @@ wheels = [
|
|
|
713
717
|
|
|
714
718
|
[[package]]
|
|
715
719
|
name = "mm-crypto-utils"
|
|
716
|
-
version = "0.2.
|
|
720
|
+
version = "0.2.4"
|
|
717
721
|
source = { registry = "https://pypi.org/simple" }
|
|
718
722
|
dependencies = [
|
|
719
723
|
{ name = "loguru" },
|
|
720
724
|
{ name = "mm-std" },
|
|
721
725
|
]
|
|
722
726
|
wheels = [
|
|
723
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
727
|
+
{ url = "https://files.pythonhosted.org/packages/1b/80/261c463cad1176b14d92b7390328f89184307f201d9d3117012abe5e8a72/mm_crypto_utils-0.2.4-py3-none-any.whl", hash = "sha256:487214228ce79ffb9a8afeef13d67b578393558d03a0268d4b7747174f9ac7ce", size = 8255 },
|
|
724
728
|
]
|
|
725
729
|
|
|
726
730
|
[[package]]
|
|
727
731
|
name = "mm-eth"
|
|
728
|
-
version = "0.5.
|
|
732
|
+
version = "0.5.2"
|
|
729
733
|
source = { editable = "." }
|
|
730
734
|
dependencies = [
|
|
735
|
+
{ name = "cryptography" },
|
|
731
736
|
{ name = "mm-crypto-utils" },
|
|
732
737
|
{ name = "typer" },
|
|
733
738
|
{ name = "web3" },
|
|
@@ -747,7 +752,8 @@ dev = [
|
|
|
747
752
|
|
|
748
753
|
[package.metadata]
|
|
749
754
|
requires-dist = [
|
|
750
|
-
{ name = "
|
|
755
|
+
{ name = "cryptography", specifier = ">=44.0.1" },
|
|
756
|
+
{ name = "mm-crypto-utils", specifier = ">=0.2.4" },
|
|
751
757
|
{ name = "typer", specifier = ">=0.15.1" },
|
|
752
758
|
{ name = "web3", specifier = "~=7.8.0" },
|
|
753
759
|
{ name = "websocket-client", specifier = "~=1.8.0" },
|
|
@@ -760,13 +766,13 @@ dev = [
|
|
|
760
766
|
{ name = "pip-audit", specifier = "~=2.8.0" },
|
|
761
767
|
{ name = "pytest", specifier = "~=8.3.4" },
|
|
762
768
|
{ name = "pytest-xdist", specifier = "~=3.6.1" },
|
|
763
|
-
{ name = "ruff", specifier = "~=0.9.
|
|
769
|
+
{ name = "ruff", specifier = "~=0.9.6" },
|
|
764
770
|
{ name = "types-pyyaml", specifier = ">=6.0.12.20241230" },
|
|
765
771
|
]
|
|
766
772
|
|
|
767
773
|
[[package]]
|
|
768
774
|
name = "mm-std"
|
|
769
|
-
version = "0.
|
|
775
|
+
version = "0.3.0"
|
|
770
776
|
source = { registry = "https://pypi.org/simple" }
|
|
771
777
|
dependencies = [
|
|
772
778
|
{ name = "cryptography" },
|
|
@@ -778,7 +784,7 @@ dependencies = [
|
|
|
778
784
|
{ name = "rich" },
|
|
779
785
|
]
|
|
780
786
|
wheels = [
|
|
781
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
787
|
+
{ url = "https://files.pythonhosted.org/packages/41/b3/8e14a0eaf34b2db3f4c97eacafff63d63bb8c28f7baf718b3bc99f948dc2/mm_std-0.3.0-py3-none-any.whl", hash = "sha256:3aaab32cb88c29741d7a37cea4b2cb74548ec9b94ea4f8ebf0149f678ad921a3", size = 14693 },
|
|
782
788
|
]
|
|
783
789
|
|
|
784
790
|
[[package]]
|
|
@@ -1323,27 +1329,27 @@ wheels = [
|
|
|
1323
1329
|
|
|
1324
1330
|
[[package]]
|
|
1325
1331
|
name = "ruff"
|
|
1326
|
-
version = "0.9.
|
|
1327
|
-
source = { registry = "https://pypi.org/simple" }
|
|
1328
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1329
|
-
wheels = [
|
|
1330
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1331
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1332
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1333
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1334
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1335
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1336
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1337
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1338
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1339
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1340
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1341
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1342
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1343
|
-
{ url = "https://files.pythonhosted.org/packages/ec/
|
|
1344
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1345
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1346
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1332
|
+
version = "0.9.6"
|
|
1333
|
+
source = { registry = "https://pypi.org/simple" }
|
|
1334
|
+
sdist = { url = "https://files.pythonhosted.org/packages/2a/e1/e265aba384343dd8ddd3083f5e33536cd17e1566c41453a5517b5dd443be/ruff-0.9.6.tar.gz", hash = "sha256:81761592f72b620ec8fa1068a6fd00e98a5ebee342a3642efd84454f3031dca9", size = 3639454 }
|
|
1335
|
+
wheels = [
|
|
1336
|
+
{ url = "https://files.pythonhosted.org/packages/76/e3/3d2c022e687e18cf5d93d6bfa2722d46afc64eaa438c7fbbdd603b3597be/ruff-0.9.6-py3-none-linux_armv6l.whl", hash = "sha256:2f218f356dd2d995839f1941322ff021c72a492c470f0b26a34f844c29cdf5ba", size = 11714128 },
|
|
1337
|
+
{ url = "https://files.pythonhosted.org/packages/e1/22/aff073b70f95c052e5c58153cba735748c9e70107a77d03420d7850710a0/ruff-0.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b908ff4df65dad7b251c9968a2e4560836d8f5487c2f0cc238321ed951ea0504", size = 11682539 },
|
|
1338
|
+
{ url = "https://files.pythonhosted.org/packages/75/a7/f5b7390afd98a7918582a3d256cd3e78ba0a26165a467c1820084587cbf9/ruff-0.9.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b109c0ad2ececf42e75fa99dc4043ff72a357436bb171900714a9ea581ddef83", size = 11132512 },
|
|
1339
|
+
{ url = "https://files.pythonhosted.org/packages/a6/e3/45de13ef65047fea2e33f7e573d848206e15c715e5cd56095589a7733d04/ruff-0.9.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1de4367cca3dac99bcbd15c161404e849bb0bfd543664db39232648dc00112dc", size = 11929275 },
|
|
1340
|
+
{ url = "https://files.pythonhosted.org/packages/7d/f2/23d04cd6c43b2e641ab961ade8d0b5edb212ecebd112506188c91f2a6e6c/ruff-0.9.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3ee4d7c2c92ddfdaedf0bf31b2b176fa7aa8950efc454628d477394d35638b", size = 11466502 },
|
|
1341
|
+
{ url = "https://files.pythonhosted.org/packages/b5/6f/3a8cf166f2d7f1627dd2201e6cbc4cb81f8b7d58099348f0c1ff7b733792/ruff-0.9.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dc1edd1775270e6aa2386119aea692039781429f0be1e0949ea5884e011aa8e", size = 12676364 },
|
|
1342
|
+
{ url = "https://files.pythonhosted.org/packages/f5/c4/db52e2189983c70114ff2b7e3997e48c8318af44fe83e1ce9517570a50c6/ruff-0.9.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4a091729086dffa4bd070aa5dab7e39cc6b9d62eb2bef8f3d91172d30d599666", size = 13335518 },
|
|
1343
|
+
{ url = "https://files.pythonhosted.org/packages/66/44/545f8a4d136830f08f4d24324e7db957c5374bf3a3f7a6c0bc7be4623a37/ruff-0.9.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1bbc6808bf7b15796cef0815e1dfb796fbd383e7dbd4334709642649625e7c5", size = 12823287 },
|
|
1344
|
+
{ url = "https://files.pythonhosted.org/packages/c5/26/8208ef9ee7431032c143649a9967c3ae1aae4257d95e6f8519f07309aa66/ruff-0.9.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:589d1d9f25b5754ff230dce914a174a7c951a85a4e9270613a2b74231fdac2f5", size = 14592374 },
|
|
1345
|
+
{ url = "https://files.pythonhosted.org/packages/31/70/e917781e55ff39c5b5208bda384fd397ffd76605e68544d71a7e40944945/ruff-0.9.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc61dd5131742e21103fbbdcad683a8813be0e3c204472d520d9a5021ca8b217", size = 12500173 },
|
|
1346
|
+
{ url = "https://files.pythonhosted.org/packages/84/f5/e4ddee07660f5a9622a9c2b639afd8f3104988dc4f6ba0b73ffacffa9a8c/ruff-0.9.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5e2d9126161d0357e5c8f30b0bd6168d2c3872372f14481136d13de9937f79b6", size = 11906555 },
|
|
1347
|
+
{ url = "https://files.pythonhosted.org/packages/f1/2b/6ff2fe383667075eef8656b9892e73dd9b119b5e3add51298628b87f6429/ruff-0.9.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:68660eab1a8e65babb5229a1f97b46e3120923757a68b5413d8561f8a85d4897", size = 11538958 },
|
|
1348
|
+
{ url = "https://files.pythonhosted.org/packages/3c/db/98e59e90de45d1eb46649151c10a062d5707b5b7f76f64eb1e29edf6ebb1/ruff-0.9.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c4cae6c4cc7b9b4017c71114115db0445b00a16de3bcde0946273e8392856f08", size = 12117247 },
|
|
1349
|
+
{ url = "https://files.pythonhosted.org/packages/ec/bc/54e38f6d219013a9204a5a2015c09e7a8c36cedcd50a4b01ac69a550b9d9/ruff-0.9.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:19f505b643228b417c1111a2a536424ddde0db4ef9023b9e04a46ed8a1cb4656", size = 12554647 },
|
|
1350
|
+
{ url = "https://files.pythonhosted.org/packages/a5/7d/7b461ab0e2404293c0627125bb70ac642c2e8d55bf590f6fce85f508f1b2/ruff-0.9.6-py3-none-win32.whl", hash = "sha256:194d8402bceef1b31164909540a597e0d913c0e4952015a5b40e28c146121b5d", size = 9949214 },
|
|
1351
|
+
{ url = "https://files.pythonhosted.org/packages/ee/30/c3cee10f915ed75a5c29c1e57311282d1a15855551a64795c1b2bbe5cf37/ruff-0.9.6-py3-none-win_amd64.whl", hash = "sha256:03482d5c09d90d4ee3f40d97578423698ad895c87314c4de39ed2af945633caa", size = 10999914 },
|
|
1352
|
+
{ url = "https://files.pythonhosted.org/packages/e8/a8/d71f44b93e3aa86ae232af1f2126ca7b95c0f515ec135462b3e1f351441c/ruff-0.9.6-py3-none-win_arm64.whl", hash = "sha256:0e2bb706a2be7ddfea4a4af918562fdc1bcb16df255e5fa595bbd800ce322a5a", size = 10177499 },
|
|
1347
1353
|
]
|
|
1348
1354
|
|
|
1349
1355
|
[[package]]
|
mm_eth-0.5.0/README.txt
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
from mm_std import Err, Ok, PrintFormat, fatal, print_json, print_plain
|
|
2
|
-
|
|
3
|
-
from mm_eth import erc20, rpc
|
|
4
|
-
from mm_eth.cli.cli_utils import public_rpc_url
|
|
5
|
-
from mm_eth.utils import from_wei_str
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def run(rpc_url: str, wallet_address: str, token_address: str | None, wei: bool, print_format: PrintFormat) -> None:
|
|
9
|
-
rpc_url = public_rpc_url(rpc_url)
|
|
10
|
-
json_result: dict[str, object] = {}
|
|
11
|
-
|
|
12
|
-
# nonce
|
|
13
|
-
nonce = rpc.eth_get_transaction_count(rpc_url, wallet_address).ok_or_err()
|
|
14
|
-
print_plain(f"nonce: {nonce}", print_format)
|
|
15
|
-
json_result["nonce"] = nonce
|
|
16
|
-
|
|
17
|
-
# balance
|
|
18
|
-
balance_res = rpc.eth_get_balance(rpc_url, wallet_address)
|
|
19
|
-
if isinstance(balance_res, Ok):
|
|
20
|
-
balance = str(balance_res.ok) if wei else from_wei_str(balance_res.ok, "eth")
|
|
21
|
-
else:
|
|
22
|
-
balance = balance_res.err
|
|
23
|
-
print_plain(f"eth_balance: {balance}", print_format)
|
|
24
|
-
json_result["eth_balance"] = balance
|
|
25
|
-
|
|
26
|
-
if token_address is not None:
|
|
27
|
-
# token decimal
|
|
28
|
-
decimals_res = erc20.get_decimals(rpc_url, token_address)
|
|
29
|
-
if isinstance(decimals_res, Err):
|
|
30
|
-
fatal(f"error: can't get token decimals: {decimals_res.err}")
|
|
31
|
-
decimals = decimals_res.ok
|
|
32
|
-
print_plain(f"token_decimal: {decimals}", print_format)
|
|
33
|
-
json_result["token_decimal"] = decimals
|
|
34
|
-
|
|
35
|
-
# token symbol
|
|
36
|
-
symbol_res = erc20.get_symbol(rpc_url, token_address)
|
|
37
|
-
if isinstance(symbol_res, Err):
|
|
38
|
-
fatal(f"error: can't get token symbol: {symbol_res.err}")
|
|
39
|
-
symbol = symbol_res.ok
|
|
40
|
-
print_plain(f"token_symbol: {symbol}", print_format)
|
|
41
|
-
json_result["token_symbol"] = symbol
|
|
42
|
-
|
|
43
|
-
# token balance
|
|
44
|
-
balance_res = erc20.get_balance(rpc_url, token_address, wallet_address)
|
|
45
|
-
if isinstance(balance_res, Err):
|
|
46
|
-
fatal(f"error: can't get token balance: {balance_res.err}")
|
|
47
|
-
balance = str(balance_res.ok) if wei else from_wei_str(balance_res.ok, "t", decimals=decimals)
|
|
48
|
-
print_plain(f"token_balance: {balance}", print_format)
|
|
49
|
-
json_result["token_balance"] = balance
|
|
50
|
-
|
|
51
|
-
print_json(json_result, print_format=print_format)
|
|
@@ -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=print_format)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|