web3 7.0.0b1__py3-none-any.whl → 7.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. ens/__init__.py +13 -2
  2. ens/_normalization.py +4 -4
  3. ens/async_ens.py +31 -21
  4. ens/base_ens.py +3 -1
  5. ens/contract_data.py +2 -2
  6. ens/ens.py +14 -11
  7. ens/exceptions.py +16 -29
  8. ens/specs/nf.json +1 -1
  9. ens/specs/normalization_spec.json +1 -1
  10. ens/utils.py +33 -41
  11. web3/__init__.py +23 -12
  12. web3/_utils/abi.py +162 -274
  13. web3/_utils/async_transactions.py +34 -20
  14. web3/_utils/batching.py +217 -0
  15. web3/_utils/blocks.py +6 -2
  16. web3/_utils/caching/__init__.py +12 -0
  17. web3/_utils/caching/caching_utils.py +433 -0
  18. web3/_utils/caching/request_caching_validation.py +287 -0
  19. web3/_utils/compat/__init__.py +2 -3
  20. web3/_utils/contract_sources/compile_contracts.py +1 -1
  21. web3/_utils/contract_sources/contract_data/ambiguous_function_contract.py +42 -0
  22. web3/_utils/contract_sources/contract_data/arrays_contract.py +3 -3
  23. web3/_utils/contract_sources/contract_data/bytes_contracts.py +5 -5
  24. web3/_utils/contract_sources/contract_data/constructor_contracts.py +7 -7
  25. web3/_utils/contract_sources/contract_data/contract_caller_tester.py +3 -3
  26. web3/_utils/contract_sources/contract_data/emitter_contract.py +3 -3
  27. web3/_utils/contract_sources/contract_data/event_contracts.py +50 -5
  28. web3/_utils/contract_sources/contract_data/extended_resolver.py +3 -3
  29. web3/_utils/contract_sources/contract_data/fallback_function_contract.py +3 -3
  30. web3/_utils/contract_sources/contract_data/function_name_tester_contract.py +3 -3
  31. web3/_utils/contract_sources/contract_data/math_contract.py +3 -3
  32. web3/_utils/contract_sources/contract_data/offchain_lookup.py +3 -3
  33. web3/_utils/contract_sources/contract_data/offchain_resolver.py +3 -3
  34. web3/_utils/contract_sources/contract_data/panic_errors_contract.py +3 -3
  35. web3/_utils/contract_sources/contract_data/payable_tester.py +3 -3
  36. web3/_utils/contract_sources/contract_data/receive_function_contracts.py +5 -5
  37. web3/_utils/contract_sources/contract_data/reflector_contracts.py +3 -3
  38. web3/_utils/contract_sources/contract_data/revert_contract.py +3 -3
  39. web3/_utils/contract_sources/contract_data/simple_resolver.py +3 -3
  40. web3/_utils/contract_sources/contract_data/storage_contract.py +3 -3
  41. web3/_utils/contract_sources/contract_data/string_contract.py +3 -3
  42. web3/_utils/contract_sources/contract_data/tuple_contracts.py +5 -5
  43. web3/_utils/contracts.py +172 -220
  44. web3/_utils/datatypes.py +5 -1
  45. web3/_utils/decorators.py +6 -1
  46. web3/_utils/empty.py +1 -1
  47. web3/_utils/encoding.py +16 -12
  48. web3/_utils/error_formatters_utils.py +5 -3
  49. web3/_utils/events.py +78 -72
  50. web3/_utils/fee_utils.py +1 -3
  51. web3/_utils/filters.py +24 -22
  52. web3/_utils/formatters.py +2 -2
  53. web3/_utils/http.py +8 -2
  54. web3/_utils/http_session_manager.py +314 -0
  55. web3/_utils/math.py +14 -15
  56. web3/_utils/method_formatters.py +161 -34
  57. web3/_utils/module.py +2 -1
  58. web3/_utils/module_testing/__init__.py +3 -2
  59. web3/_utils/module_testing/eth_module.py +736 -583
  60. web3/_utils/module_testing/go_ethereum_debug_module.py +128 -0
  61. web3/_utils/module_testing/module_testing_utils.py +81 -24
  62. web3/_utils/module_testing/persistent_connection_provider.py +702 -220
  63. web3/_utils/module_testing/utils.py +114 -33
  64. web3/_utils/module_testing/web3_module.py +438 -17
  65. web3/_utils/normalizers.py +13 -11
  66. web3/_utils/rpc_abi.py +10 -22
  67. web3/_utils/threads.py +8 -7
  68. web3/_utils/transactions.py +32 -25
  69. web3/_utils/type_conversion.py +5 -1
  70. web3/_utils/validation.py +20 -17
  71. web3/beacon/__init__.py +5 -0
  72. web3/beacon/api_endpoints.py +3 -0
  73. web3/beacon/async_beacon.py +29 -6
  74. web3/beacon/beacon.py +24 -6
  75. web3/contract/__init__.py +7 -0
  76. web3/contract/async_contract.py +285 -82
  77. web3/contract/base_contract.py +556 -258
  78. web3/contract/contract.py +295 -84
  79. web3/contract/utils.py +251 -55
  80. web3/datastructures.py +56 -41
  81. web3/eth/__init__.py +7 -0
  82. web3/eth/async_eth.py +89 -69
  83. web3/eth/base_eth.py +7 -3
  84. web3/eth/eth.py +43 -66
  85. web3/exceptions.py +158 -83
  86. web3/gas_strategies/time_based.py +8 -6
  87. web3/geth.py +53 -184
  88. web3/main.py +77 -43
  89. web3/manager.py +368 -101
  90. web3/method.py +43 -15
  91. web3/middleware/__init__.py +26 -8
  92. web3/middleware/attrdict.py +12 -22
  93. web3/middleware/base.py +55 -2
  94. web3/middleware/filter.py +45 -23
  95. web3/middleware/formatting.py +6 -3
  96. web3/middleware/names.py +4 -1
  97. web3/middleware/signing.py +15 -6
  98. web3/middleware/stalecheck.py +2 -1
  99. web3/module.py +62 -26
  100. web3/providers/__init__.py +21 -0
  101. web3/providers/async_base.py +93 -38
  102. web3/providers/base.py +85 -40
  103. web3/providers/eth_tester/__init__.py +5 -0
  104. web3/providers/eth_tester/defaults.py +2 -55
  105. web3/providers/eth_tester/main.py +57 -35
  106. web3/providers/eth_tester/middleware.py +16 -17
  107. web3/providers/ipc.py +42 -18
  108. web3/providers/legacy_websocket.py +27 -2
  109. web3/providers/persistent/__init__.py +7 -0
  110. web3/providers/persistent/async_ipc.py +61 -121
  111. web3/providers/persistent/persistent.py +324 -17
  112. web3/providers/persistent/persistent_connection.py +54 -5
  113. web3/providers/persistent/request_processor.py +136 -56
  114. web3/providers/persistent/subscription_container.py +56 -0
  115. web3/providers/persistent/subscription_manager.py +233 -0
  116. web3/providers/persistent/websocket.py +29 -92
  117. web3/providers/rpc/__init__.py +5 -0
  118. web3/providers/rpc/async_rpc.py +73 -18
  119. web3/providers/rpc/rpc.py +73 -30
  120. web3/providers/rpc/utils.py +1 -13
  121. web3/scripts/install_pre_releases.py +33 -0
  122. web3/scripts/parse_pygeth_version.py +16 -0
  123. web3/testing.py +4 -4
  124. web3/tracing.py +9 -5
  125. web3/types.py +141 -74
  126. web3/utils/__init__.py +64 -5
  127. web3/utils/abi.py +790 -10
  128. web3/utils/address.py +8 -0
  129. web3/utils/async_exception_handling.py +20 -11
  130. web3/utils/caching.py +34 -4
  131. web3/utils/exception_handling.py +9 -12
  132. web3/utils/subscriptions.py +285 -0
  133. {web3-7.0.0b1.dist-info → web3-7.7.0.dist-info}/LICENSE +1 -1
  134. web3-7.7.0.dist-info/METADATA +130 -0
  135. web3-7.7.0.dist-info/RECORD +171 -0
  136. {web3-7.0.0b1.dist-info → web3-7.7.0.dist-info}/WHEEL +1 -1
  137. {web3-7.0.0b1.dist-info → web3-7.7.0.dist-info}/top_level.txt +0 -1
  138. ethpm/__init__.py +0 -20
  139. ethpm/_utils/__init__.py +0 -0
  140. ethpm/_utils/backend.py +0 -93
  141. ethpm/_utils/cache.py +0 -44
  142. ethpm/_utils/chains.py +0 -119
  143. ethpm/_utils/contract.py +0 -35
  144. ethpm/_utils/deployments.py +0 -145
  145. ethpm/_utils/ipfs.py +0 -116
  146. ethpm/_utils/protobuf/__init__.py +0 -0
  147. ethpm/_utils/protobuf/ipfs_file_pb2.py +0 -33
  148. ethpm/_utils/registry.py +0 -29
  149. ethpm/assets/__init__.py +0 -0
  150. ethpm/assets/ens/v3.json +0 -1
  151. ethpm/assets/escrow/with_bytecode_v3.json +0 -1
  152. ethpm/assets/ipfs_file.proto +0 -32
  153. ethpm/assets/owned/output_v3.json +0 -1
  154. ethpm/assets/owned/with_contract_type_v3.json +0 -1
  155. ethpm/assets/registry/contracts/Authority.sol +0 -156
  156. ethpm/assets/registry/contracts/IndexedOrderedSetLib.sol +0 -106
  157. ethpm/assets/registry/contracts/PackageDB.sol +0 -225
  158. ethpm/assets/registry/contracts/PackageRegistry.sol +0 -361
  159. ethpm/assets/registry/contracts/PackageRegistryInterface.sol +0 -97
  160. ethpm/assets/registry/contracts/ReleaseDB.sol +0 -309
  161. ethpm/assets/registry/contracts/ReleaseValidator.sol +0 -152
  162. ethpm/assets/registry/solc_input.json +0 -1
  163. ethpm/assets/registry/solc_output.json +0 -1
  164. ethpm/assets/registry/v3.json +0 -1
  165. ethpm/assets/safe-math-lib/v3-strict-no-deployments.json +0 -1
  166. ethpm/assets/simple-registry/contracts/Ownable.sol +0 -63
  167. ethpm/assets/simple-registry/contracts/PackageRegistry.sol +0 -373
  168. ethpm/assets/simple-registry/contracts/PackageRegistryInterface.sol +0 -96
  169. ethpm/assets/simple-registry/solc_input.json +0 -33
  170. ethpm/assets/simple-registry/solc_output.json +0 -1
  171. ethpm/assets/simple-registry/v3.json +0 -1
  172. ethpm/assets/standard-token/output_v3.json +0 -1
  173. ethpm/assets/standard-token/with_bytecode_v3.json +0 -1
  174. ethpm/assets/vyper_registry/0.1.0.json +0 -1
  175. ethpm/assets/vyper_registry/registry.vy +0 -216
  176. ethpm/assets/vyper_registry/registry_with_delete.vy +0 -244
  177. ethpm/backends/__init__.py +0 -0
  178. ethpm/backends/base.py +0 -43
  179. ethpm/backends/http.py +0 -108
  180. ethpm/backends/ipfs.py +0 -219
  181. ethpm/backends/registry.py +0 -154
  182. ethpm/constants.py +0 -17
  183. ethpm/contract.py +0 -187
  184. ethpm/dependencies.py +0 -58
  185. ethpm/deployments.py +0 -80
  186. ethpm/ethpm-spec/examples/escrow/1.0.0-pretty.json +0 -146
  187. ethpm/ethpm-spec/examples/escrow/1.0.0.json +0 -1
  188. ethpm/ethpm-spec/examples/escrow/contracts/Escrow.sol +0 -32
  189. ethpm/ethpm-spec/examples/escrow/contracts/SafeSendLib.sol +0 -20
  190. ethpm/ethpm-spec/examples/escrow/v3-pretty.json +0 -171
  191. ethpm/ethpm-spec/examples/escrow/v3.json +0 -1
  192. ethpm/ethpm-spec/examples/owned/1.0.0-pretty.json +0 -21
  193. ethpm/ethpm-spec/examples/owned/1.0.0.json +0 -1
  194. ethpm/ethpm-spec/examples/owned/contracts/Owned.sol +0 -12
  195. ethpm/ethpm-spec/examples/owned/v3-pretty.json +0 -27
  196. ethpm/ethpm-spec/examples/owned/v3.json +0 -1
  197. ethpm/ethpm-spec/examples/piper-coin/1.0.0-pretty.json +0 -31
  198. ethpm/ethpm-spec/examples/piper-coin/1.0.0.json +0 -1
  199. ethpm/ethpm-spec/examples/piper-coin/v3-pretty.json +0 -21
  200. ethpm/ethpm-spec/examples/piper-coin/v3.json +0 -1
  201. ethpm/ethpm-spec/examples/safe-math-lib/1.0.0-pretty.json +0 -85
  202. ethpm/ethpm-spec/examples/safe-math-lib/1.0.0.json +0 -1
  203. ethpm/ethpm-spec/examples/safe-math-lib/contracts/SafeMathLib.sol +0 -24
  204. ethpm/ethpm-spec/examples/safe-math-lib/v3-pretty.json +0 -117
  205. ethpm/ethpm-spec/examples/safe-math-lib/v3.json +0 -1
  206. ethpm/ethpm-spec/examples/standard-token/1.0.0-pretty.json +0 -55
  207. ethpm/ethpm-spec/examples/standard-token/1.0.0.json +0 -1
  208. ethpm/ethpm-spec/examples/standard-token/contracts/AbstractToken.sol +0 -20
  209. ethpm/ethpm-spec/examples/standard-token/contracts/StandardToken.sol +0 -84
  210. ethpm/ethpm-spec/examples/standard-token/v3-pretty.json +0 -460
  211. ethpm/ethpm-spec/examples/standard-token/v3.json +0 -1
  212. ethpm/ethpm-spec/examples/transferable/1.0.0-pretty.json +0 -21
  213. ethpm/ethpm-spec/examples/transferable/1.0.0.json +0 -1
  214. ethpm/ethpm-spec/examples/transferable/contracts/Transferable.sol +0 -14
  215. ethpm/ethpm-spec/examples/transferable/v3-pretty.json +0 -27
  216. ethpm/ethpm-spec/examples/transferable/v3.json +0 -1
  217. ethpm/ethpm-spec/examples/wallet/1.0.0-pretty.json +0 -120
  218. ethpm/ethpm-spec/examples/wallet/1.0.0.json +0 -1
  219. ethpm/ethpm-spec/examples/wallet/contracts/Wallet.sol +0 -41
  220. ethpm/ethpm-spec/examples/wallet/v3-pretty.json +0 -181
  221. ethpm/ethpm-spec/examples/wallet/v3.json +0 -1
  222. ethpm/ethpm-spec/examples/wallet-with-send/1.0.0-pretty.json +0 -135
  223. ethpm/ethpm-spec/examples/wallet-with-send/1.0.0.json +0 -1
  224. ethpm/ethpm-spec/examples/wallet-with-send/contracts/WalletWithSend.sol +0 -18
  225. ethpm/ethpm-spec/examples/wallet-with-send/v3-pretty.json +0 -207
  226. ethpm/ethpm-spec/examples/wallet-with-send/v3.json +0 -1
  227. ethpm/ethpm-spec/spec/package.spec.json +0 -379
  228. ethpm/ethpm-spec/spec/v3.spec.json +0 -483
  229. ethpm/exceptions.py +0 -68
  230. ethpm/package.py +0 -438
  231. ethpm/tools/__init__.py +0 -4
  232. ethpm/tools/builder.py +0 -930
  233. ethpm/tools/checker.py +0 -312
  234. ethpm/tools/get_manifest.py +0 -19
  235. ethpm/uri.py +0 -141
  236. ethpm/validation/__init__.py +0 -0
  237. ethpm/validation/manifest.py +0 -146
  238. ethpm/validation/misc.py +0 -39
  239. ethpm/validation/package.py +0 -80
  240. ethpm/validation/uri.py +0 -163
  241. web3/_utils/caching.py +0 -155
  242. web3/_utils/contract_sources/contract_data/address_reflector.py +0 -29
  243. web3/_utils/module_testing/go_ethereum_personal_module.py +0 -300
  244. web3/_utils/request.py +0 -265
  245. web3/pm.py +0 -602
  246. web3/tools/__init__.py +0 -4
  247. web3/tools/benchmark/__init__.py +0 -0
  248. web3/tools/benchmark/main.py +0 -185
  249. web3/tools/benchmark/node.py +0 -126
  250. web3/tools/benchmark/reporting.py +0 -39
  251. web3/tools/benchmark/utils.py +0 -69
  252. web3/tools/pytest_ethereum/__init__.py +0 -0
  253. web3/tools/pytest_ethereum/_utils.py +0 -145
  254. web3/tools/pytest_ethereum/deployer.py +0 -48
  255. web3/tools/pytest_ethereum/exceptions.py +0 -22
  256. web3/tools/pytest_ethereum/linker.py +0 -128
  257. web3/tools/pytest_ethereum/plugins.py +0 -33
  258. web3-7.0.0b1.dist-info/METADATA +0 -114
  259. web3-7.0.0b1.dist-info/RECORD +0 -280
  260. web3-7.0.0b1.dist-info/entry_points.txt +0 -2
  261. /web3/_utils/{function_identifiers.py → abi_element_identifiers.py} +0 -0
ethpm/tools/builder.py DELETED
@@ -1,930 +0,0 @@
1
- import functools
2
- import json
3
- from pathlib import (
4
- Path,
5
- )
6
- import tempfile
7
- from typing import (
8
- TYPE_CHECKING,
9
- Any,
10
- Callable,
11
- Dict,
12
- Iterable,
13
- List,
14
- Optional,
15
- Set,
16
- Tuple,
17
- )
18
-
19
- from eth_typing import (
20
- URI,
21
- HexStr,
22
- Manifest,
23
- )
24
- from eth_utils import (
25
- add_0x_prefix,
26
- is_hex,
27
- is_string,
28
- to_bytes,
29
- to_checksum_address,
30
- to_dict,
31
- to_list,
32
- )
33
- from eth_utils.toolz import (
34
- assoc,
35
- assoc_in,
36
- concat,
37
- curry,
38
- pipe,
39
- )
40
-
41
- from ethpm import (
42
- Package,
43
- )
44
- from ethpm._utils.chains import (
45
- is_BIP122_block_uri,
46
- )
47
- from ethpm.backends.ipfs import (
48
- BaseIPFSBackend,
49
- )
50
- from ethpm.exceptions import (
51
- EthPMValidationError,
52
- ManifestBuildingError,
53
- )
54
- from ethpm.package import (
55
- format_manifest,
56
- )
57
- from ethpm.uri import (
58
- is_supported_content_addressed_uri,
59
- )
60
- from ethpm.validation.manifest import (
61
- validate_manifest_against_schema,
62
- )
63
- from ethpm.validation.package import (
64
- validate_package_name,
65
- )
66
- from web3._utils.validation import (
67
- validate_address,
68
- )
69
-
70
- if TYPE_CHECKING:
71
- from web3 import Web3 # noqa: F401
72
-
73
-
74
- def build(obj: Dict[str, Any], *fns: Callable[..., Any]) -> Dict[str, Any]:
75
- """
76
- Wrapper function to pipe manifest through build functions.
77
- Does not validate the manifest by default.
78
- """
79
- return pipe(obj, *fns)
80
-
81
-
82
- #
83
- # Required Fields
84
- #
85
-
86
-
87
- @curry
88
- def package_name(name: str, manifest: Manifest) -> Manifest:
89
- """
90
- Return a copy of manifest with `name` set to "name".
91
- """
92
- return assoc(manifest, "name", name)
93
-
94
-
95
- @curry
96
- def manifest_version(manifest_version: str, manifest: Manifest) -> Manifest:
97
- """
98
- Return a copy of manifest with `manifest_version` set to "manifest".
99
- """
100
- return assoc(manifest, "manifest", manifest_version)
101
-
102
-
103
- @curry
104
- def version(version: str, manifest: Manifest) -> Manifest:
105
- """
106
- Return a copy of manifest with `version` set to "version".
107
- """
108
- return assoc(manifest, "version", version)
109
-
110
-
111
- #
112
- # Meta
113
- #
114
-
115
-
116
- def authors(*author_list: str) -> Manifest:
117
- """
118
- Return a copy of manifest with a list of author posargs set
119
- to "meta": {"authors": author_list}
120
- """
121
- return _authors(author_list)
122
-
123
-
124
- @curry
125
- @functools.wraps(authors)
126
- def _authors(authors: Set[str], manifest: Manifest) -> Manifest:
127
- return assoc_in(manifest, ("meta", "authors"), list(authors))
128
-
129
-
130
- @curry
131
- def license(license: str, manifest: Manifest) -> Manifest:
132
- """
133
- Return a copy of manifest with `license` set to
134
- "meta": {"license": `license`}
135
- """
136
- return assoc_in(manifest, ("meta", "license"), license)
137
-
138
-
139
- @curry
140
- def description(description: str, manifest: Manifest) -> Manifest:
141
- """
142
- Return a copy of manifest with `description` set to
143
- "meta": {"descriptions": `description`}
144
- """
145
- return assoc_in(manifest, ("meta", "description"), description)
146
-
147
-
148
- def keywords(*keyword_list: str) -> Manifest:
149
- """
150
- Return a copy of manifest with a list of keyword posargs set to
151
- "meta": {"keywords": keyword_list}
152
- """
153
- return _keywords(keyword_list)
154
-
155
-
156
- @curry
157
- @functools.wraps(keywords)
158
- def _keywords(keywords: Set[str], manifest: Manifest) -> Manifest:
159
- return assoc_in(manifest, ("meta", "keywords"), list(keywords))
160
-
161
-
162
- def links(**link_dict: str) -> Manifest:
163
- """
164
- Return a copy of manifest with a dict of link kwargs set to
165
- "meta": {"links": link_dict}
166
- """
167
- return _links(link_dict)
168
-
169
-
170
- @curry
171
- def _links(link_dict: Dict[str, str], manifest: Manifest) -> Manifest:
172
- return assoc_in(manifest, ("meta", "links"), link_dict)
173
-
174
-
175
- #
176
- # Sources
177
- #
178
-
179
-
180
- def get_names_and_paths(compiler_output: Dict[str, Any]) -> Dict[str, str]:
181
- """
182
- Return a mapping of contract name to relative path as defined in compiler output.
183
- """
184
- return {
185
- contract_name: make_path_relative(path)
186
- for path in compiler_output
187
- for contract_name in compiler_output[path].keys()
188
- }
189
-
190
-
191
- def make_path_relative(path: str) -> str:
192
- """
193
- Returns the given path prefixed with "./" if the path
194
- is not already relative in the compiler output.
195
- """
196
- if "../" in path:
197
- raise ManifestBuildingError(
198
- f"Path: {path} appears to be outside of the virtual source tree. "
199
- "Please make sure all sources are within the virtual source tree "
200
- "root directory."
201
- )
202
-
203
- if path[:2] != "./":
204
- return f"./{path}"
205
- return path
206
-
207
-
208
- def source_inliner(
209
- compiler_output: Dict[str, Any], package_root_dir: Optional[Path] = None
210
- ) -> Manifest:
211
- return _inline_sources(compiler_output, package_root_dir)
212
-
213
-
214
- @curry
215
- def _inline_sources(
216
- compiler_output: Dict[str, Any], package_root_dir: Optional[Path], name: str
217
- ) -> Manifest:
218
- return _inline_source(name, compiler_output, package_root_dir)
219
-
220
-
221
- def inline_source(
222
- name: str, compiler_output: Dict[str, Any], package_root_dir: Optional[Path] = None
223
- ) -> Manifest:
224
- """
225
- Return a copy of manifest with added field to
226
- "sources": {relative_source_path: contract_source_data}.
227
-
228
- If `package_root_dir` is not provided, cwd is expected to resolve the relative
229
- path to the source as defined in the compiler output.
230
- """
231
- return _inline_source(name, compiler_output, package_root_dir)
232
-
233
-
234
- @curry
235
- def _inline_source(
236
- name: str,
237
- compiler_output: Dict[str, Any],
238
- package_root_dir: Optional[Path],
239
- manifest: Manifest,
240
- ) -> Manifest:
241
- names_and_paths = get_names_and_paths(compiler_output)
242
- cwd = Path.cwd()
243
- try:
244
- source_path = names_and_paths[name]
245
- except KeyError:
246
- raise ManifestBuildingError(
247
- f"Unable to inline source: {name}. "
248
- f"Available sources include: {list(sorted(names_and_paths.keys()))}."
249
- )
250
-
251
- if package_root_dir:
252
- if (package_root_dir / source_path).is_file():
253
- source_data = (package_root_dir / source_path).read_text()
254
- else:
255
- raise ManifestBuildingError(
256
- f"Contract source: {source_path} cannot be found in "
257
- f"provided package_root_dir: {package_root_dir}."
258
- )
259
- elif (cwd / source_path).is_file():
260
- source_data = (cwd / source_path).read_text()
261
- else:
262
- raise ManifestBuildingError(
263
- "Contract source cannot be resolved, please make sure that the working "
264
- "directory is set to the correct directory or provide `package_root_dir`."
265
- )
266
-
267
- # rstrip used here since Path.read_text() adds a newline to returned contents
268
- source_data_object = {
269
- "content": source_data.rstrip("\n"),
270
- "installPath": source_path,
271
- "type": "solidity",
272
- }
273
- return assoc_in(manifest, ["sources", source_path], source_data_object)
274
-
275
-
276
- def source_pinner(
277
- compiler_output: Dict[str, Any],
278
- ipfs_backend: BaseIPFSBackend,
279
- package_root_dir: Optional[Path] = None,
280
- ) -> Manifest:
281
- return _pin_sources(compiler_output, ipfs_backend, package_root_dir)
282
-
283
-
284
- @curry
285
- def _pin_sources(
286
- compiler_output: Dict[str, Any],
287
- ipfs_backend: BaseIPFSBackend,
288
- package_root_dir: Optional[Path],
289
- name: str,
290
- ) -> Manifest:
291
- return _pin_source(name, compiler_output, ipfs_backend, package_root_dir)
292
-
293
-
294
- def pin_source(
295
- name: str,
296
- compiler_output: Dict[str, Any],
297
- ipfs_backend: BaseIPFSBackend,
298
- package_root_dir: Optional[Path] = None,
299
- ) -> Manifest:
300
- """
301
- Pins source to IPFS and returns a copy of manifest with added field to
302
- "sources": {relative_source_path: IFPS URI}.
303
-
304
- If `package_root_dir` is not provided, cwd is expected to resolve the relative path
305
- to the source as defined in the compiler output.
306
- """
307
- return _pin_source(name, compiler_output, ipfs_backend, package_root_dir)
308
-
309
-
310
- @curry
311
- def _pin_source(
312
- name: str,
313
- compiler_output: Dict[str, Any],
314
- ipfs_backend: BaseIPFSBackend,
315
- package_root_dir: Optional[Path],
316
- manifest: Manifest,
317
- ) -> Manifest:
318
- names_and_paths = get_names_and_paths(compiler_output)
319
- try:
320
- source_path = names_and_paths[name]
321
- except KeyError:
322
- raise ManifestBuildingError(
323
- f"Unable to pin source: {name}. "
324
- f"Available sources include: {list(sorted(names_and_paths.keys()))}."
325
- )
326
- if package_root_dir:
327
- if not (package_root_dir / source_path).is_file():
328
- raise ManifestBuildingError(
329
- f"Unable to find and pin contract source: {source_path} "
330
- f"under specified package_root_dir: {package_root_dir}."
331
- )
332
- (ipfs_data,) = ipfs_backend.pin_assets(package_root_dir / source_path)
333
- else:
334
- cwd = Path.cwd()
335
- if not (cwd / source_path).is_file():
336
- raise ManifestBuildingError(
337
- f"Unable to find and pin contract source: {source_path} "
338
- f"current working directory: {cwd}."
339
- )
340
- (ipfs_data,) = ipfs_backend.pin_assets(cwd / source_path)
341
-
342
- source_data_object = {
343
- "urls": [f"ipfs://{ipfs_data['Hash']}"],
344
- "type": "solidity",
345
- "installPath": source_path,
346
- }
347
- return assoc_in(manifest, ["sources", source_path], source_data_object)
348
-
349
-
350
- #
351
- # Contract Types
352
- #
353
-
354
-
355
- def contract_type(
356
- name: str,
357
- compiler_output: Dict[str, Any],
358
- alias: Optional[str] = None,
359
- abi: Optional[bool] = False,
360
- compiler: Optional[bool] = False,
361
- contract_type: Optional[bool] = False,
362
- deployment_bytecode: Optional[bool] = False,
363
- devdoc: Optional[bool] = False,
364
- userdoc: Optional[bool] = False,
365
- source_id: Optional[bool] = False,
366
- runtime_bytecode: Optional[bool] = False,
367
- ) -> Manifest:
368
- """
369
- Returns a copy of manifest with added contract_data field as specified by kwargs.
370
- If no kwargs are present, all available contract_data found in the compiler output
371
- will be included.
372
-
373
- To include specific contract_data fields, add kwarg set to True (i.e. `abi=True`)
374
- To alias a contract_type, include a kwarg `alias` (i.e. `alias="OwnedAlias"`)
375
- If only an alias kwarg is provided, all available contract data will be included.
376
- Kwargs must match fields as defined in the EthPM Spec (except "alias") if user
377
- wants to include them in custom contract_type.
378
- """
379
- contract_type_fields = {
380
- "contractType": contract_type,
381
- "deploymentBytecode": deployment_bytecode,
382
- "runtimeBytecode": runtime_bytecode,
383
- "abi": abi,
384
- "compiler": compiler,
385
- "userdoc": userdoc,
386
- "devdoc": devdoc,
387
- "sourceId": source_id,
388
- }
389
- selected_fields = [k for k, v in contract_type_fields.items() if v]
390
- return _contract_type(name, compiler_output, alias, selected_fields)
391
-
392
-
393
- @curry
394
- def _contract_type(
395
- name: str,
396
- compiler_output: Dict[str, Any],
397
- alias: Optional[str],
398
- selected_fields: Optional[List[str]],
399
- manifest: Manifest,
400
- ) -> Manifest:
401
- contracts_by_name = normalize_compiler_output(compiler_output)
402
- try:
403
- all_type_data = contracts_by_name[name]
404
- except KeyError:
405
- raise ManifestBuildingError(
406
- f"Contract name: {name} not found in the provided compiler output."
407
- )
408
- if selected_fields:
409
- contract_type_data = filter_all_data_by_selected_fields(
410
- all_type_data, selected_fields
411
- )
412
- else:
413
- contract_type_data = all_type_data
414
-
415
- if "compiler" in contract_type_data:
416
- compiler_info = contract_type_data.pop("compiler")
417
- contract_type_ref = alias if alias else name
418
- manifest_with_compilers = add_compilers_to_manifest(
419
- compiler_info, contract_type_ref, manifest
420
- )
421
- else:
422
- manifest_with_compilers = manifest
423
-
424
- if alias:
425
- return assoc_in(
426
- manifest_with_compilers,
427
- ["contractTypes", alias],
428
- assoc(contract_type_data, "contractType", name),
429
- )
430
- return assoc_in(
431
- manifest_with_compilers, ["contractTypes", name], contract_type_data
432
- )
433
-
434
-
435
- def add_compilers_to_manifest(
436
- compiler_info: Dict[str, Any], contract_type: str, manifest: Manifest
437
- ) -> Manifest:
438
- """
439
- Adds a compiler information object to a manifest's top-level `compilers`.
440
- """
441
- if "compilers" not in manifest:
442
- compiler_info["contractTypes"] = [contract_type]
443
- return assoc_in(manifest, ["compilers"], [compiler_info])
444
-
445
- updated_compiler_info = update_compilers_object(
446
- compiler_info, contract_type, manifest["compilers"]
447
- )
448
- return assoc_in(manifest, ["compilers"], updated_compiler_info)
449
-
450
-
451
- @to_list
452
- def update_compilers_object(
453
- new_compiler: Dict[str, Any],
454
- contract_type: str,
455
- previous_compilers: List[Dict[str, Any]],
456
- ) -> Iterable[Dict[str, Any]]:
457
- """
458
- Updates a manifest's top-level `compilers` with a new compiler information object.
459
- - If compiler version already exists, we just update the compiler's `contractTypes`
460
- """
461
- recorded_new_contract_type = False
462
- for compiler in previous_compilers:
463
- contract_types = compiler.pop("contractTypes")
464
- if contract_type in contract_types:
465
- raise ManifestBuildingError(
466
- f"Contract type: {contract_type} already referenced in `compilers`."
467
- )
468
- if compiler == new_compiler:
469
- contract_types.append(contract_type)
470
- recorded_new_contract_type = True
471
- compiler["contractTypes"] = contract_types
472
- yield compiler
473
-
474
- if not recorded_new_contract_type:
475
- new_compiler["contractTypes"] = [contract_type]
476
- yield new_compiler
477
-
478
-
479
- @to_dict
480
- def filter_all_data_by_selected_fields(
481
- all_type_data: Dict[str, Any], selected_fields: List[str]
482
- ) -> Iterable[Tuple[str, Any]]:
483
- """
484
- Raises exception if selected field data is not available in the contract type data
485
- automatically gathered by normalize_compiler_output. Otherwise, returns the data.
486
- """
487
- for field in selected_fields:
488
- if field in all_type_data:
489
- yield field, all_type_data[field]
490
- else:
491
- raise ManifestBuildingError(
492
- f"Selected field: {field} not available in data collected from "
493
- f"solc output: {list(sorted(all_type_data.keys()))}. Please make"
494
- "sure the relevant data is present in your solc output."
495
- )
496
-
497
-
498
- def normalize_compiler_output(compiler_output: Dict[str, Any]) -> Dict[str, Any]:
499
- """
500
- Return compiler output with normalized fields for each contract type,
501
- as specified in `normalize_contract_type`.
502
- """
503
- paths_and_names = [
504
- (path, contract_name)
505
- for path in compiler_output
506
- for contract_name in compiler_output[path].keys()
507
- ]
508
- paths, names = zip(*paths_and_names)
509
- if len(names) != len(set(names)):
510
- duplicates = {name for name in names if names.count(name) > 1}
511
- raise ManifestBuildingError(
512
- f"Duplicate contract types: {duplicates} were found in the compiler output."
513
- )
514
- return {
515
- name: normalize_contract_type(compiler_output[path][name], path)
516
- for path, name in paths_and_names
517
- }
518
-
519
-
520
- @to_dict
521
- def normalize_contract_type(
522
- contract_type_data: Dict[str, Any],
523
- source_id: str,
524
- ) -> Iterable[Tuple[str, Any]]:
525
- """
526
- Serialize contract_data found in compiler output to the defined fields.
527
- """
528
- yield "abi", contract_type_data["abi"]
529
- yield "sourceId", source_id
530
- if "evm" in contract_type_data:
531
- if "bytecode" in contract_type_data["evm"]:
532
- yield "deploymentBytecode", normalize_bytecode_object(
533
- contract_type_data["evm"]["bytecode"]
534
- )
535
- if "deployedBytecode" in contract_type_data["evm"]:
536
- yield "runtimeBytecode", normalize_bytecode_object(
537
- contract_type_data["evm"]["deployedBytecode"]
538
- )
539
- if "devdoc" in contract_type_data:
540
- yield "devdoc", contract_type_data["devdoc"]
541
- if "userdoc" in contract_type_data:
542
- yield "userdoc", contract_type_data["userdoc"]
543
- # make sure metadata isn't an empty string in solc output
544
- if "metadata" in contract_type_data and contract_type_data["metadata"]:
545
- yield "compiler", normalize_compiler_object(
546
- json.loads(contract_type_data["metadata"])
547
- )
548
-
549
-
550
- @to_dict
551
- def normalize_compiler_object(obj: Dict[str, Any]) -> Iterable[Tuple[str, Any]]:
552
- yield "name", "solc"
553
- yield "version", obj["compiler"]["version"]
554
- yield "settings", {"optimize": obj["settings"]["optimizer"]["enabled"]}
555
-
556
-
557
- @to_dict
558
- def normalize_bytecode_object(obj: Dict[str, Any]) -> Iterable[Tuple[str, Any]]:
559
- try:
560
- link_references = obj["linkReferences"]
561
- except KeyError:
562
- link_references = None
563
- try:
564
- bytecode = obj["object"]
565
- except KeyError:
566
- raise ManifestBuildingError(
567
- "'object' key not found in bytecode data from compiler output. "
568
- "Please make sure your solidity compiler output is valid."
569
- )
570
- if link_references:
571
- yield "linkReferences", process_link_references(link_references, bytecode)
572
- yield "bytecode", process_bytecode(link_references, bytecode)
573
- else:
574
- yield "bytecode", add_0x_prefix(bytecode)
575
-
576
-
577
- def process_bytecode(link_refs: Dict[str, Any], bytecode: bytes) -> HexStr:
578
- """
579
- Replace link_refs in bytecode with 0's.
580
- """
581
- all_offsets = [y for x in link_refs.values() for y in x.values()]
582
- # Link ref validation.
583
- validate_link_ref_fns = (
584
- validate_link_ref(ref["start"] * 2, ref["length"] * 2)
585
- for ref in concat(all_offsets)
586
- )
587
- pipe(bytecode, *validate_link_ref_fns)
588
- # Convert link_refs in bytecode to 0's
589
- link_fns = (
590
- replace_link_ref_in_bytecode(ref["start"] * 2, ref["length"] * 2)
591
- for ref in concat(all_offsets)
592
- )
593
- processed_bytecode = pipe(bytecode, *link_fns)
594
- return add_0x_prefix(processed_bytecode)
595
-
596
-
597
- @curry
598
- def replace_link_ref_in_bytecode(offset: int, length: int, bytecode: str) -> str:
599
- new_bytes = (
600
- bytecode[:offset] + "0" * length + bytecode[offset + length :] # noqa: E203
601
- )
602
- return new_bytes
603
-
604
-
605
- # todo pull all bytecode linking/validating across py-ethpm into shared utils
606
- @to_list
607
- def process_link_references(
608
- link_refs: Dict[str, Any], bytecode: str
609
- ) -> Iterable[Dict[str, Any]]:
610
- for link_ref in link_refs.values():
611
- yield normalize_link_ref(link_ref, bytecode)
612
-
613
-
614
- def normalize_link_ref(link_ref: Dict[str, Any], bytecode: str) -> Dict[str, Any]:
615
- name = list(link_ref.keys())[0]
616
- return {
617
- "name": name,
618
- "length": 20,
619
- "offsets": normalize_offsets(link_ref, bytecode),
620
- }
621
-
622
-
623
- @to_list
624
- def normalize_offsets(data: Dict[str, Any], bytecode: str) -> Iterable[List[int]]:
625
- for link_ref in data.values():
626
- for ref in link_ref:
627
- yield ref["start"]
628
-
629
-
630
- @curry
631
- def validate_link_ref(offset: int, length: int, bytecode: str) -> str:
632
- slot_length = offset + length
633
- slot = bytecode[offset:slot_length]
634
- if slot[:2] != "__" and slot[-2:] != "__":
635
- raise EthPMValidationError(
636
- f"Slot: {slot}, at offset: {offset} of length: {length} is not a valid "
637
- "link_ref that can be replaced."
638
- )
639
- return bytecode
640
-
641
-
642
- #
643
- # Deployments
644
- #
645
-
646
-
647
- def deployment_type(
648
- *,
649
- contract_instance: str,
650
- contract_type: str,
651
- deployment_bytecode: Dict[str, Any] = None,
652
- runtime_bytecode: Dict[str, Any] = None,
653
- compiler: Dict[str, Any] = None,
654
- ) -> Manifest:
655
- """
656
- Returns a callable that allows the user to add deployments of the same type
657
- across multiple chains.
658
- """
659
- return _deployment_type(
660
- contract_instance,
661
- contract_type,
662
- deployment_bytecode,
663
- runtime_bytecode,
664
- compiler,
665
- )
666
-
667
-
668
- def deployment(
669
- *,
670
- block_uri: URI,
671
- contract_instance: str,
672
- contract_type: str,
673
- address: HexStr,
674
- transaction: HexStr = None,
675
- block: HexStr = None,
676
- deployment_bytecode: Dict[str, Any] = None,
677
- runtime_bytecode: Dict[str, Any] = None,
678
- compiler: Dict[str, Any] = None,
679
- ) -> Manifest:
680
- """
681
- Returns a manifest, with the newly included deployment. Requires a valid
682
- blockchain URI, however no validation is provided that this URI is unique
683
- amongst the other deployment URIs, so the user must take care that each
684
- blockchain URI represents a unique blockchain.
685
- """
686
- return _deployment(
687
- contract_instance,
688
- contract_type,
689
- deployment_bytecode,
690
- runtime_bytecode,
691
- compiler,
692
- block_uri,
693
- address,
694
- transaction,
695
- block,
696
- )
697
-
698
-
699
- @curry
700
- def _deployment_type(
701
- contract_instance: str,
702
- contract_type: str,
703
- deployment_bytecode: Dict[str, Any],
704
- runtime_bytecode: Dict[str, Any],
705
- compiler: Dict[str, Any],
706
- block_uri: URI,
707
- address: HexStr,
708
- tx: HexStr = None,
709
- block: HexStr = None,
710
- manifest: Manifest = None,
711
- ) -> Manifest:
712
- return _deployment(
713
- contract_instance,
714
- contract_type,
715
- deployment_bytecode,
716
- runtime_bytecode,
717
- compiler,
718
- block_uri,
719
- address,
720
- tx,
721
- block,
722
- )
723
-
724
-
725
- @curry
726
- def _deployment(
727
- contract_instance: str,
728
- contract_type: str,
729
- deployment_bytecode: Dict[str, Any],
730
- runtime_bytecode: Dict[str, Any],
731
- compiler: Dict[str, Any],
732
- block_uri: URI,
733
- address: HexStr,
734
- tx: HexStr,
735
- block: HexStr,
736
- manifest: Manifest,
737
- ) -> Manifest:
738
- validate_address(address)
739
- if not is_BIP122_block_uri(block_uri):
740
- raise ManifestBuildingError(f"{block_uri} is not a valid BIP122 URI.")
741
-
742
- if tx:
743
- if not is_string(tx) and not is_hex(tx):
744
- raise ManifestBuildingError(
745
- f"Transaction hash: {tx} is not a valid hexstring"
746
- )
747
-
748
- if block:
749
- if not is_string(block) and not is_hex(block):
750
- raise ManifestBuildingError(f"Block hash: {block} is not a valid hexstring")
751
- # todo: validate db, rb and compiler are properly formatted dicts
752
- deployment_data = _build_deployments_object(
753
- contract_type,
754
- deployment_bytecode,
755
- runtime_bytecode,
756
- compiler,
757
- address,
758
- tx,
759
- block,
760
- manifest,
761
- )
762
- return assoc_in(
763
- manifest, ["deployments", block_uri, contract_instance], deployment_data
764
- )
765
-
766
-
767
- @to_dict
768
- def _build_deployments_object(
769
- contract_type: str,
770
- deployment_bytecode: Dict[str, Any],
771
- runtime_bytecode: Dict[str, Any],
772
- compiler: Dict[str, Any],
773
- address: HexStr,
774
- tx: HexStr,
775
- block: HexStr,
776
- manifest: Dict[str, Any],
777
- ) -> Iterable[Tuple[str, Any]]:
778
- """
779
- Returns a dict with properly formatted deployment data.
780
- """
781
- yield "contractType", contract_type
782
- yield "address", to_checksum_address(address)
783
- if deployment_bytecode:
784
- yield "deploymentBytecode", deployment_bytecode
785
- if compiler:
786
- yield "compiler", compiler
787
- if tx:
788
- yield "transaction", tx
789
- if block:
790
- yield "block", block
791
- if runtime_bytecode:
792
- yield "runtimeBytecode", runtime_bytecode
793
-
794
-
795
- #
796
- # Build Dependencies
797
- #
798
-
799
-
800
- def build_dependency(package_name: str, uri: URI) -> Manifest:
801
- """
802
- Returns the manifest with injected build dependency.
803
- """
804
- return _build_dependency(package_name, uri)
805
-
806
-
807
- @curry
808
- def _build_dependency(package_name: str, uri: URI, manifest: Manifest) -> Manifest:
809
- validate_package_name(package_name)
810
- if not is_supported_content_addressed_uri(uri):
811
- raise EthPMValidationError(
812
- f"{uri} is not a supported content-addressed URI. "
813
- "Currently only IPFS and Github blob uris are supported."
814
- )
815
- return assoc_in(manifest, ("buildDependencies", package_name), uri)
816
-
817
-
818
- #
819
- # Helpers
820
- #
821
-
822
-
823
- @curry
824
- def init_manifest(
825
- package_name: str, version: str, manifest_version: Optional[str] = "ethpm/3"
826
- ) -> Dict[str, Any]:
827
- """
828
- Returns an initial dict with the minimal required fields for a valid manifest.
829
- Should only be used as the first fn to be piped into a `build()` pipeline.
830
- """
831
- return {
832
- "name": package_name,
833
- "version": version,
834
- "manifest": manifest_version,
835
- }
836
-
837
-
838
- #
839
- # Formatting
840
- #
841
-
842
-
843
- @curry
844
- def validate(manifest: Manifest) -> Manifest:
845
- """
846
- Return a validated manifest against the V2-specification schema.
847
- """
848
- validate_manifest_against_schema(manifest)
849
- return manifest
850
-
851
-
852
- @curry
853
- def as_package(w3: "Web3", manifest: Manifest) -> Package:
854
- """
855
- Return a Package object instantiated with the provided manifest and web3 instance.
856
- """
857
- return Package(manifest, w3)
858
-
859
-
860
- def write_to_disk(
861
- manifest_root_dir: Optional[Path] = None,
862
- manifest_name: Optional[str] = None,
863
- prettify: Optional[bool] = False,
864
- ) -> Manifest:
865
- """
866
- Write the active manifest to disk
867
- Defaults
868
- - Writes manifest to cwd unless Path is provided as manifest_root_dir.
869
- - Writes manifest with a filename of Manifest[version].json unless a desired
870
- manifest name (which must end in json) is provided as manifest_name.
871
- - Writes the minified manifest version to disk unless prettify is set to True.
872
- """
873
- return _write_to_disk(manifest_root_dir, manifest_name, prettify)
874
-
875
-
876
- @curry
877
- def _write_to_disk(
878
- manifest_root_dir: Optional[Path],
879
- manifest_name: Optional[str],
880
- prettify: Optional[bool],
881
- manifest: Manifest,
882
- ) -> Manifest:
883
- if manifest_root_dir:
884
- if manifest_root_dir.is_dir():
885
- cwd = manifest_root_dir
886
- else:
887
- raise ManifestBuildingError(
888
- f"Manifest root directory: {manifest_root_dir} cannot be found, please "
889
- "provide a valid directory for writing the manifest to disk. "
890
- "(Path obj // leave manifest_root_dir blank to default to cwd)"
891
- )
892
- else:
893
- cwd = Path.cwd()
894
-
895
- if manifest_name:
896
- if not manifest_name.lower().endswith(".json"):
897
- raise ManifestBuildingError(
898
- f"Invalid manifest name: {manifest_name}. "
899
- "All manifest names must end in .json"
900
- )
901
- disk_manifest_name = manifest_name
902
- else:
903
- disk_manifest_name = manifest["version"] + ".json"
904
-
905
- contents = format_manifest(manifest, prettify=prettify)
906
-
907
- if (cwd / disk_manifest_name).is_file():
908
- raise ManifestBuildingError(
909
- f"Manifest: {disk_manifest_name} already exists in cwd: {cwd}"
910
- )
911
- (cwd / disk_manifest_name).write_text(contents)
912
- return manifest
913
-
914
-
915
- @curry
916
- def pin_to_ipfs(
917
- manifest: Manifest, *, backend: BaseIPFSBackend, prettify: Optional[bool] = False
918
- ) -> List[Dict[str, str]]:
919
- """
920
- Returns the IPFS pin data after pinning the manifest to the provided IPFS Backend.
921
-
922
- `pin_to_ipfs()` Should *always* be the last argument in a builder, as it will
923
- return the pin data and not the manifest.
924
- """
925
- contents = format_manifest(manifest, prettify=prettify)
926
-
927
- with tempfile.NamedTemporaryFile() as temp:
928
- temp.write(to_bytes(text=contents))
929
- temp.seek(0)
930
- return backend.pin_assets(Path(temp.name))