genlayer-test 0.2.0__py3-none-any.whl → 0.3.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.
- {genlayer_test-0.2.0.dist-info → genlayer_test-0.3.0.dist-info}/METADATA +77 -10
- genlayer_test-0.3.0.dist-info/RECORD +65 -0
- {genlayer_test-0.2.0.dist-info → genlayer_test-0.3.0.dist-info}/entry_points.txt +1 -1
- gltest/__init__.py +4 -4
- gltest/artifacts/contract.py +9 -4
- gltest/glchain/__init__.py +3 -3
- gltest/glchain/account.py +15 -11
- gltest/glchain/client.py +39 -3
- gltest/glchain/contract.py +57 -26
- gltest/helpers/fixture_snapshot.py +3 -2
- gltest_cli/config/__init__.py +0 -0
- gltest_cli/config/constants.py +10 -0
- gltest_cli/config/general.py +10 -0
- gltest_cli/config/plugin.py +102 -0
- gltest_cli/config/types.py +137 -0
- gltest_cli/config/user.py +222 -0
- gltest_cli/logging.py +51 -0
- tests/__init__.py +0 -0
- tests/examples/tests/test_llm_erc20.py +2 -2
- tests/examples/tests/test_multi_read_erc20.py +13 -3
- tests/examples/tests/test_multi_tenant_storage.py +12 -3
- tests/examples/tests/test_read_erc20.py +2 -2
- tests/examples/tests/test_storage.py +4 -2
- tests/examples/tests/test_user_storage.py +17 -3
- tests/gltest/__init__.py +0 -0
- tests/gltest/artifact/__init__.py +0 -0
- tests/gltest/artifact/test_contract_definition.py +91 -0
- tests/gltest_cli/__init__.py +0 -0
- tests/gltest_cli/config/test_plugin.py +127 -0
- tests/gltest_cli/config/test_user.py +351 -0
- genlayer_test-0.2.0.dist-info/RECORD +0 -55
- gltest/plugin_config.py +0 -42
- gltest/plugin_hooks.py +0 -51
- tests/artifact/test_contract_definition.py +0 -347
- tests/plugin/test_plugin_hooks.py +0 -78
- {genlayer_test-0.2.0.dist-info → genlayer_test-0.3.0.dist-info}/WHEEL +0 -0
- {genlayer_test-0.2.0.dist-info → genlayer_test-0.3.0.dist-info}/licenses/LICENSE +0 -0
- {genlayer_test-0.2.0.dist-info → genlayer_test-0.3.0.dist-info}/top_level.txt +0 -0
- /tests/{plugin/conftest.py → conftest.py} +0 -0
- /tests/{artifact → gltest/artifact}/contracts/duplicate_ic_contract_1.py +0 -0
- /tests/{artifact → gltest/artifact}/contracts/duplicate_ic_contract_2.py +0 -0
- /tests/{artifact → gltest/artifact}/contracts/not_ic_contract.py +0 -0
- /tests/{assertions → gltest/assertions}/test_assertions.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: genlayer-test
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.3.0
|
4
4
|
Summary: GenLayer Testing Suite
|
5
5
|
Author: GenLayer
|
6
6
|
License-Expression: MIT
|
@@ -14,7 +14,11 @@ Requires-Python: >=3.12
|
|
14
14
|
Description-Content-Type: text/markdown
|
15
15
|
License-File: LICENSE
|
16
16
|
Requires-Dist: pytest
|
17
|
-
Requires-Dist:
|
17
|
+
Requires-Dist: setuptools>=77.0
|
18
|
+
Requires-Dist: genlayer-py==0.5.0
|
19
|
+
Requires-Dist: colorama>=0.4.6
|
20
|
+
Requires-Dist: pyyaml
|
21
|
+
Requires-Dist: python-dotenv
|
18
22
|
Dynamic: license-file
|
19
23
|
|
20
24
|
# GenLayer Testing Suite
|
@@ -41,13 +45,13 @@ pip install genlayer-test
|
|
41
45
|
### Basic Usage
|
42
46
|
|
43
47
|
```python
|
44
|
-
from gltest import get_contract_factory,
|
48
|
+
from gltest import get_contract_factory, get_default_account, create_account
|
45
49
|
from gltest.assertions import tx_execution_succeeded
|
46
50
|
|
47
51
|
factory = get_contract_factory("MyContract")
|
48
52
|
# Deploy a contract with default account
|
49
53
|
contract = factory.deploy() # This will be deployed with default_account
|
50
|
-
assert contract.account ==
|
54
|
+
assert contract.account == get_default_account()
|
51
55
|
|
52
56
|
# Deploy a contract with other account
|
53
57
|
other_account = create_account()
|
@@ -99,6 +103,58 @@ $ cd genlayer-testing-suite
|
|
99
103
|
$ pip install -e .
|
100
104
|
```
|
101
105
|
|
106
|
+
### Configuration
|
107
|
+
|
108
|
+
The GenLayer Testing Suite can be configured using an optional but recommended `gltest.config.yaml` file in your project root. While not required, this file helps manage network configurations, contract paths, and environment settings in a centralized way, making it easier to maintain different environments and share configurations across team members.
|
109
|
+
|
110
|
+
```yaml
|
111
|
+
# gltest.config.yaml
|
112
|
+
networks:
|
113
|
+
default: localnet # Default network to use
|
114
|
+
|
115
|
+
localnet: # Local development network configuration
|
116
|
+
url: "http://127.0.0.1:4000/api"
|
117
|
+
|
118
|
+
testnet_asimov: # Test network configuration
|
119
|
+
id: 4221
|
120
|
+
url: "http://34.32.169.58:9151"
|
121
|
+
accounts:
|
122
|
+
- "${ACCOUNT_PRIVATE_KEY_1}"
|
123
|
+
- "${ACCOUNT_PRIVATE_KEY_2}"
|
124
|
+
- "${ACCOUNT_PRIVATE_KEY_3}"
|
125
|
+
|
126
|
+
paths:
|
127
|
+
contracts: "contracts" # Path to your contracts directory
|
128
|
+
|
129
|
+
environment: .env # Path to your environment file containing private keys and other secrets
|
130
|
+
```
|
131
|
+
|
132
|
+
Key configuration sections:
|
133
|
+
|
134
|
+
1. **Networks**: Define different network environments
|
135
|
+
- `default`: Specifies which network to use by default
|
136
|
+
- Network configurations can include:
|
137
|
+
- `url`: The RPC endpoint for the network
|
138
|
+
- `id`: Chain ID
|
139
|
+
- `accounts`: List of account private keys (using environment variables)
|
140
|
+
- Special case for `localnet`:
|
141
|
+
- If a network is named `localnet`, missing fields will be filled with default values
|
142
|
+
- For all other network names, `id`, `url`, and `accounts` are required fields
|
143
|
+
|
144
|
+
2. **Paths**: Define important directory paths
|
145
|
+
- `contracts`: Location of your contract files
|
146
|
+
|
147
|
+
3. **Environment**: Path to your `.env` file containing sensitive information like private keys
|
148
|
+
|
149
|
+
If you don't provide a config file, the suite will use default values. You can override these settings using command-line arguments. For example:
|
150
|
+
```bash
|
151
|
+
# Override the default network
|
152
|
+
gltest --network testnet_asimov
|
153
|
+
|
154
|
+
# Override the contracts directory
|
155
|
+
gltest --contracts-dir custom/contracts/path
|
156
|
+
```
|
157
|
+
|
102
158
|
### Running Tests
|
103
159
|
|
104
160
|
1. Run all tests:
|
@@ -126,17 +182,27 @@ $ gltest -v
|
|
126
182
|
$ gltest --contracts-dir <path_to_contracts>
|
127
183
|
```
|
128
184
|
|
129
|
-
6. Run tests
|
185
|
+
6. Run tests on a specific network:
|
186
|
+
```bash
|
187
|
+
# Run tests on localnet (default)
|
188
|
+
$ gltest --network localnet
|
189
|
+
|
190
|
+
# Run tests on testnet
|
191
|
+
$ gltest --network testnet_asimov
|
192
|
+
```
|
193
|
+
The `--network` flag allows you to specify which network configuration to use from your `gltest.config.yaml`. If not specified, it will use the `default` network defined in your config file.
|
194
|
+
|
195
|
+
7. Run tests with a custom RPC url
|
130
196
|
```bash
|
131
197
|
$ gltest --rpc-url <custom_rpc_url>
|
132
198
|
```
|
133
199
|
|
134
|
-
|
200
|
+
8. Run tests with a default wait interval for waiting transaction receipts
|
135
201
|
```bash
|
136
202
|
$ gltest --default-wait-interval <default_wait_interval>
|
137
203
|
```
|
138
204
|
|
139
|
-
|
205
|
+
9. Run tests with a default wait retries for waiting transaction receipts
|
140
206
|
```bash
|
141
207
|
$ gltest --default-wait-retries <default_wait_retries>
|
142
208
|
```
|
@@ -233,13 +299,14 @@ def test_deployment():
|
|
233
299
|
Reading from the contract is straightforward:
|
234
300
|
|
235
301
|
```python
|
236
|
-
from gltest import get_contract_factory
|
302
|
+
from gltest import get_contract_factory
|
237
303
|
|
238
304
|
def test_read_methods():
|
305
|
+
|
239
306
|
# Get the contract factory and deploy the contract
|
240
307
|
factory = get_contract_factory("Storage")
|
241
|
-
contract = factory.deploy(
|
242
|
-
|
308
|
+
contract = factory.deploy()
|
309
|
+
|
243
310
|
# Call a read-only method
|
244
311
|
result = contract.get_value(args=[])
|
245
312
|
|
@@ -0,0 +1,65 @@
|
|
1
|
+
genlayer_test-0.3.0.dist-info/licenses/LICENSE,sha256=che_H4vE0QUx3HvWrAa1_jDEVInift0U6VO15-QqEls,1064
|
2
|
+
gltest/__init__.py,sha256=Uozr4VS-_oKUxEdXbWoEVLB8JQKBWGs6vGEHDj1-6LY,348
|
3
|
+
gltest/assertions.py,sha256=0dEk0VxcHK4I7GZPHxJmz-2jaA60V499gOSR74rZbfM,1748
|
4
|
+
gltest/exceptions.py,sha256=deJPmrTe5gF33qkkKF2IVJY7lc_knI7Ql3N7jZ8aLZs,510
|
5
|
+
gltest/types.py,sha256=BODmwTr2gAUEiO9FjiuTiWwuKvXgo4xZWstQWNUfnlw,156
|
6
|
+
gltest/artifacts/__init__.py,sha256=qTt3TE19gVNWnQLUlt5aDe4nNvJ2YJ1jzDkMmYIsCG0,194
|
7
|
+
gltest/artifacts/contract.py,sha256=KChpmfjZod_0dVB8y-dvWz6IVm7QlIJsgG2ArtvVDaU,6457
|
8
|
+
gltest/glchain/__init__.py,sha256=QLd55hVB9xVTAtCKbjmGPAwh0M8_tUNJ5xI0H93YyTY,428
|
9
|
+
gltest/glchain/account.py,sha256=HUmWguJMolggQaZNRPw-LGlRlQCjLLdUanKRowMv6pI,812
|
10
|
+
gltest/glchain/client.py,sha256=urRvnLt8GpdCV3yOBSvJNZQzu_TsZr8HqKn14Q2SpIQ,1547
|
11
|
+
gltest/glchain/contract.py,sha256=RFLbEZseWatX0Xvt3-Eo_zOowxLMhukoXjK8V8Ca0Ok,11370
|
12
|
+
gltest/helpers/__init__.py,sha256=I7HiTu_H7_hP65zY6Wl02r-5eAMr2eZvqBVmusuQLX4,180
|
13
|
+
gltest/helpers/fixture_snapshot.py,sha256=VydrtviG60ukSFIvzO5QwK-SHmkRmbsQFEVdyItvGWI,2142
|
14
|
+
gltest/helpers/take_snapshot.py,sha256=eXqEKXM2hcox3pLGIcNddobU8zXPQvD-Iwf87eHqW2s,1276
|
15
|
+
gltest_cli/logging.py,sha256=2Bkh6OR5C19HefARLQN5xBfam3apXzf7_Wei2PBfKlM,1241
|
16
|
+
gltest_cli/main.py,sha256=Ti2-0Ev1x5_cM0D1UKqdgaDt80CDHEQGtdRne2qLm4M,53
|
17
|
+
gltest_cli/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
|
+
gltest_cli/config/constants.py,sha256=lX8C3aS7zXWazA8LWgE0BkPvy7NopyEMyJNI2yYWX9M,300
|
19
|
+
gltest_cli/config/general.py,sha256=ezpoGsT8grO9zQH6RugV14b1GzeFt-htYToHQBJhNvY,186
|
20
|
+
gltest_cli/config/plugin.py,sha256=zEWsi18hEoK9yloKKPd8y77wXCpgWf7hAWI1JL8S5Ho,3325
|
21
|
+
gltest_cli/config/types.py,sha256=R5ylpHKzoOK43_tXC047mJqAybCZhj615_FWBhsmNAU,5237
|
22
|
+
gltest_cli/config/user.py,sha256=LjjoqXWRLPeNgOvLKy2tJDNl1M0uLb-5rwEsnGyJunE,8065
|
23
|
+
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
|
+
tests/conftest.py,sha256=RKdoE5_zcMimeojAoA_GSFI9du4pMzMi1vZ1njtfoAs,28
|
25
|
+
tests/examples/contracts/football_prediction_market.py,sha256=kdouFijjeCdIJyaVJlgXcqbBAXecA9_YdhklSsIW-QM,3219
|
26
|
+
tests/examples/contracts/intelligent_oracle.py,sha256=WrNZWWoi1sz22Azt2EXgdWHDg5Ihca2pWUHrM9pVfQE,12319
|
27
|
+
tests/examples/contracts/intelligent_oracle_factory.py,sha256=ax496IZuDCA728rRcbjwTaM4Q4E-Y1jGkHsEcyf1cig,1490
|
28
|
+
tests/examples/contracts/llm_erc20.py,sha256=nfIs-7A79L46NgHQzWbPyEOUlzAlFLsf4K05acwKr_M,2523
|
29
|
+
tests/examples/contracts/log_indexer.py,sha256=VwMC8_Gy1Z1qjuy5GeEMyepjZ3Z5y7VAOrHMl5MrjxI,1852
|
30
|
+
tests/examples/contracts/multi_read_erc20.py,sha256=HsMJKGT9a9eZAO43Em7hCRfh1yyHDgcUbQ0gmOE1MXs,850
|
31
|
+
tests/examples/contracts/multi_tenant_storage.py,sha256=aGLPC76FegXdnIjMjeGsu3s3AbKK9dtV6t1d_KoI8rI,1897
|
32
|
+
tests/examples/contracts/read_erc20.py,sha256=kstiB93JHHajJe1GldzeawxnVYutjT8KE2d1bYTgggU,390
|
33
|
+
tests/examples/contracts/storage.py,sha256=GZHBXhjc94eEkdSO1UWgcop0fEo0hD57KZM0ds3pUFM,490
|
34
|
+
tests/examples/contracts/user_storage.py,sha256=j-RXxTIqb1dePYqP_pkeoCxxDq07VURryvzF_Q-sZmI,638
|
35
|
+
tests/examples/contracts/wizard_of_coin.py,sha256=BJ0Nv6N-JJP_Pk7YUSXPPRxX5_mDRBDlfL6nabeaoyA,1606
|
36
|
+
tests/examples/contracts/multi_file_contract/__init__.py,sha256=8O3BvoUrLSmc4uTf2jm7MyrmcaiGD0w8wPwotdAqZHQ,485
|
37
|
+
tests/examples/contracts/multi_file_contract/other.py,sha256=jHDtjUL3eAUgE6yOYKFw_RfAH7kIwk8CvxUjbWHNruk,236
|
38
|
+
tests/examples/tests/test_football_prediction_market.py,sha256=wFu024sq3IURLL1zyLyO_G1sRCjPTV7iImi87__dZ4Y,657
|
39
|
+
tests/examples/tests/test_intelligent_oracle_factory.py,sha256=Nw7jO9bjD79AETT2QQl0Vun-yxSAAuqGSdkQn2Y3WUw,5377
|
40
|
+
tests/examples/tests/test_llm_erc20.py,sha256=3-wsZi23TpQ_9HYPfcbyo9206AkDndqTfBzRWXzlsNE,1400
|
41
|
+
tests/examples/tests/test_log_indexer.py,sha256=Km44SiA8dlA4WBqwugXVBCQUlODdf1dB4p4nt24HG9k,2649
|
42
|
+
tests/examples/tests/test_multi_file_contract.py,sha256=pWmK6lcZrSAnDH09Z6Q-cXs8V6VGFhHkvgThvJKEB4U,512
|
43
|
+
tests/examples/tests/test_multi_file_contract_legacy.py,sha256=Jx_u0rDrQJspQgFo1KUddcFgTcOhcE-YLuLgk3tKrCA,527
|
44
|
+
tests/examples/tests/test_multi_read_erc20.py,sha256=A-mRoZPj3_0B6CUnwtPFxtXoOfd1RuB8PIeExniZlCs,3411
|
45
|
+
tests/examples/tests/test_multi_tenant_storage.py,sha256=yliqhit7wWO1Y6OXl_cv3ruTCOto8ZfKGtkT3lRvZpQ,2717
|
46
|
+
tests/examples/tests/test_read_erc20.py,sha256=9bUmigPab2dDf1GElRXVbf1TVbMur37IPT7HFZDmFUg,1208
|
47
|
+
tests/examples/tests/test_storage.py,sha256=jcVNAeBynn70Ov1rF1robZwFZptuNLtHW-u1XfG393k,712
|
48
|
+
tests/examples/tests/test_storage_legacy.py,sha256=RNVnD0G9ilb4I2s0CPAAgJEuKUgEkkbItuesOfmv-pg,677
|
49
|
+
tests/examples/tests/test_user_storage.py,sha256=qUv57rn1X3wAiIglnj3LH3r2clIBwF38MMkKvU4IGaA,2552
|
50
|
+
tests/examples/tests/test_wizard_of_coin.py,sha256=aUDeV5w0XONMMS71Vzw80lHfcSM0z8RKPJSXAuDwRto,392
|
51
|
+
tests/gltest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
52
|
+
tests/gltest/artifact/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
53
|
+
tests/gltest/artifact/test_contract_definition.py,sha256=6R8THNFKKpG7brULzp63vT1_pPd_JFNp3ZS08CJJWrg,3642
|
54
|
+
tests/gltest/artifact/contracts/duplicate_ic_contract_1.py,sha256=bSWsUVjBy5cGtI72cjnkstsMzuUJbB3IG5JjTxOF-dc,500
|
55
|
+
tests/gltest/artifact/contracts/duplicate_ic_contract_2.py,sha256=bSWsUVjBy5cGtI72cjnkstsMzuUJbB3IG5JjTxOF-dc,500
|
56
|
+
tests/gltest/artifact/contracts/not_ic_contract.py,sha256=hQyGnYiiVceYdLI2WrvcFgPqzy1S4-YMb9FPhiHEGSA,510
|
57
|
+
tests/gltest/assertions/test_assertions.py,sha256=qzVrOdOM4xYtIy1sFHVAD_-naDHOequ23tEN0MELh0k,10781
|
58
|
+
tests/gltest_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
59
|
+
tests/gltest_cli/config/test_plugin.py,sha256=06-GENVugrL6mPQkgRgQqRsCTuQMy3WZcbh_9Du6zHo,3502
|
60
|
+
tests/gltest_cli/config/test_user.py,sha256=oJDcM6NbA16tQzQj5s8ZDvQYBm2uuvar5junFcVeitY,12116
|
61
|
+
genlayer_test-0.3.0.dist-info/METADATA,sha256=daKEgnpolSsdJRa4yvqPIiciVNKGKePFWT2H-o-fLiQ,17231
|
62
|
+
genlayer_test-0.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
63
|
+
genlayer_test-0.3.0.dist-info/entry_points.txt,sha256=RWPcSArBpz_G4BYioh5L8Q8hyClRbSgzLimjcWMp-BQ,94
|
64
|
+
genlayer_test-0.3.0.dist-info/top_level.txt,sha256=-qiGZxTRBytujzgVcKpxjvQ-WNeUDjXa59ceGMwMpko,24
|
65
|
+
genlayer_test-0.3.0.dist-info/RECORD,,
|
gltest/__init__.py
CHANGED
@@ -3,8 +3,8 @@ from gltest.glchain import (
|
|
3
3
|
create_accounts,
|
4
4
|
get_contract_factory,
|
5
5
|
get_gl_client,
|
6
|
-
|
7
|
-
|
6
|
+
get_accounts,
|
7
|
+
get_default_account,
|
8
8
|
)
|
9
9
|
|
10
10
|
__all__ = [
|
@@ -13,6 +13,6 @@ __all__ = [
|
|
13
13
|
"create_accounts",
|
14
14
|
"get_contract_factory",
|
15
15
|
"get_gl_client",
|
16
|
-
"
|
17
|
-
"
|
16
|
+
"get_accounts",
|
17
|
+
"get_default_account",
|
18
18
|
]
|
gltest/artifacts/contract.py
CHANGED
@@ -2,7 +2,7 @@ import ast
|
|
2
2
|
from typing import Optional
|
3
3
|
from dataclasses import dataclass
|
4
4
|
from pathlib import Path
|
5
|
-
from
|
5
|
+
from gltest_cli.config.general import get_general_config
|
6
6
|
import io
|
7
7
|
import zipfile
|
8
8
|
from typing import Union
|
@@ -21,9 +21,12 @@ class ContractDefinition:
|
|
21
21
|
def search_path_by_class_name(contracts_dir: Path, contract_name: str) -> Path:
|
22
22
|
"""Search for a file by class name in the contracts directory."""
|
23
23
|
matching_files = []
|
24
|
+
exclude_dirs = {".venv", "venv", "env", "build", "dist", "__pycache__", ".git"}
|
24
25
|
|
25
26
|
for file_path in contracts_dir.rglob("*"):
|
26
|
-
if
|
27
|
+
if any(exclude_dir in file_path.parts for exclude_dir in exclude_dirs):
|
28
|
+
continue
|
29
|
+
if file_path.suffix not in [".gpy", ".py"]:
|
27
30
|
continue
|
28
31
|
try:
|
29
32
|
# Read the file content
|
@@ -142,7 +145,8 @@ def find_contract_definition_from_name(
|
|
142
145
|
"""
|
143
146
|
Search in the contracts directory for a contract definition.
|
144
147
|
"""
|
145
|
-
|
148
|
+
general_config = get_general_config()
|
149
|
+
contracts_dir = general_config.get_contracts_dir()
|
146
150
|
if not contracts_dir.exists():
|
147
151
|
raise FileNotFoundError(f"Contracts directory not found at: {contracts_dir}")
|
148
152
|
|
@@ -156,7 +160,8 @@ def find_contract_definition_from_path(
|
|
156
160
|
"""
|
157
161
|
Create a ContractDefinition from a given file path relative to the contracts directory.
|
158
162
|
"""
|
159
|
-
|
163
|
+
general_config = get_general_config()
|
164
|
+
contracts_dir = general_config.get_contracts_dir()
|
160
165
|
if not contracts_dir.exists():
|
161
166
|
raise FileNotFoundError(f"Contracts directory not found at: {contracts_dir}")
|
162
167
|
|
gltest/glchain/__init__.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from .contract import Contract, ContractFactory, get_contract_factory
|
2
2
|
from .client import get_gl_client, get_gl_provider
|
3
|
-
from .account import
|
3
|
+
from .account import create_account, get_accounts, get_default_account, create_accounts
|
4
4
|
|
5
5
|
|
6
6
|
__all__ = [
|
@@ -8,9 +8,9 @@ __all__ = [
|
|
8
8
|
"ContractFactory",
|
9
9
|
"get_contract_factory",
|
10
10
|
"create_account",
|
11
|
-
"default_account",
|
12
|
-
"accounts",
|
13
11
|
"create_accounts",
|
12
|
+
"get_accounts",
|
13
|
+
"get_default_account",
|
14
14
|
"get_gl_client",
|
15
15
|
"get_gl_provider",
|
16
16
|
]
|
gltest/glchain/account.py
CHANGED
@@ -1,18 +1,22 @@
|
|
1
|
+
from gltest_cli.config.general import get_general_config
|
1
2
|
from genlayer_py import create_account
|
3
|
+
from eth_account.signers.local import LocalAccount
|
4
|
+
from typing import List
|
2
5
|
|
3
6
|
|
4
7
|
def create_accounts(n_accounts: int):
|
5
|
-
|
6
|
-
Create a list of accounts
|
7
|
-
"""
|
8
|
-
accounts = []
|
9
|
-
for _ in range(n_accounts):
|
10
|
-
accounts.append(create_account())
|
11
|
-
return accounts
|
8
|
+
return [create_account() for _ in range(n_accounts)]
|
12
9
|
|
13
10
|
|
14
|
-
|
15
|
-
|
11
|
+
def get_accounts() -> List[LocalAccount]:
|
12
|
+
general_config = get_general_config()
|
13
|
+
selected_network = general_config.get_network_name()
|
14
|
+
accounts = general_config.get_accounts_keys(selected_network)
|
15
|
+
return [create_account(account) for account in accounts]
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
|
18
|
+
def get_default_account() -> LocalAccount:
|
19
|
+
general_config = get_general_config()
|
20
|
+
selected_network = general_config.get_network_name()
|
21
|
+
default_account_key = general_config.get_default_account_key(selected_network)
|
22
|
+
return create_account(default_account_key)
|
gltest/glchain/client.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
from genlayer_py.chains import localnet
|
2
2
|
from genlayer_py import create_client
|
3
|
-
from .account import
|
3
|
+
from .account import get_default_account
|
4
4
|
from functools import lru_cache
|
5
|
-
from
|
5
|
+
from gltest_cli.config.general import get_general_config
|
6
6
|
|
7
7
|
|
8
8
|
@lru_cache(maxsize=1)
|
@@ -10,8 +10,44 @@ def get_gl_client():
|
|
10
10
|
"""
|
11
11
|
Get the GenLayer client instance.
|
12
12
|
"""
|
13
|
+
general_config = get_general_config()
|
14
|
+
chain = general_config.get_chain()
|
15
|
+
default_account = get_default_account()
|
16
|
+
endpoint = general_config.get_rpc_url()
|
13
17
|
return create_client(
|
14
|
-
chain=
|
18
|
+
chain=chain,
|
19
|
+
account=default_account,
|
20
|
+
endpoint=endpoint,
|
21
|
+
)
|
22
|
+
|
23
|
+
|
24
|
+
@lru_cache(maxsize=1)
|
25
|
+
def get_gl_hosted_studio_client():
|
26
|
+
"""
|
27
|
+
Get the GenLayer hosted studio client instance.
|
28
|
+
|
29
|
+
Note: This is a temporary solution to get contract schema.
|
30
|
+
TODO: Remove this once we have a proper way to get contract schema from testnet.
|
31
|
+
"""
|
32
|
+
return create_client(
|
33
|
+
chain=localnet,
|
34
|
+
account=get_default_account(),
|
35
|
+
endpoint="https://studio.genlayer.com/api",
|
36
|
+
)
|
37
|
+
|
38
|
+
|
39
|
+
@lru_cache(maxsize=1)
|
40
|
+
def get_local_client():
|
41
|
+
"""
|
42
|
+
Get the GenLayer local client instance.
|
43
|
+
|
44
|
+
Note: This is a temporary solution to get contract schema.
|
45
|
+
TODO: Remove this once we have a proper way to get contract schema from testnet.
|
46
|
+
"""
|
47
|
+
return create_client(
|
48
|
+
chain=localnet,
|
49
|
+
account=get_default_account(),
|
50
|
+
endpoint="http://127.0.0.1:4000/api",
|
15
51
|
)
|
16
52
|
|
17
53
|
|
gltest/glchain/contract.py
CHANGED
@@ -12,11 +12,12 @@ from gltest.artifacts import (
|
|
12
12
|
)
|
13
13
|
from gltest.assertions import tx_execution_failed
|
14
14
|
from gltest.exceptions import DeploymentError
|
15
|
-
from .client import get_gl_client
|
15
|
+
from .client import get_gl_client, get_gl_hosted_studio_client, get_local_client
|
16
16
|
from gltest.types import CalldataEncodable, GenLayerTransaction, TransactionStatus
|
17
17
|
from typing import List, Any, Type, Optional, Dict, Callable
|
18
18
|
import types
|
19
|
-
from
|
19
|
+
from gltest_cli.config.general import get_general_config
|
20
|
+
from gltest_cli.logging import logger
|
20
21
|
|
21
22
|
|
22
23
|
@dataclass
|
@@ -101,15 +102,16 @@ class Contract:
|
|
101
102
|
wait_interval: Optional[int] = None,
|
102
103
|
wait_retries: Optional[int] = None,
|
103
104
|
wait_triggered_transactions: bool = True,
|
104
|
-
wait_triggered_transactions_status: TransactionStatus = TransactionStatus.
|
105
|
+
wait_triggered_transactions_status: TransactionStatus = TransactionStatus.FINALIZED,
|
105
106
|
) -> GenLayerTransaction:
|
106
107
|
"""
|
107
108
|
Wrapper to the contract write method.
|
108
109
|
"""
|
110
|
+
general_config = get_general_config()
|
109
111
|
if wait_interval is None:
|
110
|
-
wait_interval = get_default_wait_interval()
|
112
|
+
wait_interval = general_config.get_default_wait_interval()
|
111
113
|
if wait_retries is None:
|
112
|
-
wait_retries = get_default_wait_retries()
|
114
|
+
wait_retries = general_config.get_default_wait_retries()
|
113
115
|
client = get_gl_client()
|
114
116
|
tx_hash = client.write_contract(
|
115
117
|
address=self.address,
|
@@ -178,6 +180,31 @@ class ContractFactory:
|
|
178
180
|
contract_code=contract_info.contract_code,
|
179
181
|
)
|
180
182
|
|
183
|
+
def _get_schema_with_fallback(self):
|
184
|
+
"""Attempts to get the contract schema using multiple clients in a fallback pattern.
|
185
|
+
|
186
|
+
This method tries to get the contract schema in the following order:
|
187
|
+
1. Hosted studio client
|
188
|
+
2. Local client
|
189
|
+
3. Regular client
|
190
|
+
|
191
|
+
Returns:
|
192
|
+
Optional[Dict[str, Any]]: The contract schema if successful, None if all attempts fail.
|
193
|
+
"""
|
194
|
+
clients = (
|
195
|
+
("hosted studio", get_gl_hosted_studio_client()),
|
196
|
+
("local", get_local_client()),
|
197
|
+
("default", get_gl_client()),
|
198
|
+
)
|
199
|
+
for label, client in clients:
|
200
|
+
try:
|
201
|
+
return client.get_contract_schema_for_code(
|
202
|
+
contract_code=self.contract_code
|
203
|
+
)
|
204
|
+
except Exception as e:
|
205
|
+
logger.warning("Schema fetch via %s client failed: %s", label, e)
|
206
|
+
return None
|
207
|
+
|
181
208
|
def build_contract(
|
182
209
|
self,
|
183
210
|
contract_address: Union[Address, ChecksumAddress],
|
@@ -186,16 +213,13 @@ class ContractFactory:
|
|
186
213
|
"""
|
187
214
|
Build contract from address
|
188
215
|
"""
|
189
|
-
|
190
|
-
|
191
|
-
schema = client.get_contract_schema(address=contract_address)
|
192
|
-
return Contract.new(
|
193
|
-
address=contract_address, schema=schema, account=account
|
194
|
-
)
|
195
|
-
except Exception as e:
|
216
|
+
schema = self._get_schema_with_fallback()
|
217
|
+
if schema is None:
|
196
218
|
raise ValueError(
|
197
|
-
|
198
|
-
)
|
219
|
+
"Failed to get schema from all clients (hosted studio, local, and regular)"
|
220
|
+
)
|
221
|
+
|
222
|
+
return Contract.new(address=contract_address, schema=schema, account=account)
|
199
223
|
|
200
224
|
def deploy(
|
201
225
|
self,
|
@@ -210,10 +234,12 @@ class ContractFactory:
|
|
210
234
|
"""
|
211
235
|
Deploy the contract
|
212
236
|
"""
|
237
|
+
general_config = get_general_config()
|
213
238
|
if wait_interval is None:
|
214
|
-
wait_interval = get_default_wait_interval()
|
239
|
+
wait_interval = general_config.get_default_wait_interval()
|
215
240
|
if wait_retries is None:
|
216
|
-
wait_retries = get_default_wait_retries()
|
241
|
+
wait_retries = general_config.get_default_wait_retries()
|
242
|
+
|
217
243
|
client = get_gl_client()
|
218
244
|
try:
|
219
245
|
tx_hash = client.deploy_contract(
|
@@ -229,22 +255,27 @@ class ContractFactory:
|
|
229
255
|
interval=wait_interval,
|
230
256
|
retries=wait_retries,
|
231
257
|
)
|
232
|
-
if (
|
233
|
-
not tx_receipt
|
234
|
-
or "data" not in tx_receipt
|
235
|
-
or "contract_address" not in tx_receipt["data"]
|
236
|
-
):
|
258
|
+
if tx_execution_failed(tx_receipt):
|
237
259
|
raise ValueError(
|
238
|
-
"
|
260
|
+
f"Deployment transaction finalized with error: {tx_receipt}"
|
239
261
|
)
|
240
262
|
|
241
|
-
if
|
263
|
+
if (
|
264
|
+
"tx_data_decoded" in tx_receipt
|
265
|
+
and "contract_address" in tx_receipt["tx_data_decoded"]
|
266
|
+
):
|
267
|
+
contract_address = tx_receipt["tx_data_decoded"]["contract_address"]
|
268
|
+
elif "data" in tx_receipt and "contract_address" in tx_receipt["data"]:
|
269
|
+
contract_address = tx_receipt["data"]["contract_address"]
|
270
|
+
else:
|
271
|
+
raise ValueError("Transaction receipt missing contract address")
|
272
|
+
|
273
|
+
schema = self._get_schema_with_fallback()
|
274
|
+
if schema is None:
|
242
275
|
raise ValueError(
|
243
|
-
|
276
|
+
"Failed to get schema from all clients (hosted studio, local, and regular)"
|
244
277
|
)
|
245
278
|
|
246
|
-
contract_address = tx_receipt["data"]["contract_address"]
|
247
|
-
schema = client.get_contract_schema(address=contract_address)
|
248
279
|
return Contract.new(
|
249
280
|
address=contract_address, schema=schema, account=account
|
250
281
|
)
|
@@ -7,7 +7,7 @@ from gltest.exceptions import (
|
|
7
7
|
InvalidSnapshotError,
|
8
8
|
FixtureAnonymousFunctionError,
|
9
9
|
)
|
10
|
-
from
|
10
|
+
from gltest_cli.config.general import get_general_config
|
11
11
|
|
12
12
|
SUPPORTED_RPC_DOMAINS = ["localhost", "127.0.0.1"]
|
13
13
|
|
@@ -34,7 +34,8 @@ def load_fixture(fixture: Callable[[], T]) -> T:
|
|
34
34
|
if fixture.__name__ == "<lambda>":
|
35
35
|
raise FixtureAnonymousFunctionError("Fixtures must be named functions")
|
36
36
|
|
37
|
-
|
37
|
+
general_config = get_general_config()
|
38
|
+
rpc_url = general_config.get_rpc_url()
|
38
39
|
domain = urlparse(rpc_url).netloc.split(":")[0] # Extract domain without port
|
39
40
|
if domain not in SUPPORTED_RPC_DOMAINS:
|
40
41
|
return fixture()
|
File without changes
|
@@ -0,0 +1,10 @@
|
|
1
|
+
from genlayer_py.chains.localnet import SIMULATOR_JSON_RPC_URL
|
2
|
+
from pathlib import Path
|
3
|
+
|
4
|
+
|
5
|
+
GLTEST_CONFIG_FILE = "gltest.config.yaml"
|
6
|
+
DEFAULT_NETWORK = "localnet"
|
7
|
+
DEFAULT_RPC_URL = SIMULATOR_JSON_RPC_URL
|
8
|
+
DEFAULT_ENVIRONMENT = ".env"
|
9
|
+
DEFAULT_CONTRACTS_DIR = Path("contracts")
|
10
|
+
DEFAULT_NETWORK_ID = 61999
|