py-geth 4.2.0__tar.gz → 5.2.0__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.
Files changed (78) hide show
  1. {py-geth-4.2.0 → py_geth-5.2.0}/LICENSE +1 -1
  2. {py-geth-4.2.0 → py_geth-5.2.0}/MANIFEST.in +2 -0
  3. {py-geth-4.2.0/py_geth.egg-info → py_geth-5.2.0}/PKG-INFO +41 -50
  4. {py-geth-4.2.0 → py_geth-5.2.0}/README.md +16 -44
  5. {py-geth-4.2.0 → py_geth-5.2.0}/geth/__init__.py +12 -2
  6. py_geth-5.2.0/geth/accounts.py +201 -0
  7. py_geth-5.2.0/geth/chain.py +154 -0
  8. py_geth-5.2.0/geth/exceptions.py +116 -0
  9. py_geth-5.2.0/geth/genesis.json +29 -0
  10. {py-geth-4.2.0 → py_geth-5.2.0}/geth/install.py +126 -132
  11. {py-geth-4.2.0 → py_geth-5.2.0}/geth/main.py +27 -5
  12. {py-geth-4.2.0 → py_geth-5.2.0}/geth/mixins.py +54 -29
  13. py_geth-5.2.0/geth/process.py +335 -0
  14. {py-geth-4.2.0 → py_geth-5.2.0}/geth/reset.py +40 -16
  15. py_geth-5.2.0/geth/types.py +65 -0
  16. py_geth-5.2.0/geth/utils/encoding.py +58 -0
  17. {py-geth-4.2.0 → py_geth-5.2.0}/geth/utils/filesystem.py +8 -15
  18. {py-geth-4.2.0 → py_geth-5.2.0}/geth/utils/networking.py +18 -6
  19. {py-geth-4.2.0 → py_geth-5.2.0}/geth/utils/proc.py +13 -3
  20. {py-geth-4.2.0 → py_geth-5.2.0}/geth/utils/thread.py +5 -1
  21. {py-geth-4.2.0 → py_geth-5.2.0}/geth/utils/timeout.py +39 -13
  22. py_geth-5.2.0/geth/utils/validation.py +179 -0
  23. py_geth-5.2.0/geth/wrapper.py +290 -0
  24. {py-geth-4.2.0 → py_geth-5.2.0/py_geth.egg-info}/PKG-INFO +41 -50
  25. {py-geth-4.2.0 → py_geth-5.2.0}/py_geth.egg-info/SOURCES.txt +9 -11
  26. py_geth-5.2.0/py_geth.egg-info/requires.txt +30 -0
  27. {py-geth-4.2.0 → py_geth-5.2.0}/pyproject.toml +70 -24
  28. py_geth-5.2.0/scripts/release/test_package.py +50 -0
  29. {py-geth-4.2.0 → py_geth-5.2.0}/setup.py +14 -7
  30. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/accounts/conftest.py +1 -2
  31. py_geth-5.2.0/tests/core/accounts/test_account_list_parsing.py +20 -0
  32. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/accounts/test_create_geth_account.py +8 -8
  33. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/accounts/test_geth_accounts.py +4 -4
  34. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/running/test_running_mainnet_chain.py +15 -0
  35. py-geth-4.2.0/tests/core/running/test_running_ropsten_chain.py → py_geth-5.2.0/tests/core/running/test_running_sepolia_chain.py +3 -3
  36. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/running/test_running_with_logging.py +1 -2
  37. py_geth-5.2.0/tests/core/test_import_and_version.py +4 -0
  38. py_geth-5.2.0/tests/core/test_library_files.py +39 -0
  39. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/utility/test_is_live_chain.py +1 -2
  40. py_geth-5.2.0/tests/core/utility/test_is_sepolia_chain.py +28 -0
  41. py_geth-5.2.0/tests/core/utility/test_validation.py +269 -0
  42. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/waiting/test_waiting_for_ipc_socket.py +3 -2
  43. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/waiting/test_waiting_for_rpc_connection.py +3 -2
  44. py-geth-4.2.0/geth/accounts.py +0 -150
  45. py-geth-4.2.0/geth/chain.py +0 -169
  46. py-geth-4.2.0/geth/exceptions.py +0 -43
  47. py-geth-4.2.0/geth/genesis.json +0 -12
  48. py-geth-4.2.0/geth/process.py +0 -311
  49. py-geth-4.2.0/geth/utils/dag.py +0 -45
  50. py-geth-4.2.0/geth/utils/encoding.py +0 -46
  51. py-geth-4.2.0/geth/wrapper.py +0 -339
  52. py-geth-4.2.0/py_geth.egg-info/requires.txt +0 -23
  53. py-geth-4.2.0/tests/core/accounts/projects/test-01/geth/nodekey +0 -1
  54. py-geth-4.2.0/tests/core/accounts/projects/test-02/geth/LOCK +0 -0
  55. py-geth-4.2.0/tests/core/accounts/projects/test-02/geth/nodekey +0 -1
  56. py-geth-4.2.0/tests/core/accounts/projects/test-03/geth/LOCK +0 -0
  57. py-geth-4.2.0/tests/core/accounts/projects/test-03/geth/nodekey +0 -1
  58. py-geth-4.2.0/tests/core/accounts/test_account_list_parsing.py +0 -14
  59. py-geth-4.2.0/tests/core/test_import.py +0 -2
  60. py-geth-4.2.0/tests/core/utility/test_is_ropsten_chain.py +0 -29
  61. py-geth-4.2.0/tests/core/waiting/test_waiting_for_dag_generation.py +0 -41
  62. {py-geth-4.2.0 → py_geth-5.2.0}/geth/default_blockchain_password +0 -0
  63. py-geth-4.2.0/geth/utils/__init__.py → py_geth-5.2.0/geth/py.typed +0 -0
  64. py-geth-4.2.0/tests/core/accounts/projects/test-01/geth/LOCK → py_geth-5.2.0/geth/utils/__init__.py +0 -0
  65. {py-geth-4.2.0 → py_geth-5.2.0}/py_geth.egg-info/dependency_links.txt +0 -0
  66. {py-geth-4.2.0 → py_geth-5.2.0}/py_geth.egg-info/not-zip-safe +0 -0
  67. {py-geth-4.2.0 → py_geth-5.2.0}/py_geth.egg-info/top_level.txt +0 -0
  68. {py-geth-4.2.0 → py_geth-5.2.0}/setup.cfg +0 -0
  69. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/accounts/projects/test-01/keystore/UTC--2015-08-24T21-30-14.222885490Z--ae71658b3ab452f7e4f03bda6f777b860b2e2ff2 +0 -0
  70. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/accounts/projects/test-02/keystore/UTC--2015-08-24T21-30-14.222885490Z--ae71658b3ab452f7e4f03bda6f777b860b2e2ff2 +0 -0
  71. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/accounts/projects/test-02/keystore/UTC--2015-08-24T21-32-00.716418819Z--e8e085862a8d951dd78ec5ea784b3e22ee1ca9c6 +0 -0
  72. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/accounts/projects/test-02/keystore/UTC--2015-08-24T21-32-04.748321142Z--0da70f43a568e88168436be52ed129f4a9bbdaf5 +0 -0
  73. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/running/test_running_dev_chain.py +0 -0
  74. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/running/test_use_as_a_context_manager.py +0 -0
  75. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/utility/test_constructing_test_chain_kwargs.py +0 -0
  76. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/utility/test_geth_version.py +0 -0
  77. {py-geth-4.2.0 → py_geth-5.2.0}/tests/core/waiting/conftest.py +0 -0
  78. {py-geth-4.2.0 → py_geth-5.2.0}/tests/installation/test_geth_installation.py +1 -1
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2016-2023 The Ethereum Foundation
3
+ Copyright (c) 2016-2025 The Ethereum Foundation
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,7 @@
1
1
  include LICENSE
2
2
  include README.md
3
3
 
4
+ recursive-include scripts *
4
5
  recursive-include tests *
5
6
 
6
7
  global-include *.pyi
@@ -12,3 +13,4 @@ prune venv*
12
13
 
13
14
  include geth/default_blockchain_password
14
15
  include geth/genesis.json
16
+ include geth/py.typed
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: py-geth
3
- Version: 4.2.0
3
+ Version: 5.2.0
4
4
  Summary: py-geth: Run Go-Ethereum as a subprocess
5
5
  Home-page: https://github.com/ethereum/py-geth
6
6
  Author: The Ethereum Foundation
@@ -16,29 +16,48 @@ Classifier: Programming Language :: Python :: 3.8
16
16
  Classifier: Programming Language :: Python :: 3.9
17
17
  Classifier: Programming Language :: Python :: 3.10
18
18
  Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
19
21
  Requires-Python: >=3.8, <4
20
22
  Description-Content-Type: text/markdown
21
23
  License-File: LICENSE
24
+ Requires-Dist: eval_type_backport>=0.1.0; python_version < "3.10"
25
+ Requires-Dist: pydantic>=2.6.0
26
+ Requires-Dist: requests>=2.23
22
27
  Requires-Dist: semantic-version>=2.6.0
28
+ Requires-Dist: types-requests>=2.0.0
29
+ Requires-Dist: typing-extensions>=4.0.1
23
30
  Provides-Extra: dev
24
31
  Requires-Dist: build>=0.9.0; extra == "dev"
25
- Requires-Dist: bumpversion>=0.5.3; extra == "dev"
32
+ Requires-Dist: bump_my_version>=0.19.0; extra == "dev"
26
33
  Requires-Dist: ipython; extra == "dev"
34
+ Requires-Dist: mypy==1.10.0; extra == "dev"
27
35
  Requires-Dist: pre-commit>=3.4.0; extra == "dev"
28
- Requires-Dist: requests>=2.20; extra == "dev"
29
36
  Requires-Dist: tox>=4.0.0; extra == "dev"
30
37
  Requires-Dist: twine; extra == "dev"
31
38
  Requires-Dist: wheel; extra == "dev"
32
- Requires-Dist: towncrier<22,>=21; extra == "dev"
39
+ Requires-Dist: towncrier<25,>=24; extra == "dev"
33
40
  Requires-Dist: flaky>=3.2.0; extra == "dev"
34
41
  Requires-Dist: pytest>=7.0.0; extra == "dev"
35
42
  Requires-Dist: pytest-xdist>=2.4.0; extra == "dev"
36
43
  Provides-Extra: docs
37
- Requires-Dist: towncrier<22,>=21; extra == "docs"
44
+ Requires-Dist: towncrier<25,>=24; extra == "docs"
38
45
  Provides-Extra: test
39
46
  Requires-Dist: flaky>=3.2.0; extra == "test"
40
47
  Requires-Dist: pytest>=7.0.0; extra == "test"
41
48
  Requires-Dist: pytest-xdist>=2.4.0; extra == "test"
49
+ Dynamic: author
50
+ Dynamic: author-email
51
+ Dynamic: classifier
52
+ Dynamic: description
53
+ Dynamic: description-content-type
54
+ Dynamic: home-page
55
+ Dynamic: keywords
56
+ Dynamic: license
57
+ Dynamic: provides-extra
58
+ Dynamic: requires-dist
59
+ Dynamic: requires-python
60
+ Dynamic: summary
42
61
 
43
62
  # py-geth
44
63
 
@@ -57,8 +76,6 @@ This library requires the `geth` executable to be present.
57
76
 
58
77
  ## Installation
59
78
 
60
- Installation
61
-
62
79
  ```bash
63
80
  python -m pip install py-geth
64
81
  ```
@@ -68,12 +85,12 @@ python -m pip install py-geth
68
85
  To run geth connected to the mainnet
69
86
 
70
87
  ```python
71
- >>> from geth import LiveGethProcess
72
- >>> geth = LiveGethProcess()
88
+ >>> from geth import MainnetGethProcess
89
+ >>> geth = MainnetGethProcess()
73
90
  >>> geth.start()
74
91
  ```
75
92
 
76
- Or a private local chain for testing. These require you to give them a name.
93
+ Or in dev mode for testing. These require you to give them a name.
77
94
 
78
95
  ```python
79
96
  >>> from geth import DevGethProcess
@@ -138,83 +155,57 @@ and stderr output to a logfile.
138
155
  All logs will be written to logfiles in `./logs/` in the current directory.
139
156
 
140
157
  The underlying `geth` process can take additional time to open the RPC or IPC
141
- connections, as well as to start mining if it needs to generate the DAG. You
142
- can use the following interfaces to query whether these are ready.
158
+ connections. You can use the following interfaces to query whether these are ready.
143
159
 
144
160
  ```python
145
- >>> geth.is_rpc_ready
146
- True
147
161
  >>> geth.wait_for_rpc(timeout=30) # wait up to 30 seconds for the RPC connection to open
148
- >>> geth.is_ipc_ready
162
+ >>> geth.is_rpc_ready
149
163
  True
150
164
  >>> geth.wait_for_ipc(timeout=30) # wait up to 30 seconds for the IPC socket to open
151
- >>> geth.is_dag_generated
152
- True
153
- >>> geth.is_mining
165
+ >>> geth.is_ipc_ready
154
166
  True
155
- >>> geth.wait_for_dag(timeout=600) # wait up to 10 minutes for the DAG to generate.
156
167
  ```
157
168
 
158
- > The DAG functionality currently only applies to the DAG for epoch 0.
159
-
160
169
  ## Installing specific versions of `geth`
161
170
 
162
171
  > This feature is experimental and subject to breaking changes.
163
172
 
164
- Versions of `geth` dating back to v1.11.0 can be installed using `py-geth`.
173
+ Versions of `geth` dating back to v1.14.0 can be installed using `py-geth`.
165
174
  See [install.py](https://github.com/ethereum/py-geth/blob/main/geth/install.py) for
166
175
  the current list of supported versions.
167
176
 
168
177
  Installation can be done via the command line:
169
178
 
170
179
  ```bash
171
- $ python -m geth.install v1.13.10
180
+ $ python -m geth.install v1.14.12
172
181
  ```
173
182
 
174
183
  Or from python using the `install_geth` function.
175
184
 
176
185
  ```python
177
186
  >>> from geth import install_geth
178
- >>> install_geth('v1.13.10')
187
+ >>> install_geth('v1.14.12')
179
188
  ```
180
189
 
181
190
  The installed binary can be found in the `$HOME/.py-geth` directory, under your
182
- home directory. The `v1.13.10` binary would be located at
183
- `$HOME/.py-geth/geth-v1.13.10/bin/geth`.
191
+ home directory. The `v1.14.12` binary would be located at
192
+ `$HOME/.py-geth/geth-v1.14.12/bin/geth`.
184
193
 
185
194
  ## About `DevGethProcess`
186
195
 
187
- The `DevGethProcess` is designed to facilitate testing. In that regard, it is
188
- preconfigured as follows.
196
+ The `DevGethProcess` will run geth in `--dev` mode and is designed to facilitate testing.
197
+ In that regard, it is preconfigured as follows.
189
198
 
190
- - A single account is created and allocated 1 billion ether.
199
+ - A single account is created, allocated 1 billion ether, and assigned as the coinbase.
191
200
  - All APIs are enabled on both `rpc` and `ipc` interfaces.
192
- - Account 0 is unlocked
193
201
  - Networking is configured to not look for or connect to any peers.
194
202
  - The `networkid` of `1234` is used.
195
203
  - Verbosity is set to `5` (DEBUG)
196
- - Mining is enabled with a single thread.
197
204
  - The RPC interface *tries* to bind to 8545 but will find an open port if this
198
205
  port is not available.
199
206
  - The DevP2P interface *tries* to bind to 30303 but will find an open port if this
200
207
  port is not available.
201
208
 
202
- ## Gotchas
203
-
204
- If you are running with `mining` enabled, which is default for `DevGethProcess`,
205
- then you will likely need to generate the `DAG` manually. If you do not, then
206
- it will auto-generate the first time you run the process and this takes a
207
- while.
208
-
209
- To generate it manually:
210
-
211
- ```sh
212
- $ geth makedag 0 ~/.ethash
213
- ```
214
-
215
- This is especially important in CI environments like Travis-CI where your
216
- process will likely timeout during generation.
217
-
218
209
  ## Development
219
210
 
220
211
  Clone the repository:
@@ -297,14 +288,14 @@ the version for the one you wish to add support for. Note that the `v` in the ve
297
288
  optional.
298
289
 
299
290
  ```shell
300
- $ python update_geth.py v1_10_9
291
+ $ python update_geth.py v1_14_0
301
292
  ```
302
293
 
303
294
  To introduce support for more than one version, pass in the versions in increasing order,
304
295
  ending with the latest version.
305
296
 
306
297
  ```shell
307
- $ python update_geth.py v1_10_7 v1_10_8 v1_10_9
298
+ $ python update_geth.py v1_14_0 v1_14_2 v1_14_3
308
299
  ```
309
300
 
310
301
  Always review your changes before committing as something may cause this existing pattern to change at some point.
@@ -15,8 +15,6 @@ This library requires the `geth` executable to be present.
15
15
 
16
16
  ## Installation
17
17
 
18
- Installation
19
-
20
18
  ```bash
21
19
  python -m pip install py-geth
22
20
  ```
@@ -26,12 +24,12 @@ python -m pip install py-geth
26
24
  To run geth connected to the mainnet
27
25
 
28
26
  ```python
29
- >>> from geth import LiveGethProcess
30
- >>> geth = LiveGethProcess()
27
+ >>> from geth import MainnetGethProcess
28
+ >>> geth = MainnetGethProcess()
31
29
  >>> geth.start()
32
30
  ```
33
31
 
34
- Or a private local chain for testing. These require you to give them a name.
32
+ Or in dev mode for testing. These require you to give them a name.
35
33
 
36
34
  ```python
37
35
  >>> from geth import DevGethProcess
@@ -96,83 +94,57 @@ and stderr output to a logfile.
96
94
  All logs will be written to logfiles in `./logs/` in the current directory.
97
95
 
98
96
  The underlying `geth` process can take additional time to open the RPC or IPC
99
- connections, as well as to start mining if it needs to generate the DAG. You
100
- can use the following interfaces to query whether these are ready.
97
+ connections. You can use the following interfaces to query whether these are ready.
101
98
 
102
99
  ```python
103
- >>> geth.is_rpc_ready
104
- True
105
100
  >>> geth.wait_for_rpc(timeout=30) # wait up to 30 seconds for the RPC connection to open
106
- >>> geth.is_ipc_ready
101
+ >>> geth.is_rpc_ready
107
102
  True
108
103
  >>> geth.wait_for_ipc(timeout=30) # wait up to 30 seconds for the IPC socket to open
109
- >>> geth.is_dag_generated
110
- True
111
- >>> geth.is_mining
104
+ >>> geth.is_ipc_ready
112
105
  True
113
- >>> geth.wait_for_dag(timeout=600) # wait up to 10 minutes for the DAG to generate.
114
106
  ```
115
107
 
116
- > The DAG functionality currently only applies to the DAG for epoch 0.
117
-
118
108
  ## Installing specific versions of `geth`
119
109
 
120
110
  > This feature is experimental and subject to breaking changes.
121
111
 
122
- Versions of `geth` dating back to v1.11.0 can be installed using `py-geth`.
112
+ Versions of `geth` dating back to v1.14.0 can be installed using `py-geth`.
123
113
  See [install.py](https://github.com/ethereum/py-geth/blob/main/geth/install.py) for
124
114
  the current list of supported versions.
125
115
 
126
116
  Installation can be done via the command line:
127
117
 
128
118
  ```bash
129
- $ python -m geth.install v1.13.10
119
+ $ python -m geth.install v1.14.12
130
120
  ```
131
121
 
132
122
  Or from python using the `install_geth` function.
133
123
 
134
124
  ```python
135
125
  >>> from geth import install_geth
136
- >>> install_geth('v1.13.10')
126
+ >>> install_geth('v1.14.12')
137
127
  ```
138
128
 
139
129
  The installed binary can be found in the `$HOME/.py-geth` directory, under your
140
- home directory. The `v1.13.10` binary would be located at
141
- `$HOME/.py-geth/geth-v1.13.10/bin/geth`.
130
+ home directory. The `v1.14.12` binary would be located at
131
+ `$HOME/.py-geth/geth-v1.14.12/bin/geth`.
142
132
 
143
133
  ## About `DevGethProcess`
144
134
 
145
- The `DevGethProcess` is designed to facilitate testing. In that regard, it is
146
- preconfigured as follows.
135
+ The `DevGethProcess` will run geth in `--dev` mode and is designed to facilitate testing.
136
+ In that regard, it is preconfigured as follows.
147
137
 
148
- - A single account is created and allocated 1 billion ether.
138
+ - A single account is created, allocated 1 billion ether, and assigned as the coinbase.
149
139
  - All APIs are enabled on both `rpc` and `ipc` interfaces.
150
- - Account 0 is unlocked
151
140
  - Networking is configured to not look for or connect to any peers.
152
141
  - The `networkid` of `1234` is used.
153
142
  - Verbosity is set to `5` (DEBUG)
154
- - Mining is enabled with a single thread.
155
143
  - The RPC interface *tries* to bind to 8545 but will find an open port if this
156
144
  port is not available.
157
145
  - The DevP2P interface *tries* to bind to 30303 but will find an open port if this
158
146
  port is not available.
159
147
 
160
- ## Gotchas
161
-
162
- If you are running with `mining` enabled, which is default for `DevGethProcess`,
163
- then you will likely need to generate the `DAG` manually. If you do not, then
164
- it will auto-generate the first time you run the process and this takes a
165
- while.
166
-
167
- To generate it manually:
168
-
169
- ```sh
170
- $ geth makedag 0 ~/.ethash
171
- ```
172
-
173
- This is especially important in CI environments like Travis-CI where your
174
- process will likely timeout during generation.
175
-
176
148
  ## Development
177
149
 
178
150
  Clone the repository:
@@ -255,14 +227,14 @@ the version for the one you wish to add support for. Note that the `v` in the ve
255
227
  optional.
256
228
 
257
229
  ```shell
258
- $ python update_geth.py v1_10_9
230
+ $ python update_geth.py v1_14_0
259
231
  ```
260
232
 
261
233
  To introduce support for more than one version, pass in the versions in increasing order,
262
234
  ending with the latest version.
263
235
 
264
236
  ```shell
265
- $ python update_geth.py v1_10_7 v1_10_8 v1_10_9
237
+ $ python update_geth.py v1_14_0 v1_14_2 v1_14_3
266
238
  ```
267
239
 
268
240
  Always review your changes before committing as something may cause this existing pattern to change at some point.
@@ -14,10 +14,20 @@ from .mixins import (
14
14
  )
15
15
  from .process import (
16
16
  DevGethProcess,
17
- LiveGethProcess,
18
17
  MainnetGethProcess,
19
- RopstenGethProcess,
18
+ SepoliaGethProcess,
20
19
  TestnetGethProcess,
21
20
  )
22
21
 
23
22
  __version__ = __version("py-geth")
23
+
24
+ __all__ = (
25
+ "install_geth",
26
+ "get_geth_version",
27
+ "InterceptedStreamsMixin",
28
+ "LoggingMixin",
29
+ "MainnetGethProcess",
30
+ "SepoliaGethProcess",
31
+ "TestnetGethProcess",
32
+ "DevGethProcess",
33
+ )
@@ -0,0 +1,201 @@
1
+ from __future__ import (
2
+ annotations,
3
+ )
4
+
5
+ import os
6
+ import re
7
+
8
+ from typing_extensions import (
9
+ Unpack,
10
+ )
11
+
12
+ from geth.exceptions import (
13
+ PyGethValueError,
14
+ )
15
+ from geth.types import (
16
+ GethKwargsTypedDict,
17
+ )
18
+ from geth.utils.validation import (
19
+ validate_geth_kwargs,
20
+ )
21
+
22
+ from .utils.proc import (
23
+ format_error_message,
24
+ )
25
+ from .wrapper import (
26
+ spawn_geth,
27
+ )
28
+
29
+
30
+ def get_accounts(
31
+ **geth_kwargs: Unpack[GethKwargsTypedDict],
32
+ ) -> tuple[str, ...] | tuple[()]:
33
+ """
34
+ Returns all geth accounts as tuple of hex encoded strings
35
+
36
+ >>> get_accounts(data_dir='some/data/dir')
37
+ ... ('0x...', '0x...')
38
+ """
39
+ validate_geth_kwargs(geth_kwargs)
40
+
41
+ if not geth_kwargs.get("data_dir"):
42
+ raise PyGethValueError("data_dir is required to get accounts")
43
+
44
+ geth_kwargs["suffix_args"] = ["account", "list"]
45
+
46
+ command, proc = spawn_geth(geth_kwargs)
47
+ stdoutdata, stderrdata = proc.communicate()
48
+
49
+ if proc.returncode:
50
+ if "no keys in store" in stderrdata.decode():
51
+ return tuple()
52
+ else:
53
+ raise PyGethValueError(
54
+ format_error_message(
55
+ "Error trying to list accounts",
56
+ command,
57
+ proc.returncode,
58
+ stdoutdata.decode(),
59
+ stderrdata.decode(),
60
+ )
61
+ )
62
+ accounts = parse_geth_accounts(stdoutdata)
63
+ return accounts
64
+
65
+
66
+ account_regex = re.compile(b"([a-f0-9]{40})")
67
+
68
+
69
+ def create_new_account(**geth_kwargs: Unpack[GethKwargsTypedDict]) -> str:
70
+ r"""
71
+ Creates a new Ethereum account on geth.
72
+
73
+ This is useful for testing when you want to stress
74
+ interaction (transfers) between Ethereum accounts.
75
+
76
+ This command communicates with ``geth`` command over
77
+ terminal interaction. It creates keystore folder and new
78
+ account there.
79
+
80
+ This function only works against offline geth processes,
81
+ because geth builds an account cache when starting up.
82
+ If geth process is already running you can create new
83
+ accounts using
84
+ `web3.personal.newAccount()
85
+ <https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-personal>_`
86
+
87
+ RPC API.
88
+
89
+ Example pytest fixture for tests:
90
+
91
+ .. code-block:: python
92
+
93
+ import os
94
+
95
+ from geth.wrapper import DEFAULT_PASSWORD_PATH
96
+ from geth.accounts import create_new_account
97
+
98
+
99
+ @pytest.fixture
100
+ def target_account() -> str:
101
+ '''Create a new Ethereum account on a running Geth node.
102
+
103
+ The account can be used as a withdrawal target for tests.
104
+
105
+ :return: 0x address of the account
106
+ '''
107
+
108
+ # We store keystore files in the current working directory
109
+ # of the test run
110
+ data_dir = os.getcwd()
111
+
112
+ # Use the default password "this-is-not-a-secure-password"
113
+ # as supplied in geth/default_blockchain_password file.
114
+ # The supplied password must be bytes, not string,
115
+ # as we only want ASCII characters and do not want to
116
+ # deal encoding problems with passwords
117
+ account = create_new_account(data_dir, DEFAULT_PASSWORD_PATH)
118
+ return account
119
+
120
+ :param \**geth_kwargs:
121
+ Command line arguments to pass to geth. See below:
122
+
123
+ :Required Keyword Arguments:
124
+ * *data_dir* (``str``) --
125
+ Geth datadir path - where to keep "keystore" folder
126
+ * *password* (``str`` or ``bytes``) --
127
+ Password to use for the new account, either the password as bytes or a str
128
+ path to a file containing the password.
129
+
130
+ :return: Account as 0x prefixed hex string
131
+ :rtype: str
132
+ """
133
+ if not geth_kwargs.get("data_dir"):
134
+ raise PyGethValueError("data_dir is required to create a new account")
135
+
136
+ if not geth_kwargs.get("password"):
137
+ raise PyGethValueError("password is required to create a new account")
138
+
139
+ password = geth_kwargs.get("password")
140
+
141
+ geth_kwargs.update({"suffix_args": ["account", "new"]})
142
+ validate_geth_kwargs(geth_kwargs)
143
+
144
+ if isinstance(password, str):
145
+ if not os.path.exists(password):
146
+ raise PyGethValueError(f"Password file not found at path: {password}")
147
+ elif not isinstance(password, bytes):
148
+ raise PyGethValueError(
149
+ "Password must be either a str (path to a file) or bytes"
150
+ )
151
+
152
+ command, proc = spawn_geth(geth_kwargs)
153
+
154
+ if isinstance(password, str):
155
+ stdoutdata, stderrdata = proc.communicate()
156
+ else:
157
+ stdoutdata, stderrdata = proc.communicate(b"\n".join((password, password)))
158
+
159
+ if proc.returncode:
160
+ raise PyGethValueError(
161
+ format_error_message(
162
+ "Error trying to create a new account",
163
+ command,
164
+ proc.returncode,
165
+ stdoutdata.decode(),
166
+ stderrdata.decode(),
167
+ )
168
+ )
169
+
170
+ match = account_regex.search(stdoutdata)
171
+ if not match:
172
+ raise PyGethValueError(
173
+ format_error_message(
174
+ "Did not find an address in process output",
175
+ command,
176
+ proc.returncode,
177
+ stdoutdata.decode(),
178
+ stderrdata.decode(),
179
+ )
180
+ )
181
+
182
+ return "0x" + match.groups()[0].decode()
183
+
184
+
185
+ def ensure_account_exists(**geth_kwargs: Unpack[GethKwargsTypedDict]) -> str:
186
+ if not geth_kwargs.get("data_dir"):
187
+ raise PyGethValueError("data_dir is required to get accounts")
188
+
189
+ validate_geth_kwargs(geth_kwargs)
190
+ accounts = get_accounts(**geth_kwargs)
191
+ if not accounts:
192
+ account = create_new_account(**geth_kwargs)
193
+ else:
194
+ account = accounts[0]
195
+ return account
196
+
197
+
198
+ def parse_geth_accounts(raw_accounts_output: bytes) -> tuple[str, ...]:
199
+ accounts = account_regex.findall(raw_accounts_output)
200
+ accounts_set = set(accounts) # remove duplicates
201
+ return tuple("0x" + account.decode() for account in accounts_set)