genlayer-test 0.1.3__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.
Files changed (43) hide show
  1. {genlayer_test-0.1.3.dist-info → genlayer_test-0.3.0.dist-info}/METADATA +77 -10
  2. genlayer_test-0.3.0.dist-info/RECORD +65 -0
  3. {genlayer_test-0.1.3.dist-info → genlayer_test-0.3.0.dist-info}/entry_points.txt +1 -1
  4. gltest/__init__.py +4 -4
  5. gltest/artifacts/__init__.py +5 -2
  6. gltest/artifacts/contract.py +94 -14
  7. gltest/glchain/__init__.py +3 -3
  8. gltest/glchain/account.py +15 -11
  9. gltest/glchain/client.py +39 -3
  10. gltest/glchain/contract.py +98 -31
  11. gltest/helpers/fixture_snapshot.py +3 -2
  12. gltest_cli/config/__init__.py +0 -0
  13. gltest_cli/config/constants.py +10 -0
  14. gltest_cli/config/general.py +10 -0
  15. gltest_cli/config/plugin.py +102 -0
  16. gltest_cli/config/types.py +137 -0
  17. gltest_cli/config/user.py +222 -0
  18. gltest_cli/logging.py +51 -0
  19. tests/__init__.py +0 -0
  20. tests/examples/tests/test_llm_erc20.py +2 -2
  21. tests/examples/tests/test_multi_read_erc20.py +13 -3
  22. tests/examples/tests/test_multi_tenant_storage.py +12 -3
  23. tests/examples/tests/test_read_erc20.py +2 -2
  24. tests/examples/tests/test_storage.py +4 -2
  25. tests/examples/tests/test_user_storage.py +17 -3
  26. tests/gltest/__init__.py +0 -0
  27. tests/gltest/artifact/__init__.py +0 -0
  28. tests/gltest/artifact/contracts/duplicate_ic_contract_1.py +22 -0
  29. tests/gltest/artifact/contracts/duplicate_ic_contract_2.py +22 -0
  30. tests/{artifact → gltest/artifact}/test_contract_definition.py +29 -30
  31. tests/gltest_cli/__init__.py +0 -0
  32. tests/gltest_cli/config/test_plugin.py +127 -0
  33. tests/gltest_cli/config/test_user.py +351 -0
  34. genlayer_test-0.1.3.dist-info/RECORD +0 -53
  35. gltest/plugin_config.py +0 -42
  36. gltest/plugin_hooks.py +0 -51
  37. tests/plugin/test_plugin_hooks.py +0 -78
  38. {genlayer_test-0.1.3.dist-info → genlayer_test-0.3.0.dist-info}/WHEEL +0 -0
  39. {genlayer_test-0.1.3.dist-info → genlayer_test-0.3.0.dist-info}/licenses/LICENSE +0 -0
  40. {genlayer_test-0.1.3.dist-info → genlayer_test-0.3.0.dist-info}/top_level.txt +0 -0
  41. /tests/{plugin/conftest.py → conftest.py} +0 -0
  42. /tests/{artifact → gltest/artifact}/contracts/not_ic_contract.py +0 -0
  43. /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.1.3
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: genlayer-py==0.3.0
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, default_account, create_account
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 == default_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 with a custom RPC url
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
- 6. Run tests with a default wait interval for waiting transaction receipts
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
- 6. Run tests with a default wait retries for waiting transaction receipts
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, default_account
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(account=default_account)
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,,
@@ -2,4 +2,4 @@
2
2
  gltest = gltest_cli.main:main
3
3
 
4
4
  [pytest11]
5
- gltest = gltest.plugin_hooks
5
+ gltest = gltest_cli.config.plugin
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
- default_account,
7
- accounts,
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
- "default_account",
17
- "accounts",
16
+ "get_accounts",
17
+ "get_default_account",
18
18
  ]
@@ -1,3 +1,6 @@
1
- from .contract import find_contract_definition
1
+ from .contract import (
2
+ find_contract_definition_from_name,
3
+ find_contract_definition_from_path,
4
+ )
2
5
 
3
- __all__ = ["find_contract_definition"]
6
+ __all__ = ["find_contract_definition_from_name", "find_contract_definition_from_path"]
@@ -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 gltest.plugin_config import get_contracts_dir
5
+ from gltest_cli.config.general import get_general_config
6
6
  import io
7
7
  import zipfile
8
8
  from typing import Union
@@ -20,8 +20,13 @@ class ContractDefinition:
20
20
 
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
+ matching_files = []
24
+ exclude_dirs = {".venv", "venv", "env", "build", "dist", "__pycache__", ".git"}
25
+
23
26
  for file_path in contracts_dir.rglob("*"):
24
- if not file_path.suffix in [".gpy", ".py"]:
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"]:
25
30
  continue
26
31
  try:
27
32
  # Read the file content
@@ -40,10 +45,24 @@ def search_path_by_class_name(contracts_dir: Path, contract_name: str) -> Path:
40
45
  and base.value.id == "gl"
41
46
  and base.attr == "Contract"
42
47
  ):
43
- return file_path
48
+ matching_files.append(file_path)
49
+ break
50
+ break
44
51
  except Exception as e:
45
- raise ValueError(f"Error reading file {file_path}: {e}")
46
- raise FileNotFoundError(f"Contract {contract_name} not found at: {contracts_dir}")
52
+ raise ValueError(f"Error reading file {file_path}: {e}") from e
53
+
54
+ if len(matching_files) == 0:
55
+ raise FileNotFoundError(
56
+ f"Contract {contract_name} not found at: {contracts_dir}"
57
+ )
58
+ if len(matching_files) > 1:
59
+ file_paths_str = ", ".join(str(f) for f in matching_files)
60
+ raise ValueError(
61
+ f"Multiple contracts named '{contract_name}' found in contracts directory. "
62
+ f"Found in files: {file_paths_str}. Please ensure contract names are unique."
63
+ ) from None
64
+
65
+ return matching_files[0]
47
66
 
48
67
 
49
68
  def compute_contract_code(
@@ -71,14 +90,35 @@ def compute_contract_code(
71
90
  return buffer.getvalue()
72
91
 
73
92
 
74
- def find_contract_definition(contract_name: str) -> Optional[ContractDefinition]:
75
- """
76
- Search in the contracts directory for a contract definition.
77
- """
78
- contracts_dir = get_contracts_dir()
79
- if not contracts_dir.exists():
80
- raise FileNotFoundError(f"Contracts directory not found at: {contracts_dir}")
81
- main_file_path = search_path_by_class_name(contracts_dir, contract_name)
93
+ def _extract_contract_name_from_file(file_path: Path) -> str:
94
+ """Extract contract name from a file by parsing the AST."""
95
+ try:
96
+ with open(file_path, "r") as f:
97
+ content = f.read()
98
+ tree = ast.parse(content)
99
+
100
+ # Search for class definitions that inherit from gl.Contract
101
+ for node in ast.walk(tree):
102
+ if isinstance(node, ast.ClassDef):
103
+ for base in node.bases:
104
+ if (
105
+ isinstance(base, ast.Attribute)
106
+ and isinstance(base.value, ast.Name)
107
+ and base.value.id == "gl"
108
+ and base.attr == "Contract"
109
+ ):
110
+ return node.name
111
+ except Exception as e:
112
+ raise ValueError(f"Error parsing contract file {file_path}: {e}") from e
113
+
114
+ raise ValueError(f"No valid contract class found in {file_path}")
115
+
116
+
117
+ def _create_contract_definition(
118
+ main_file_path: Path, contract_name: str
119
+ ) -> ContractDefinition:
120
+ """Create a ContractDefinition from a main file path and contract name."""
121
+ # Determine if it's a multifile contract
82
122
  main_file_dir = main_file_path.parent
83
123
  runner_file_path = None
84
124
  if main_file_path.name in ["__init__.py", "__init__.gpy"]:
@@ -87,9 +127,49 @@ def find_contract_definition(contract_name: str) -> Optional[ContractDefinition]
87
127
  if not runner_file_path.exists():
88
128
  # No runner file, so it's a single file contract
89
129
  runner_file_path = None
130
+
131
+ # Compute contract code
132
+ contract_code = compute_contract_code(main_file_path, runner_file_path)
133
+
90
134
  return ContractDefinition(
91
135
  contract_name=contract_name,
92
- contract_code=compute_contract_code(main_file_path, runner_file_path),
136
+ contract_code=contract_code,
93
137
  main_file_path=main_file_path,
94
138
  runner_file_path=runner_file_path,
95
139
  )
140
+
141
+
142
+ def find_contract_definition_from_name(
143
+ contract_name: str,
144
+ ) -> Optional[ContractDefinition]:
145
+ """
146
+ Search in the contracts directory for a contract definition.
147
+ """
148
+ general_config = get_general_config()
149
+ contracts_dir = general_config.get_contracts_dir()
150
+ if not contracts_dir.exists():
151
+ raise FileNotFoundError(f"Contracts directory not found at: {contracts_dir}")
152
+
153
+ main_file_path = search_path_by_class_name(contracts_dir, contract_name)
154
+ return _create_contract_definition(main_file_path, contract_name)
155
+
156
+
157
+ def find_contract_definition_from_path(
158
+ contract_file_path: Union[str, Path],
159
+ ) -> ContractDefinition:
160
+ """
161
+ Create a ContractDefinition from a given file path relative to the contracts directory.
162
+ """
163
+ general_config = get_general_config()
164
+ contracts_dir = general_config.get_contracts_dir()
165
+ if not contracts_dir.exists():
166
+ raise FileNotFoundError(f"Contracts directory not found at: {contracts_dir}")
167
+
168
+ # Resolve the file path relative to contracts directory
169
+ main_file_path = contracts_dir / contract_file_path
170
+ if not main_file_path.exists():
171
+ raise FileNotFoundError(f"Contract file not found at: {main_file_path}")
172
+
173
+ contract_name = _extract_contract_name_from_file(main_file_path)
174
+
175
+ return _create_contract_definition(main_file_path, contract_name)
@@ -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 create_accounts, create_account, accounts, default_account
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
- # Accounts for testing
15
- accounts = create_accounts(n_accounts=10)
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
- # Default account to use for transaction handling, if not specified
18
- default_account = accounts[0]
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 default_account
3
+ from .account import get_default_account
4
4
  from functools import lru_cache
5
- from gltest.plugin_config import get_rpc_url
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=localnet, account=default_account, endpoint=get_rpc_url()
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