mm-eth 0.5.10__py3-none-any.whl → 0.5.12__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_eth/async_rpc.py +7 -6
- mm_eth/ens.py +68 -13
- mm_eth/utils.py +2 -0
- {mm_eth-0.5.10.dist-info → mm_eth-0.5.12.dist-info}/METADATA +4 -3
- {mm_eth-0.5.10.dist-info → mm_eth-0.5.12.dist-info}/RECORD +7 -7
- {mm_eth-0.5.10.dist-info → mm_eth-0.5.12.dist-info}/WHEEL +0 -0
- {mm_eth-0.5.10.dist-info → mm_eth-0.5.12.dist-info}/entry_points.txt +0 -0
mm_eth/async_rpc.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import json
|
|
2
|
+
from collections.abc import Sequence
|
|
2
3
|
from typing import Any
|
|
3
4
|
|
|
4
5
|
import websockets
|
|
5
6
|
from mm_crypto_utils import Nodes, Proxies, random_node, random_proxy
|
|
6
|
-
from mm_std import Err, Ok, Result,
|
|
7
|
+
from mm_std import Err, Ok, Result, hra
|
|
7
8
|
|
|
8
9
|
from mm_eth.utils import hex_str_to_int
|
|
9
10
|
|
|
@@ -12,9 +13,9 @@ async def rpc_call(
|
|
|
12
13
|
*,
|
|
13
14
|
nodes: Nodes,
|
|
14
15
|
method: str,
|
|
15
|
-
params:
|
|
16
|
+
params: Sequence[object],
|
|
16
17
|
id_: int = 1,
|
|
17
|
-
timeout:
|
|
18
|
+
timeout: float = 10,
|
|
18
19
|
proxies: Proxies = None,
|
|
19
20
|
attempts: int = 1,
|
|
20
21
|
) -> Result[Any]:
|
|
@@ -32,8 +33,8 @@ async def rpc_call(
|
|
|
32
33
|
return res
|
|
33
34
|
|
|
34
35
|
|
|
35
|
-
async def _http_call(node: str, data: dict[str, object], timeout:
|
|
36
|
-
res = await
|
|
36
|
+
async def _http_call(node: str, data: dict[str, object], timeout: float, proxy: str | None) -> Result[Any]:
|
|
37
|
+
res = await hra(node, method="POST", proxy=proxy, timeout=timeout, params=data, json_params=True)
|
|
37
38
|
if res.is_error():
|
|
38
39
|
return res.to_err_result()
|
|
39
40
|
try:
|
|
@@ -47,7 +48,7 @@ async def _http_call(node: str, data: dict[str, object], timeout: int, proxy: st
|
|
|
47
48
|
return res.to_err_result(f"exception: {err}")
|
|
48
49
|
|
|
49
50
|
|
|
50
|
-
async def _ws_call(node: str, data: dict[str, object], timeout:
|
|
51
|
+
async def _ws_call(node: str, data: dict[str, object], timeout: float) -> Result[Any]:
|
|
51
52
|
try:
|
|
52
53
|
async with websockets.connect(node, timeout=timeout) as ws:
|
|
53
54
|
await ws.send(json.dumps(data))
|
mm_eth/ens.py
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
from ens.utils import normal_name_to_hash
|
|
1
2
|
from mm_crypto_utils import Nodes, Proxies, random_node, random_proxy
|
|
2
3
|
from mm_std import Err, Ok, Result
|
|
4
|
+
from web3 import Web3
|
|
3
5
|
|
|
4
|
-
from mm_eth.
|
|
6
|
+
from mm_eth.async_rpc import rpc_call
|
|
7
|
+
from mm_eth.utils import get_w3
|
|
8
|
+
|
|
9
|
+
ENS_REGISTRY_ADDRESS: str = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
|
|
10
|
+
FUNC_SELECTOR_RESOLVER: str = "0x0178b8bf" # resolver(bytes32)
|
|
11
|
+
FUNC_SELECTOR_NAME: str = "0x691f3431" # name(bytes32)
|
|
5
12
|
|
|
6
13
|
|
|
7
14
|
def get_name_with_retries(
|
|
@@ -25,27 +32,75 @@ def get_name(rpc_url: str, address: str, timeout: float = 5, proxy: str | None =
|
|
|
25
32
|
error = e.__class__.__qualname__
|
|
26
33
|
return Err("exception: " + error)
|
|
27
34
|
|
|
35
|
+
# async def async_get_name(rpc_url: str, address: str, timeout: float = 5, proxy: str | None = None) -> Result[str | None]:
|
|
36
|
+
# w3 = await get_async_w3(rpc_url, timeout=timeout, proxy=proxy)
|
|
37
|
+
# try:
|
|
38
|
+
# res = await w3.ens.name(w3.to_checksum_address(address)) # type: ignore[union-attr]
|
|
39
|
+
# return Ok(res)
|
|
40
|
+
# except Exception as e:
|
|
41
|
+
# error = str(e)
|
|
42
|
+
# if not error:
|
|
43
|
+
# error = e.__class__.__qualname__
|
|
44
|
+
# return Err("exception: " + error)
|
|
45
|
+
# finally:
|
|
46
|
+
# await w3.provider.disconnect()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
async def get_name_async(rpc_url: str, address: str, timeout: float = 5, proxy: str | None = None) -> Result[str | None]:
|
|
50
|
+
checksum_addr: str = Web3.to_checksum_address(address)
|
|
51
|
+
reverse_name: str = checksum_addr.lower()[2:] + ".addr.reverse"
|
|
52
|
+
name_hash_hex: str = normal_name_to_hash(reverse_name).hex()
|
|
53
|
+
|
|
54
|
+
resolver_data: str = FUNC_SELECTOR_RESOLVER + name_hash_hex
|
|
55
|
+
|
|
56
|
+
resolver_params = [{"to": ENS_REGISTRY_ADDRESS, "data": resolver_data}, "latest"]
|
|
57
|
+
|
|
58
|
+
resolver_res: Result[str] = await rpc_call(
|
|
59
|
+
nodes=rpc_url,
|
|
60
|
+
method="eth_call",
|
|
61
|
+
params=resolver_params,
|
|
62
|
+
timeout=timeout,
|
|
63
|
+
proxies=proxy,
|
|
64
|
+
attempts=1,
|
|
65
|
+
)
|
|
66
|
+
if not isinstance(resolver_res, Ok) or len(resolver_res.ok) != 66:
|
|
67
|
+
return Ok(None)
|
|
68
|
+
|
|
69
|
+
resolver_address: str = Web3.to_checksum_address("0x" + resolver_res.ok[-40:])
|
|
70
|
+
|
|
71
|
+
name_data: str = FUNC_SELECTOR_NAME + name_hash_hex
|
|
72
|
+
name_params = [{"to": resolver_address, "data": name_data}, "latest"]
|
|
73
|
+
|
|
74
|
+
name_res: Result[str] = await rpc_call(
|
|
75
|
+
nodes=rpc_url,
|
|
76
|
+
method="eth_call",
|
|
77
|
+
params=name_params,
|
|
78
|
+
timeout=timeout,
|
|
79
|
+
proxies=proxy,
|
|
80
|
+
attempts=1,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if isinstance(name_res, Err):
|
|
84
|
+
return name_res
|
|
85
|
+
if name_res.ok == "0x":
|
|
86
|
+
return Ok(None)
|
|
28
87
|
|
|
29
|
-
async def async_get_name(rpc_url: str, address: str, timeout: float = 5, proxy: str | None = None) -> Result[str | None]:
|
|
30
|
-
w3 = await get_async_w3(rpc_url, timeout=timeout, proxy=proxy)
|
|
31
88
|
try:
|
|
32
|
-
|
|
33
|
-
|
|
89
|
+
hex_data: str = name_res.ok
|
|
90
|
+
length_hex: str = hex_data[66:130]
|
|
91
|
+
str_len: int = int(length_hex, 16) * 2
|
|
92
|
+
name_hex: str = hex_data[130 : 130 + str_len]
|
|
93
|
+
return Ok(bytes.fromhex(name_hex).decode("utf-8"))
|
|
34
94
|
except Exception as e:
|
|
35
|
-
|
|
36
|
-
if not error:
|
|
37
|
-
error = e.__class__.__qualname__
|
|
38
|
-
return Err("exception: " + error)
|
|
39
|
-
finally:
|
|
40
|
-
await w3.provider.disconnect()
|
|
95
|
+
return Err(e)
|
|
41
96
|
|
|
42
97
|
|
|
43
|
-
async def
|
|
98
|
+
async def get_name_with_retries_async(
|
|
44
99
|
rpc_urls: Nodes, address: str, retries: int, timeout: float = 5, proxies: Proxies = None
|
|
45
100
|
) -> Result[str | None]:
|
|
46
101
|
res: Result[str | None] = Err("not started yet")
|
|
47
102
|
for _ in range(retries):
|
|
48
|
-
res = await
|
|
103
|
+
res = await get_name_async(random_node(rpc_urls), address, timeout=timeout, proxy=random_proxy(proxies))
|
|
49
104
|
if res.is_ok():
|
|
50
105
|
return res
|
|
51
106
|
return res
|
mm_eth/utils.py
CHANGED
|
@@ -196,6 +196,8 @@ def get_w3(rpc_url: str, timeout: float | None = None, proxy: str | None = None)
|
|
|
196
196
|
|
|
197
197
|
|
|
198
198
|
async def get_async_w3(rpc_url: str, timeout: float | None = None, proxy: str | None = None) -> AsyncWeb3:
|
|
199
|
+
# TODO: Don't use async w3. AsyncHTTPProvider uses threads
|
|
200
|
+
# check its constructor: self._request_session_manager = HTTPSessionManager()
|
|
199
201
|
request_kwargs: dict[str, object] = {"timeout": timeout}
|
|
200
202
|
if proxy and proxy.startswith("http"):
|
|
201
203
|
request_kwargs["proxy"] = proxy
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mm-eth
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.12
|
|
4
4
|
Requires-Python: >=3.12
|
|
5
5
|
Requires-Dist: aiohttp-socks~=0.10.1
|
|
6
|
-
Requires-Dist: mm-crypto-utils>=0.2.
|
|
6
|
+
Requires-Dist: mm-crypto-utils>=0.2.10
|
|
7
|
+
Requires-Dist: mm-std~=0.3.22
|
|
7
8
|
Requires-Dist: typer>=0.15.2
|
|
8
|
-
Requires-Dist: web3~=7.
|
|
9
|
+
Requires-Dist: web3~=7.10.0
|
|
9
10
|
Requires-Dist: websocket-client~=1.8.0
|
|
@@ -2,10 +2,10 @@ mm_eth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
2
2
|
mm_eth/abi.py,sha256=Qf-QOsR9QexyQM9XWKNeTMkRarIL3XQJbaDbJ8ifMrw,4856
|
|
3
3
|
mm_eth/account.py,sha256=k0MNMatBe0zo1iKZiB_Tq6zyEIo22IncD6ewNUJp3dY,2075
|
|
4
4
|
mm_eth/anvil.py,sha256=98RCfI7dEpxFBTV6UErYvubWVP3n0ctUFn1--4kZ84U,1603
|
|
5
|
-
mm_eth/async_rpc.py,sha256=
|
|
5
|
+
mm_eth/async_rpc.py,sha256=zjPcOoC-NTjMxbWu6cRQn-knHEQ75ZO5L-KZoaiwUJ0,2981
|
|
6
6
|
mm_eth/constants.py,sha256=Cy_G-IleBH4gAZ4ok8AGHHlqmdW0ZM7ZldyVpzAfWLs,54
|
|
7
7
|
mm_eth/deploy.py,sha256=SB3ruY808_5UnG8kHR34uVP66P3zOWZu0ImKD7UUv2s,691
|
|
8
|
-
mm_eth/ens.py,sha256=
|
|
8
|
+
mm_eth/ens.py,sha256=lH3TZABYFBiEEtWlyxCqrcYC-nZQsI_1wSCMzBzHPrM,3860
|
|
9
9
|
mm_eth/erc20.py,sha256=LZmTkjmXpN7sUhOtSLiTqb8Ubet9C9q32EQwTS78OqE,7378
|
|
10
10
|
mm_eth/ethernodes.py,sha256=V4VVbC6Nr9jhwT7blxtLugXC5KfXqE8n-kP0VvGHbqo,3070
|
|
11
11
|
mm_eth/json_encoder.py,sha256=S4oD-qfTVztMb4sRpY1puhBQwOBofTyQXWszmdXk4og,433
|
|
@@ -13,7 +13,7 @@ mm_eth/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
13
13
|
mm_eth/rpc.py,sha256=k0eHxo_Dp6G0fHQ_rD-QbwOJz5ngC6kxBjl5NEHnyw8,13832
|
|
14
14
|
mm_eth/solc.py,sha256=dYRvT8PjZlLDZhNsc_-0790Eug_ZwU2G-iBfIdGj6wQ,1071
|
|
15
15
|
mm_eth/tx.py,sha256=efSoMCoWkenbGdHo1_LX66_Edz1HvED5-J_i3wrHwMw,4051
|
|
16
|
-
mm_eth/utils.py,sha256=
|
|
16
|
+
mm_eth/utils.py,sha256=FytG3U6h80mnUaKP8W2mPZ77EuOp4U7pVbPuoKI3wW4,8215
|
|
17
17
|
mm_eth/vault.py,sha256=h8NyiOQh5YFskh1lZA3KyvnJUnxl9769ME2ChplG0CM,1477
|
|
18
18
|
mm_eth/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
19
|
mm_eth/cli/calcs.py,sha256=cLFTYNAN-I53tUiSg-zFfVr2afjIZPftDDjHj16FBz0,1068
|
|
@@ -42,7 +42,7 @@ mm_eth/cli/cmd/wallet/private_key_cmd.py,sha256=Fv_2OLog1h32pIP7PJITwl_pHdy3BXva
|
|
|
42
42
|
mm_eth/cli/examples/balances.toml,sha256=i_ALpiEcf8-0TFiUg1cgJhxxfHYeBl9x0b3tnUWjswU,421
|
|
43
43
|
mm_eth/cli/examples/call_contract.toml,sha256=ZQWK-409V_vLIZ2bsRD5RCWPPzShPz2KJTTRQY4YaGw,248
|
|
44
44
|
mm_eth/cli/examples/transfer.toml,sha256=8mWuphDquoSDJw-hb9VJqtonjmv3kJ5Ip8jJ4t5YnfM,1810
|
|
45
|
-
mm_eth-0.5.
|
|
46
|
-
mm_eth-0.5.
|
|
47
|
-
mm_eth-0.5.
|
|
48
|
-
mm_eth-0.5.
|
|
45
|
+
mm_eth-0.5.12.dist-info/METADATA,sha256=Hj0xMr3BCxx3MxKT-e5C6cQMO9tHQ0XJhjFbA4teqDA,277
|
|
46
|
+
mm_eth-0.5.12.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
47
|
+
mm_eth-0.5.12.dist-info/entry_points.txt,sha256=aGhpsozl8NIrkuUcX5fSgURCcDhr3ShUdeTSIrJq4oc,46
|
|
48
|
+
mm_eth-0.5.12.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|