genlayer-test 0.3.1__py3-none-any.whl → 0.4.1__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 (39) hide show
  1. {genlayer_test-0.3.1.dist-info → genlayer_test-0.4.1.dist-info}/METADATA +124 -4
  2. genlayer_test-0.4.1.dist-info/RECORD +67 -0
  3. gltest/fixtures.py +91 -0
  4. gltest/glchain/contract.py +1 -1
  5. gltest/helpers/fixture_snapshot.py +1 -6
  6. gltest/logging.py +17 -0
  7. gltest_cli/config/plugin.py +13 -0
  8. gltest_cli/config/types.py +11 -0
  9. gltest_cli/logging.py +1 -1
  10. tests/examples/contracts/football_prediction_market.py +11 -8
  11. tests/examples/contracts/intelligent_oracle.py +7 -6
  12. tests/examples/contracts/intelligent_oracle_factory.py +1 -0
  13. tests/examples/contracts/llm_erc20.py +3 -2
  14. tests/examples/contracts/log_indexer.py +7 -5
  15. tests/examples/contracts/multi_file_contract/__init__.py +5 -2
  16. tests/examples/contracts/multi_read_erc20.py +2 -1
  17. tests/examples/contracts/multi_tenant_storage.py +3 -2
  18. tests/examples/contracts/read_erc20.py +6 -1
  19. tests/examples/contracts/storage.py +2 -1
  20. tests/examples/contracts/user_storage.py +2 -1
  21. tests/examples/contracts/wizard_of_coin.py +4 -3
  22. tests/examples/tests/test_football_prediction_market.py +20 -1
  23. tests/examples/tests/test_intelligent_oracle_factory.py +62 -9
  24. tests/examples/tests/test_llm_erc20.py +20 -1
  25. tests/examples/tests/test_log_indexer.py +2 -1
  26. tests/examples/tests/test_multi_file_contract.py +2 -1
  27. tests/examples/tests/test_multi_file_contract_legacy.py +2 -1
  28. tests/examples/tests/test_multi_read_erc20.py +9 -3
  29. tests/examples/tests/test_multi_tenant_storage.py +2 -1
  30. tests/examples/tests/test_read_erc20.py +2 -1
  31. tests/examples/tests/test_storage.py +2 -1
  32. tests/examples/tests/test_storage_legacy.py +2 -1
  33. tests/examples/tests/test_user_storage.py +9 -3
  34. tests/examples/tests/test_wizard_of_coin.py +16 -1
  35. genlayer_test-0.3.1.dist-info/RECORD +0 -65
  36. {genlayer_test-0.3.1.dist-info → genlayer_test-0.4.1.dist-info}/WHEEL +0 -0
  37. {genlayer_test-0.3.1.dist-info → genlayer_test-0.4.1.dist-info}/entry_points.txt +0 -0
  38. {genlayer_test-0.3.1.dist-info → genlayer_test-0.4.1.dist-info}/licenses/LICENSE +0 -0
  39. {genlayer_test-0.3.1.dist-info → genlayer_test-0.4.1.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: genlayer-test
3
- Version: 0.3.1
3
+ Version: 0.4.1
4
4
  Summary: GenLayer Testing Suite
5
5
  Author: GenLayer
6
6
  License-Expression: MIT
@@ -50,7 +50,7 @@ from gltest.assertions import tx_execution_succeeded
50
50
 
51
51
  factory = get_contract_factory("MyContract")
52
52
  # Deploy a contract with default account
53
- contract = factory.deploy() # This will be deployed with default_account
53
+ contract = factory.deploy() # This will be deployed with the default account
54
54
  assert contract.account == get_default_account()
55
55
 
56
56
  # Deploy a contract with other account
@@ -207,6 +207,30 @@ $ gltest --default-wait-interval <default_wait_interval>
207
207
  $ gltest --default-wait-retries <default_wait_retries>
208
208
  ```
209
209
 
210
+ 10. Run tests with mocked LLM responses (localnet only)
211
+ ```bash
212
+ $ gltest --test-with-mocks
213
+ ```
214
+ The `--test-with-mocks` flag enables mocking of LLM responses when creating validators. This is particularly useful for:
215
+ - Testing without actual LLM API calls
216
+ - Ensuring deterministic test results
217
+ - Faster test execution
218
+ - Testing specific edge cases with controlled responses
219
+
220
+ When using this flag with the `setup_validators` fixture, you can provide custom mock responses:
221
+ ```python
222
+ def test_with_mocked_llm(setup_validators):
223
+ # Setup validators with a specific mock response
224
+ mock_response = {"result": "This is a mocked LLM response"}
225
+ setup_validators(mock_response=mock_response)
226
+
227
+ # Your LLM-based contract will receive the mocked response
228
+ contract = factory.deploy()
229
+ result = contract.llm_method() # Will use the mocked response
230
+ ```
231
+
232
+ Note: This feature is only available when running tests on localnet.
233
+
210
234
  ## 🚀 Key Features
211
235
 
212
236
  - **Pytest Integration** – Extends pytest to support intelligent contract testing, making it familiar and easy to adopt.
@@ -275,7 +299,7 @@ Key features demonstrated in this contract:
275
299
  Here's how to deploy the Storage contract:
276
300
 
277
301
  ```python
278
- from gltest import get_contract_factory, default_account
302
+ from gltest import get_contract_factory, get_default_account
279
303
 
280
304
  def test_deployment():
281
305
  # Get the contract factory for your contract
@@ -285,7 +309,7 @@ def test_deployment():
285
309
  # Deploy the contract with constructor arguments
286
310
  contract = factory.deploy(
287
311
  args=["initial_value"], # Constructor arguments
288
- account=default_account, # Account to deploy from
312
+ account=get_default_account(), # Account to deploy from
289
313
  consensus_max_rotations=3, # Optional: max consensus rotations
290
314
  leader_only=False, # Optional: whether to run only on leader
291
315
  )
@@ -384,6 +408,102 @@ Both `tx_execution_succeeded` and `tx_execution_failed` accept the following par
384
408
 
385
409
  For more example contracts, check out the [contracts directory](tests/examples/contracts) which contains various sample contracts demonstrating different features and use cases.
386
410
 
411
+ ### Test Fixtures
412
+
413
+ The GenLayer Testing Suite provides reusable pytest fixtures in `gltest.fixtures` to simplify common testing operations. These fixtures can be imported and used in your test files to avoid repetitive setup code.
414
+
415
+ #### Available Fixtures
416
+
417
+ The following fixtures are available in `gltest.fixtures`:
418
+
419
+ - **`gl_client`** (session scope) - GenLayer client instance for network operations
420
+ - **`default_account`** (session scope) - Default account for testing and deployments
421
+ - **`accounts`** (session scope) - List of test accounts for multi-account scenarios
422
+ - **`setup_validators`** (function scope) - Function to create test validators for LLM operations
423
+
424
+ ##### 1. `gl_client` (session scope)
425
+ Provides a GenLayer PY client instance that's created once per test session. This is useful for operations that interact directly with the GenLayer network.
426
+
427
+ ```python
428
+ def test_client_operations(gl_client):
429
+ # Use the client for network operations
430
+ tx_hash = "0x1234..."
431
+ transaction = gl_client.get_transaction(tx_hash)
432
+ ```
433
+
434
+ ##### 2. `default_account` (session scope)
435
+ Provides the default account used to execute transactions when no account is specified.
436
+
437
+ ```python
438
+ def test_with_default_account(default_account):
439
+ # Use the default account for deployments
440
+ factory = get_contract_factory("MyContract")
441
+ contract = factory.deploy(account=default_account)
442
+ ```
443
+
444
+ ##### 3. `accounts` (session scope)
445
+ Provides a list of account objects loaded from the private keys defined in `gltest.config.yaml` for the current network, or pre-created test accounts if no config is present
446
+
447
+ ```python
448
+ def test_multiple_accounts(accounts):
449
+ # Get multiple accounts for testing
450
+ sender = accounts[0]
451
+ receiver = accounts[1]
452
+
453
+ # Test transfers or multi-party interactions
454
+ contract.transfer(args=[receiver.address, 100], account=sender)
455
+ ```
456
+
457
+ ##### 4. `setup_validators` (function scope)
458
+ Creates test validators for localnet environment. This fixture is particularly useful for testing LLM-based contract methods and consensus behavior. It yields a function that allows you to configure validators with custom settings.
459
+
460
+ ```python
461
+ def test_with_validators(setup_validators):
462
+ # Setup validators with default configuration
463
+ setup_validators()
464
+
465
+ # Or setup with custom mock responses for testing
466
+ mock_response = {"result": "mocked LLM response"}
467
+ setup_validators(mock_response=mock_response, n_validators=3)
468
+
469
+ # Now test your LLM-based contract methods
470
+ contract = factory.deploy()
471
+ result = contract.llm_based_method()
472
+ ```
473
+
474
+ Parameters for `setup_validators`:
475
+ - `mock_response` (dict, optional): Mock validator response when using `--test-with-mocks` flag
476
+ - `n_validators` (int, optional): Number of validators to create (default: 5)
477
+
478
+ #### Using Fixtures in Your Tests
479
+
480
+ To use these fixtures, simply import them and include them as parameters in your test functions:
481
+
482
+ ```python
483
+ from gltest import get_contract_factory
484
+ from gltest.assertions import tx_execution_succeeded
485
+
486
+ def test_complete_workflow(gl_client, default_account, accounts, setup_validators):
487
+ # Setup validators for LLM operations
488
+ setup_validators()
489
+
490
+ # Deploy contract with default account
491
+ factory = get_contract_factory("MyContract")
492
+ contract = factory.deploy(account=default_account)
493
+
494
+ # Interact using other accounts
495
+ other_account = accounts[1]
496
+ tx_receipt = contract.some_method(args=["value"], account=other_account)
497
+
498
+ assert tx_execution_succeeded(tx_receipt)
499
+ ```
500
+
501
+ Fixtures help maintain clean, DRY test code by:
502
+ - Eliminating repetitive setup code
503
+ - Ensuring consistent test environments
504
+ - Managing resource cleanup automatically
505
+ - Providing appropriate scoping for performance
506
+
387
507
  ## 📝 Best Practices
388
508
 
389
509
  1. **Test Organization**
@@ -0,0 +1,67 @@
1
+ genlayer_test-0.4.1.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/fixtures.py,sha256=IyaTe3b-4weU2Bb5XKnP23dpk3jNKJDAOmYoYqRXFLQ,2501
6
+ gltest/logging.py,sha256=jAkHsuMm-AEx1Xu1srU6W-0YzTwXJB48mCK-OVzAiN4,342
7
+ gltest/types.py,sha256=BODmwTr2gAUEiO9FjiuTiWwuKvXgo4xZWstQWNUfnlw,156
8
+ gltest/artifacts/__init__.py,sha256=qTt3TE19gVNWnQLUlt5aDe4nNvJ2YJ1jzDkMmYIsCG0,194
9
+ gltest/artifacts/contract.py,sha256=KChpmfjZod_0dVB8y-dvWz6IVm7QlIJsgG2ArtvVDaU,6457
10
+ gltest/glchain/__init__.py,sha256=QLd55hVB9xVTAtCKbjmGPAwh0M8_tUNJ5xI0H93YyTY,428
11
+ gltest/glchain/account.py,sha256=HUmWguJMolggQaZNRPw-LGlRlQCjLLdUanKRowMv6pI,812
12
+ gltest/glchain/client.py,sha256=urRvnLt8GpdCV3yOBSvJNZQzu_TsZr8HqKn14Q2SpIQ,1547
13
+ gltest/glchain/contract.py,sha256=ozz1sLYnYyS0O6C1JlUhPKydV1PdPppMCqk-U1Qqmhk,11366
14
+ gltest/helpers/__init__.py,sha256=I7HiTu_H7_hP65zY6Wl02r-5eAMr2eZvqBVmusuQLX4,180
15
+ gltest/helpers/fixture_snapshot.py,sha256=bMgvlEVQBGIQzj7NOyosXWlphI1H2C1o75Zo0C-kGfQ,1931
16
+ gltest/helpers/take_snapshot.py,sha256=eXqEKXM2hcox3pLGIcNddobU8zXPQvD-Iwf87eHqW2s,1276
17
+ gltest_cli/logging.py,sha256=YRWIGwCJIkaB747oQvmS2tzF-B7zymdEMJznrlfyQYA,1245
18
+ gltest_cli/main.py,sha256=Ti2-0Ev1x5_cM0D1UKqdgaDt80CDHEQGtdRne2qLm4M,53
19
+ gltest_cli/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ gltest_cli/config/constants.py,sha256=lX8C3aS7zXWazA8LWgE0BkPvy7NopyEMyJNI2yYWX9M,300
21
+ gltest_cli/config/general.py,sha256=ezpoGsT8grO9zQH6RugV14b1GzeFt-htYToHQBJhNvY,186
22
+ gltest_cli/config/plugin.py,sha256=8eA19hNI8dmnZLwcruXj6MChyspjtqiiCbfFKRT4_yk,3695
23
+ gltest_cli/config/types.py,sha256=2mbbEPD15zHh6-BkLSEByalL4-bi2OP4Qy3EFslqs5M,5669
24
+ gltest_cli/config/user.py,sha256=LjjoqXWRLPeNgOvLKy2tJDNl1M0uLb-5rwEsnGyJunE,8065
25
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
+ tests/conftest.py,sha256=RKdoE5_zcMimeojAoA_GSFI9du4pMzMi1vZ1njtfoAs,28
27
+ tests/examples/contracts/football_prediction_market.py,sha256=0Lm2x2F1DhmUP1fcfzGQAfc50tWFcaHliwyAzXIRFVw,3247
28
+ tests/examples/contracts/intelligent_oracle.py,sha256=cZNGbjKMXY-pimVmPIKIlS963Gd3L1JAipq0VBR1J5Q,12360
29
+ tests/examples/contracts/intelligent_oracle_factory.py,sha256=8lBEn3Atb0yUpXwlvnShlcRxCBTXCrrkoITDHWoWuHU,1499
30
+ tests/examples/contracts/llm_erc20.py,sha256=pOvSUszCtC_f5yDX0tZnj494Ce10uESZ09JLLE8V67o,2534
31
+ tests/examples/contracts/log_indexer.py,sha256=Nlf8XUt13ujam3k6hbbVrPHK-KJ366Csz1TBjc4P07g,1901
32
+ tests/examples/contracts/multi_read_erc20.py,sha256=28qYqn191Ro3rP7YJtZwL6Sc7JDXTeh8_QoqvdVPdqM,864
33
+ tests/examples/contracts/multi_tenant_storage.py,sha256=5F3MCKbzyHMFqLRT9hZNCd3RzjSJvAKVJwLFMeazwog,1906
34
+ tests/examples/contracts/read_erc20.py,sha256=RgH269F0x482WuLLYcacBnZsGJjhgJp6sG_33cV6Z-w,454
35
+ tests/examples/contracts/storage.py,sha256=3DD3qvzb0JkVcBtu240e5kaZWgkh-bu6YExqBUYvfaw,501
36
+ tests/examples/contracts/user_storage.py,sha256=2W2Iv-hQZMkAaPl2RY_F-OeJpD4IlPxgWzN6e1bTkKE,649
37
+ tests/examples/contracts/wizard_of_coin.py,sha256=Y8daPpoSKdM8wfbCPOIgEdpkLIA1ZMmeg6Hu5fBB-kU,1624
38
+ tests/examples/contracts/multi_file_contract/__init__.py,sha256=CCdaK5p12GDf35hgbBWURNM5KUn6SWAcuyieTmZwVWE,548
39
+ tests/examples/contracts/multi_file_contract/other.py,sha256=jHDtjUL3eAUgE6yOYKFw_RfAH7kIwk8CvxUjbWHNruk,236
40
+ tests/examples/tests/test_football_prediction_market.py,sha256=ADIWjh4zmT_9R0xJ4UU5jchPySxKPG_ujp9fy1i3tvQ,1093
41
+ tests/examples/tests/test_intelligent_oracle_factory.py,sha256=K2Xhgth1VLpM7C3qUw1PDp3ODNRs56hx-iv7aP1fTzA,8267
42
+ tests/examples/tests/test_llm_erc20.py,sha256=JZokOzdhxqH9J1x5KrpUukARLOXAGJpIjSh-FImXnN8,2057
43
+ tests/examples/tests/test_log_indexer.py,sha256=KoOeTkwDmFamE8vyqM95y10cvpr1C22EcsYxv2L5unY,2688
44
+ tests/examples/tests/test_multi_file_contract.py,sha256=asZ32ZO4LsttLSFq_CNozX_j19PQbRRW81xw0d8HNp0,551
45
+ tests/examples/tests/test_multi_file_contract_legacy.py,sha256=IovwcE1KzDZ__FszvwQyGFHwlLIxdV4cC9S9hWSGVv4,566
46
+ tests/examples/tests/test_multi_read_erc20.py,sha256=yBac795CA4_uMmtXtIvPLigfjozWi5nPQK6bcJlafvQ,3635
47
+ tests/examples/tests/test_multi_tenant_storage.py,sha256=d4c4fNAjc2a6MkkHDexAP-pFf0tqipHwyM_fouGhA0g,2756
48
+ tests/examples/tests/test_read_erc20.py,sha256=0bMSNUHo9MqRzeJGGKw5ToB9U_MJTa4YFRPdYIeWS-s,1247
49
+ tests/examples/tests/test_storage.py,sha256=c9Yu8556DyQjJktAPsEUKzeMCn_-5CRNzXFgacVuDNY,751
50
+ tests/examples/tests/test_storage_legacy.py,sha256=kXxMA-nNTuj4cV8yXkC_6iLJd8yS0HsyeVM9NnvbXLo,716
51
+ tests/examples/tests/test_user_storage.py,sha256=Kg034FS4sD9p22-S0fEAH0HaDyevk0HQJiiLDjCBCTs,2776
52
+ tests/examples/tests/test_wizard_of_coin.py,sha256=LiiN86ehRKUTbavGfPdqvkyyyY0DD0pp31j3BEgZciw,843
53
+ tests/gltest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
+ tests/gltest/artifact/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
+ tests/gltest/artifact/test_contract_definition.py,sha256=6R8THNFKKpG7brULzp63vT1_pPd_JFNp3ZS08CJJWrg,3642
56
+ tests/gltest/artifact/contracts/duplicate_ic_contract_1.py,sha256=bSWsUVjBy5cGtI72cjnkstsMzuUJbB3IG5JjTxOF-dc,500
57
+ tests/gltest/artifact/contracts/duplicate_ic_contract_2.py,sha256=bSWsUVjBy5cGtI72cjnkstsMzuUJbB3IG5JjTxOF-dc,500
58
+ tests/gltest/artifact/contracts/not_ic_contract.py,sha256=hQyGnYiiVceYdLI2WrvcFgPqzy1S4-YMb9FPhiHEGSA,510
59
+ tests/gltest/assertions/test_assertions.py,sha256=qzVrOdOM4xYtIy1sFHVAD_-naDHOequ23tEN0MELh0k,10781
60
+ tests/gltest_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
+ tests/gltest_cli/config/test_plugin.py,sha256=06-GENVugrL6mPQkgRgQqRsCTuQMy3WZcbh_9Du6zHo,3502
62
+ tests/gltest_cli/config/test_user.py,sha256=oJDcM6NbA16tQzQj5s8ZDvQYBm2uuvar5junFcVeitY,12116
63
+ genlayer_test-0.4.1.dist-info/METADATA,sha256=HxYSMvnSVF_6i-eQhETma9ajk0FkHqc3lM2QdcO83gY,21928
64
+ genlayer_test-0.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
65
+ genlayer_test-0.4.1.dist-info/entry_points.txt,sha256=RWPcSArBpz_G4BYioh5L8Q8hyClRbSgzLimjcWMp-BQ,94
66
+ genlayer_test-0.4.1.dist-info/top_level.txt,sha256=-qiGZxTRBytujzgVcKpxjvQ-WNeUDjXa59ceGMwMpko,24
67
+ genlayer_test-0.4.1.dist-info/RECORD,,
gltest/fixtures.py ADDED
@@ -0,0 +1,91 @@
1
+ """
2
+ This module provides reusable pytest fixtures for common gltest operations.
3
+ These fixtures can be imported and used in test files.
4
+ """
5
+
6
+ import pytest
7
+ from gltest.glchain import (
8
+ get_gl_client,
9
+ get_accounts,
10
+ get_default_account,
11
+ get_gl_provider,
12
+ )
13
+ from gltest_cli.config.general import get_general_config
14
+
15
+
16
+ @pytest.fixture(scope="session")
17
+ def gl_client():
18
+ """
19
+ Provides a GenLayer client instance.
20
+
21
+ Scope: session - created once per test session
22
+ """
23
+ return get_gl_client()
24
+
25
+
26
+ @pytest.fixture(scope="session")
27
+ def default_account():
28
+ """
29
+ Provides the default account for testing.
30
+
31
+ Scope: session - created once per test session
32
+ """
33
+ return get_default_account()
34
+
35
+
36
+ @pytest.fixture(scope="session")
37
+ def accounts():
38
+ """
39
+ Provides a list of test accounts.
40
+
41
+ Scope: session - created once per test session
42
+ """
43
+ return get_accounts()
44
+
45
+
46
+ @pytest.fixture(scope="function")
47
+ def setup_validators():
48
+ """
49
+ Creates test validators for localnet environment.
50
+
51
+ Args:
52
+ mock_response (dict, optional): Mock validator response when using --test-with-mocks flag
53
+ n_validators (int, optional): Number of validators to create (default: 5)
54
+
55
+ Scope: function - created fresh for each test
56
+ """
57
+ general_config = get_general_config()
58
+ provider = get_gl_provider()
59
+
60
+ def _setup(mock_response=None, n_validators=5):
61
+ if not general_config.check_local_rpc():
62
+ return
63
+ if general_config.get_test_with_mocks():
64
+ for _ in range(n_validators):
65
+ provider.make_request(
66
+ method="sim_createValidator",
67
+ params=[
68
+ 8,
69
+ "openai",
70
+ "gpt-4o",
71
+ {"temperature": 0.75, "max_tokens": 500},
72
+ "openai-compatible",
73
+ {
74
+ "api_key_env_var": "OPENAIKEY",
75
+ "api_url": "https://api.openai.com",
76
+ "mock_response": mock_response if mock_response else {},
77
+ },
78
+ ],
79
+ )
80
+ else:
81
+ provider.make_request(
82
+ method="sim_createRandomValidators",
83
+ params=[n_validators, 8, 12],
84
+ )
85
+
86
+ yield _setup
87
+
88
+ if not general_config.check_local_rpc():
89
+ return
90
+
91
+ provider.make_request(method="sim_deleteAllValidators", params=[])
@@ -17,7 +17,7 @@ from gltest.types import CalldataEncodable, GenLayerTransaction, TransactionStat
17
17
  from typing import List, Any, Type, Optional, Dict, Callable
18
18
  import types
19
19
  from gltest_cli.config.general import get_general_config
20
- from gltest_cli.logging import logger
20
+ from gltest.logging import logger
21
21
 
22
22
 
23
23
  @dataclass
@@ -1,6 +1,5 @@
1
1
  from typing import TypeVar, Callable, List, Any
2
2
  from dataclasses import dataclass
3
- from urllib.parse import urlparse
4
3
  from .take_snapshot import SnapshotRestorer, take_snapshot
5
4
  from gltest.exceptions import (
6
5
  FixtureSnapshotError,
@@ -9,8 +8,6 @@ from gltest.exceptions import (
9
8
  )
10
9
  from gltest_cli.config.general import get_general_config
11
10
 
12
- SUPPORTED_RPC_DOMAINS = ["localhost", "127.0.0.1"]
13
-
14
11
  T = TypeVar("T")
15
12
 
16
13
 
@@ -35,9 +32,7 @@ def load_fixture(fixture: Callable[[], T]) -> T:
35
32
  raise FixtureAnonymousFunctionError("Fixtures must be named functions")
36
33
 
37
34
  general_config = get_general_config()
38
- rpc_url = general_config.get_rpc_url()
39
- domain = urlparse(rpc_url).netloc.split(":")[0] # Extract domain without port
40
- if domain not in SUPPORTED_RPC_DOMAINS:
35
+ if not general_config.check_local_rpc():
41
36
  return fixture()
42
37
 
43
38
  # Find existing snapshot for this fixture
gltest/logging.py ADDED
@@ -0,0 +1,17 @@
1
+ import logging
2
+
3
+
4
+ def setup_logger() -> logging.Logger:
5
+ """Setup a logger for the gltest package - disabled by default"""
6
+
7
+ logger = logging.getLogger("gltest")
8
+
9
+ logger.setLevel(logging.NOTSET)
10
+ logger.disabled = True
11
+ logger.addHandler(logging.NullHandler())
12
+ return logger
13
+
14
+
15
+ logger = setup_logger()
16
+
17
+ __all__ = ["logger"]
@@ -48,6 +48,13 @@ def pytest_addoption(parser):
48
48
  help="Target network (defaults to 'localnet' if no config file)",
49
49
  )
50
50
 
51
+ group.addoption(
52
+ "--test-with-mocks",
53
+ action="store_true",
54
+ default=False,
55
+ help="Test with mocks",
56
+ )
57
+
51
58
 
52
59
  def pytest_configure(config):
53
60
  general_config = get_general_config()
@@ -73,6 +80,7 @@ def pytest_configure(config):
73
80
  default_wait_retries = config.getoption("--default-wait-retries")
74
81
  rpc_url = config.getoption("--rpc-url")
75
82
  network = config.getoption("--network")
83
+ test_with_mocks = config.getoption("--test-with-mocks")
76
84
 
77
85
  plugin_config = PluginConfig()
78
86
  plugin_config.contracts_dir = (
@@ -82,6 +90,7 @@ def pytest_configure(config):
82
90
  plugin_config.default_wait_retries = int(default_wait_retries)
83
91
  plugin_config.rpc_url = rpc_url
84
92
  plugin_config.network_name = network
93
+ plugin_config.test_with_mocks = test_with_mocks
85
94
 
86
95
  general_config.plugin_config = plugin_config
87
96
 
@@ -100,3 +109,7 @@ def pytest_sessionstart(session):
100
109
  f" Default wait interval: {general_config.get_default_wait_interval()} ms"
101
110
  )
102
111
  logger.info(f" Default wait retries: {general_config.get_default_wait_retries()}")
112
+ logger.info(f" Test with mocks: {general_config.get_test_with_mocks()}")
113
+
114
+
115
+ pytest_plugins = ["gltest.fixtures"]
@@ -4,6 +4,7 @@ from pathlib import Path
4
4
  from typing import Dict, List, Optional
5
5
  from genlayer_py.chains import localnet, testnet_asimov
6
6
  from genlayer_py.types import GenLayerChain
7
+ from urllib.parse import urlparse
7
8
 
8
9
 
9
10
  class NetworkConfig(str, Enum):
@@ -18,6 +19,7 @@ class PluginConfig:
18
19
  default_wait_interval: Optional[int] = None
19
20
  default_wait_retries: Optional[int] = None
20
21
  network_name: Optional[str] = None
22
+ test_with_mocks: bool = False
21
23
 
22
24
 
23
25
  @dataclass
@@ -135,3 +137,12 @@ class GeneralConfig:
135
137
  if self.plugin_config.network_name is not None:
136
138
  return self.plugin_config.network_name
137
139
  return self.user_config.default_network
140
+
141
+ def get_test_with_mocks(self) -> bool:
142
+ return self.plugin_config.test_with_mocks
143
+
144
+ def check_local_rpc(self) -> bool:
145
+ SUPPORTED_RPC_DOMAINS = ["localhost", "127.0.0.1"]
146
+ rpc_url = self.get_rpc_url()
147
+ domain = urlparse(rpc_url).netloc.split(":")[0] # Extract domain without port
148
+ return domain in SUPPORTED_RPC_DOMAINS
gltest_cli/logging.py CHANGED
@@ -30,7 +30,7 @@ class ColoredFormatter(logging.Formatter):
30
30
 
31
31
 
32
32
  def setup_logger():
33
- logger = logging.getLogger("gltest")
33
+ logger = logging.getLogger("gltest_cli")
34
34
  logger.setLevel(logging.DEBUG)
35
35
 
36
36
  if logger.handlers:
@@ -1,4 +1,5 @@
1
- # { "Depends": "py-genlayer:test" }
1
+ # v0.1.0
2
+ # { "Depends": "py-genlayer:latest" }
2
3
 
3
4
  from genlayer import *
4
5
 
@@ -36,7 +37,7 @@ class PredictionMarket(gl.Contract):
36
37
  )
37
38
  self.team1 = team1
38
39
  self.team2 = team2
39
- self.winner = 0
40
+ self.winner = u256(0)
40
41
  self.score = ""
41
42
 
42
43
  @gl.public.write
@@ -49,8 +50,8 @@ class PredictionMarket(gl.Contract):
49
50
  team1 = self.team1
50
51
  team2 = self.team2
51
52
 
52
- def get_match_result() -> str:
53
- web_data = gl.get_webpage(market_resolution_url, mode="text")
53
+ def get_match_result() -> typing.Any:
54
+ web_data = gl.nondet.web.render(market_resolution_url, mode="text")
54
55
  print(web_data)
55
56
 
56
57
  task = f"""
@@ -75,11 +76,13 @@ nothing else. Don't include any other words or characters,
75
76
  your output must be only JSON without any formatting prefix or suffix.
76
77
  This result should be perfectly parsable by a JSON parser without errors.
77
78
  """
78
- result = gl.exec_prompt(task).replace("```json", "").replace("```", "")
79
+ result = (
80
+ gl.nondet.exec_prompt(task).replace("```json", "").replace("```", "")
81
+ )
79
82
  print(result)
80
- return json.dumps(json.loads(result), sort_keys=True)
83
+ return json.loads(result)
81
84
 
82
- result_json = json.loads(gl.eq_principle_strict_eq(get_match_result))
85
+ result_json = gl.eq_principle.strict_eq(get_match_result)
83
86
 
84
87
  if result_json["winner"] > -1:
85
88
  self.has_resolved = True
@@ -94,4 +97,4 @@ This result should be perfectly parsable by a JSON parser without errors.
94
97
  "winner": self.winner,
95
98
  "score": self.score,
96
99
  "has_resolved": self.has_resolved,
97
- }
100
+ }
@@ -1,3 +1,4 @@
1
+ # v0.1.0
1
2
  # { "Depends": "py-genlayer:test" }
2
3
 
3
4
  import json
@@ -139,7 +140,7 @@ class IntelligentOracle(gl.Contract):
139
140
  for resource_url in resources_to_check:
140
141
 
141
142
  def evaluate_single_source() -> str:
142
- resource_web_data = gl.get_webpage(resource_url, mode="text")
143
+ resource_web_data = gl.nondet.web.render(resource_url, mode="text")
143
144
  print(resource_web_data)
144
145
 
145
146
  task = f"""
@@ -223,11 +224,11 @@ Provide your response in **valid JSON** format with the following structure:
223
224
  - **Clarity:** Make sure your reasoning is easy to understand.
224
225
  - **Validity:** Ensure the JSON output is properly formatted and free of errors. Do not include trailing commas.
225
226
  """
226
- result = gl.exec_prompt(task)
227
+ result = gl.nondet.exec_prompt(task)
227
228
  print(result)
228
229
  return result
229
230
 
230
- result = gl.eq_principle_prompt_comparative(
231
+ result = gl.eq_principle.prompt_comparative(
231
232
  evaluate_single_source,
232
233
  principle="`outcome` field must be exactly the same. All other fields must be similar",
233
234
  )
@@ -305,11 +306,11 @@ Provide your response in **valid JSON** format with the following structure:
305
306
 
306
307
  """
307
308
 
308
- result = gl.exec_prompt(task)
309
+ result = gl.nondet.exec_prompt(task)
309
310
  print(result)
310
311
  return result
311
312
 
312
- result = gl.eq_principle_prompt_comparative(
313
+ result = gl.eq_principle.prompt_comparative(
313
314
  evaluate_all_sources,
314
315
  principle="`outcome` field must be exactly the same. All other fields must be similar",
315
316
  )
@@ -331,7 +332,7 @@ Provide your response in **valid JSON** format with the following structure:
331
332
  self.status = Status.RESOLVED.value
332
333
 
333
334
  @gl.public.view
334
- def get_dict(self) -> dict[str, str]:
335
+ def get_dict(self) -> dict[str, str | list[str]]:
335
336
  return {
336
337
  "title": self.title,
337
338
  "description": self.description,
@@ -1,3 +1,4 @@
1
+ # v0.1.0
1
2
  # { "Depends": "py-genlayer:test" }
2
3
 
3
4
  from genlayer import *
@@ -1,4 +1,5 @@
1
- # { "Depends": "py-genlayer:test" }
1
+ # v0.1.0
2
+ # { "Depends": "py-genlayer:latest" }
2
3
 
3
4
  import json
4
5
 
@@ -47,7 +48,7 @@ The balance of the receiver should have increased by the amount sent.
47
48
  The total sum of all balances should remain the same before and after the transaction"""
48
49
 
49
50
  final_result = (
50
- gl.eq_principle_prompt_non_comparative(
51
+ gl.eq_principle.prompt_non_comparative(
51
52
  lambda: input,
52
53
  task=task,
53
54
  criteria=criteria,
@@ -1,13 +1,15 @@
1
+ # v0.1.0
1
2
  # {
2
3
  # "Seq": [
3
- # { "Depends": "py-lib-genlayermodelwrappers:test" },
4
- # { "Depends": "py-genlayer:test" }
4
+ # { "Depends": "py-lib-genlayer-embeddings:09h0i209wrzh4xzq86f79c60x0ifs7xcjwl53ysrnw06i54ddxyi" },
5
+ # { "Depends": "py-genlayer:latest" }
5
6
  # ]
6
7
  # }
7
8
 
8
9
  import numpy as np
9
10
  from genlayer import *
10
- import genlayermodelwrappers
11
+ import genlayer_embeddings as gle
12
+
11
13
  from dataclasses import dataclass
12
14
  import typing
13
15
 
@@ -21,13 +23,13 @@ class StoreValue:
21
23
 
22
24
  # contract class
23
25
  class LogIndexer(gl.Contract):
24
- vector_store: VecDB[np.float32, typing.Literal[384], StoreValue]
26
+ vector_store: gle.VecDB[np.float32, typing.Literal[384], StoreValue]
25
27
 
26
28
  def __init__(self):
27
29
  pass
28
30
 
29
31
  def get_embedding_generator(self):
30
- return genlayermodelwrappers.SentenceTransformer("all-MiniLM-L6-v2")
32
+ return gle.SentenceTransformer("all-MiniLM-L6-v2")
31
33
 
32
34
  def get_embedding(
33
35
  self, txt: str
@@ -8,7 +8,10 @@ class MultiFileContract(gl.Contract):
8
8
  with open("/contract/other.py", "rt") as f:
9
9
  text = f.read()
10
10
  self.other_addr = gl.deploy_contract(
11
- code=text.encode("utf-8"), args=["123"], salt_nonce=1
11
+ code=text.encode("utf-8"),
12
+ args=["123"],
13
+ salt_nonce=u256(1),
14
+ value=u256(0),
12
15
  )
13
16
 
14
17
  @gl.public.write
@@ -17,4 +20,4 @@ class MultiFileContract(gl.Contract):
17
20
 
18
21
  @gl.public.view
19
22
  def test(self) -> str:
20
- return gl.ContractAt(self.other_addr).view().test()
23
+ return gl.get_contract_at(self.other_addr).view().test()
@@ -1,3 +1,4 @@
1
+ # v0.1.0
1
2
  # { "Depends": "py-genlayer:test" }
2
3
 
3
4
  from genlayer import *
@@ -14,7 +15,7 @@ class multi_read_erc20(gl.Contract):
14
15
  self, account_address: str, token_contracts: list[str]
15
16
  ) -> None:
16
17
  for token_contract in token_contracts:
17
- contract = gl.ContractAt(Address(token_contract))
18
+ contract = gl.get_contract_at(Address(token_contract))
18
19
  balance = contract.view().get_balance_of(account_address)
19
20
  self.balances.get_or_insert_default(Address(account_address))[
20
21
  Address(token_contract)
@@ -1,3 +1,4 @@
1
+ # v0.1.0
1
2
  # { "Depends": "py-genlayer:test" }
2
3
 
3
4
  from genlayer import *
@@ -29,7 +30,7 @@ class MultiTentantStorage(gl.Contract):
29
30
  @gl.public.view
30
31
  def get_all_storages(self) -> dict[str, str]:
31
32
  return {
32
- storage_contract.as_hex: gl.ContractAt(storage_contract)
33
+ storage_contract.as_hex: gl.get_contract_at(storage_contract)
33
34
  .view()
34
35
  .get_storage()
35
36
  for storage_contract in self.all_storage_contracts
@@ -45,4 +46,4 @@ class MultiTentantStorage(gl.Contract):
45
46
  self.available_storage_contracts.pop()
46
47
 
47
48
  contract_to_use = self.mappings[gl.message.sender_address]
48
- gl.ContractAt(contract_to_use).emit(gas=100000).update_storage(new_storage)
49
+ gl.get_contract_at(contract_to_use).emit().update_storage(new_storage)
@@ -1,3 +1,4 @@
1
+ # v0.1.0
1
2
  # { "Depends": "py-genlayer:test" }
2
3
 
3
4
  from genlayer import *
@@ -11,4 +12,8 @@ class read_erc20(gl.Contract):
11
12
 
12
13
  @gl.public.view
13
14
  def get_balance_of(self, account_address: str) -> int:
14
- return gl.ContractAt(self.token_contract).view().get_balance_of(account_address)
15
+ return (
16
+ gl.get_contract_at(self.token_contract)
17
+ .view()
18
+ .get_balance_of(account_address)
19
+ )
@@ -1,4 +1,5 @@
1
- # { "Depends": "py-genlayer:test" }
1
+ # v0.1.0
2
+ # { "Depends": "py-genlayer:latest" }
2
3
 
3
4
  from genlayer import *
4
5
 
@@ -1,4 +1,5 @@
1
- # { "Depends": "py-genlayer:test" }
1
+ # v0.1.0
2
+ # { "Depends": "py-genlayer:latest" }
2
3
 
3
4
  from genlayer import *
4
5
 
@@ -1,4 +1,5 @@
1
- # { "Depends": "py-genlayer:test" }
1
+ # v0.1.0
2
+ # { "Depends": "py-genlayer:latest" }
2
3
  from genlayer import *
3
4
 
4
5
  import json
@@ -39,12 +40,12 @@ This result should be perfectly parseable by a JSON parser without errors.
39
40
  """
40
41
 
41
42
  def get_wizard_answer():
42
- result = gl.exec_prompt(prompt)
43
+ result = gl.nondet.exec_prompt(prompt)
43
44
  result = result.replace("```json", "").replace("```", "")
44
45
  print(result)
45
46
  return result
46
47
 
47
- result = gl.eq_principle_prompt_comparative(
48
+ result = gl.eq_principle.prompt_comparative(
48
49
  get_wizard_answer, "The value of give_coin has to match"
49
50
  )
50
51
  parsed_result = json.loads(result)
@@ -1,8 +1,27 @@
1
1
  from gltest import get_contract_factory
2
2
  from gltest.assertions import tx_execution_succeeded
3
+ import json
3
4
 
4
5
 
5
- def test_football_prediction_market():
6
+ def test_football_prediction_market(setup_validators):
7
+
8
+ # Setup validators with mock response
9
+ team_1 = "Georgia"
10
+ team_2 = "Portugal"
11
+ score = "2:0"
12
+ winner = 1
13
+ mock_response = {
14
+ "response": {
15
+ f"Team 1: {team_1}\nTeam 2: {team_2}": json.dumps(
16
+ {
17
+ "score": score,
18
+ "winner": winner,
19
+ }
20
+ ),
21
+ }
22
+ }
23
+ setup_validators(mock_response)
24
+
6
25
  # Deploy Contract
7
26
  factory = get_contract_factory("PredictionMarket")
8
27
  contract = factory.deploy(args=["2024-06-26", "Georgia", "Portugal"])
@@ -1,4 +1,5 @@
1
1
  import time
2
+ import json
2
3
 
3
4
  from gltest import get_contract_factory
4
5
  from gltest.assertions import tx_execution_succeeded
@@ -18,16 +19,55 @@ def wait_for_contract_deployment(intelligent_oracle_contract, max_retries=10, de
18
19
  return False
19
20
 
20
21
 
21
- def test_intelligent_oracle_factory_pattern():
22
- # Get the intelligent oracle factory
23
- intelligent_oracle_factory = get_contract_factory("IntelligentOracle")
22
+ def create_mock_response(markets_data):
23
+ reasoning_single_source_marathon = "The HTML content contains the results of the Madrid Marathon 2024, which occurred on April 28, 2024. Mitku Tafa won and matches the name 'Tafa Mitku' in the list of potential outcomes."
24
+ reasoning_all_sources_marathon = "The URL indicates that the Madrid Marathon 2024 has occurred on April 28, 2024, and Mitku Tafa was the winner. The name matches one of the potential outcomes. There are no conflicting sources."
25
+ reasoning_single_source_election = "The URL is a valid news page. The election has occurred, and Donald Trump is reported to have won with 312 votes. The rule specifies that the outcome is based on official election results."
26
+ reasoning_all_sources_election = "The only data source provided is from BBC News. It reports that Donald Trump won the 2024 US presidential election with 312 votes. The rule specifies that the outcome is based on official election results. There are no other sources contradicting this information."
27
+
28
+ return {
29
+ "response": {
30
+ f"outcomes.\n\n### Inputs\n<title>\n{markets_data[0]['title']}": json.dumps(
31
+ {
32
+ "valid_source": "true",
33
+ "event_has_occurred": "true",
34
+ "reasoning": reasoning_single_source_marathon,
35
+ "outcome": markets_data[0]["outcome"],
36
+ }
37
+ ),
38
+ f"inputs\n\n ### Inputs\n <title>\n {markets_data[0]['title']}\n": json.dumps(
39
+ {
40
+ "relevant_sources": [markets_data[0]["evidence_urls"]],
41
+ "reasoning": reasoning_all_sources_marathon,
42
+ "outcome": markets_data[0]["outcome"],
43
+ }
44
+ ),
45
+ f"outcomes.\n\n### Inputs\n<title>\n{markets_data[1]['title']}": json.dumps(
46
+ {
47
+ "valid_source": "true",
48
+ "event_has_occurred": "true",
49
+ "reasoning": reasoning_single_source_election,
50
+ "outcome": markets_data[1]["outcome"],
51
+ }
52
+ ),
53
+ f"inputs\n\n ### Inputs\n <title>\n {markets_data[1]['title']}\n": json.dumps(
54
+ {
55
+ "relevant_sources": [markets_data[1]["evidence_urls"]],
56
+ "reasoning": reasoning_all_sources_election,
57
+ "outcome": markets_data[1]["outcome"],
58
+ }
59
+ ),
60
+ },
61
+ "eq_principle_prompt_comparative": {
62
+ reasoning_single_source_marathon: True,
63
+ reasoning_all_sources_marathon: True,
64
+ reasoning_single_source_election: True,
65
+ reasoning_all_sources_election: True,
66
+ },
67
+ }
24
68
 
25
- # Deploy the Registry contract with the IntelligentOracle code
26
- registry_factory = get_contract_factory("Registry")
27
- registry_contract = registry_factory.deploy(
28
- args=[intelligent_oracle_factory.contract_code]
29
- )
30
69
 
70
+ def test_intelligent_oracle_factory_pattern(setup_validators):
31
71
  markets_data = [
32
72
  {
33
73
  "prediction_market_id": "marathon2024",
@@ -56,9 +96,22 @@ def test_intelligent_oracle_factory_pattern():
56
96
  "evidence_urls": "https://www.bbc.com/news/election/2024/us/results",
57
97
  },
58
98
  ]
59
- created_market_contracts = []
99
+
100
+ mock_response = create_mock_response(markets_data)
101
+
102
+ setup_validators(mock_response)
103
+
104
+ # Get the intelligent oracle factory
105
+ intelligent_oracle_factory = get_contract_factory("IntelligentOracle")
106
+
107
+ # Deploy the Registry contract with the IntelligentOracle code
108
+ registry_factory = get_contract_factory("Registry")
109
+ registry_contract = registry_factory.deploy(
110
+ args=[intelligent_oracle_factory.contract_code]
111
+ )
60
112
 
61
113
  # Create markets through factory
114
+ created_market_contracts = []
62
115
  for market_data in markets_data:
63
116
  create_result = registry_contract.create_new_prediction_market(
64
117
  args=[
@@ -1,15 +1,34 @@
1
1
  from gltest import get_contract_factory, get_default_account, create_account
2
2
  from gltest.assertions import tx_execution_succeeded
3
+ import json
3
4
 
4
5
  TOKEN_TOTAL_SUPPLY = 1000
5
6
  TRANSFER_AMOUNT = 100
6
7
 
7
8
 
8
- def test_llm_erc20():
9
+ def test_llm_erc20(setup_validators):
9
10
  # Account Setup
10
11
  from_account_a = get_default_account()
11
12
  from_account_b = create_account()
12
13
 
14
+ # Mock Response
15
+ mock_response = {
16
+ "response": {
17
+ "The balance of the sender": json.dumps(
18
+ {
19
+ "transaction_success": True,
20
+ "transaction_error": "",
21
+ "updated_balances": {
22
+ from_account_a.address: TOKEN_TOTAL_SUPPLY - TRANSFER_AMOUNT,
23
+ from_account_b.address: TRANSFER_AMOUNT,
24
+ },
25
+ }
26
+ )
27
+ },
28
+ "eq_principle_prompt_non_comparative": {"The balance of the sender": True},
29
+ }
30
+ setup_validators(mock_response=mock_response)
31
+
13
32
  # Deploy Contract
14
33
  factory = get_contract_factory("LlmErc20")
15
34
  contract = factory.deploy(args=[TOKEN_TOTAL_SUPPLY])
@@ -2,7 +2,8 @@ from gltest import get_contract_factory
2
2
  from gltest.assertions import tx_execution_succeeded
3
3
 
4
4
 
5
- def test_log_indexer():
5
+ def test_log_indexer(setup_validators):
6
+ setup_validators()
6
7
  # Deploy Contract
7
8
  factory = get_contract_factory("LogIndexer")
8
9
  contract = factory.deploy(args=[])
@@ -2,9 +2,10 @@ from gltest import get_contract_factory
2
2
  from gltest.assertions import tx_execution_succeeded
3
3
 
4
4
 
5
- def test_multi_file_contract():
5
+ def test_multi_file_contract(setup_validators):
6
6
  # Multi file contracts are considered if they are defined in a __init__.py file
7
7
  # Deploy Contract, it will deploy other.py as well
8
+ setup_validators()
8
9
  factory = get_contract_factory("MultiFileContract")
9
10
  contract = factory.deploy(args=[])
10
11
 
@@ -2,9 +2,10 @@ from gltest import get_contract_factory
2
2
  from gltest.assertions import tx_execution_succeeded
3
3
 
4
4
 
5
- def test_multi_file_contract_legacy():
5
+ def test_multi_file_contract_legacy(setup_validators):
6
6
  # Multi file contracts are considered if they are defined in a __init__.gpy file
7
7
  # Deploy Contract, it will deploy other.gpy as well
8
+ setup_validators()
8
9
  factory = get_contract_factory("MultiFileContractLegacy")
9
10
  contract = factory.deploy(args=[])
10
11
 
@@ -4,7 +4,7 @@ from gltest_cli.config.general import get_general_config
4
4
  from genlayer_py.chains import testnet_asimov
5
5
 
6
6
 
7
- def test_multi_read_erc20():
7
+ def test_multi_read_erc20(setup_validators):
8
8
  """
9
9
  This test verifies the functionality of a multi-read ERC20 contract. It deploys two separate ERC20 token contracts
10
10
  (referred to as 'doge' and 'shiba') and a multi-read ERC20 contract. The test aims to:
@@ -17,14 +17,20 @@ def test_multi_read_erc20():
17
17
 
18
18
  This test demonstrates the integration contract to contract reads
19
19
  """
20
+ setup_validators()
20
21
  general_config = get_general_config()
21
22
  chain = general_config.get_chain()
22
23
 
23
24
  TOKEN_TOTAL_SUPPLY = 1000
24
25
 
25
26
  if chain.id == testnet_asimov.id:
26
- from_account_doge = get_accounts()[0]
27
- from_account_shiba = get_accounts()[1]
27
+ accounts = get_accounts()
28
+ if len(accounts) < 2:
29
+ raise ValueError(
30
+ f"Test requires at least 2 accounts, but only {len(accounts)} available"
31
+ )
32
+ from_account_doge = accounts[0]
33
+ from_account_shiba = accounts[1]
28
34
  else:
29
35
  from_account_doge = create_account()
30
36
  from_account_shiba = create_account()
@@ -4,7 +4,7 @@ from gltest_cli.config.general import get_general_config
4
4
  from genlayer_py.chains import testnet_asimov
5
5
 
6
6
 
7
- def test_multi_tenant_storage():
7
+ def test_multi_tenant_storage(setup_validators):
8
8
  """
9
9
  This test verifies the functionality of a multi-tenant storage contract. It deploys two separate storage contracts
10
10
  and a multi-tenant storage contract that manages them. The test aims to:
@@ -17,6 +17,7 @@ def test_multi_tenant_storage():
17
17
 
18
18
  This test demonstrates contract-to-contract interactions and multi-tenant data management.
19
19
  """
20
+ setup_validators()
20
21
  general_config = get_general_config()
21
22
  chain = general_config.get_chain()
22
23
 
@@ -1,7 +1,7 @@
1
1
  from gltest import get_contract_factory, get_default_account
2
2
 
3
3
 
4
- def test_read_erc20():
4
+ def test_read_erc20(setup_validators):
5
5
  """
6
6
  Tests that recursive contract calls work by:
7
7
  1. creating an LLM ERC20 contract
@@ -11,6 +11,7 @@ def test_read_erc20():
11
11
 
12
12
  It's like a linked list, but with contracts.
13
13
  """
14
+ setup_validators()
14
15
  TOKEN_TOTAL_SUPPLY = 1000
15
16
 
16
17
  # LLM ERC20
@@ -6,7 +6,8 @@ INITIAL_STATE = "a"
6
6
  UPDATED_STATE = "b"
7
7
 
8
8
 
9
- def test_storage():
9
+ def test_storage(setup_validators):
10
+ setup_validators()
10
11
  factory = get_contract_factory("Storage")
11
12
  contract = factory.deploy(args=[INITIAL_STATE], wait_retries=40)
12
13
 
@@ -6,7 +6,8 @@ INITIAL_STATE = "a"
6
6
  UPDATED_STATE = "b"
7
7
 
8
8
 
9
- def test_storage_legacy():
9
+ def test_storage_legacy(setup_validators):
10
+ setup_validators()
10
11
  factory = get_contract_factory("StorageLegacy")
11
12
  contract = factory.deploy(args=[INITIAL_STATE])
12
13
 
@@ -15,14 +15,20 @@ INITIAL_STATE_USER_B = "user_b_initial_state"
15
15
  UPDATED_STATE_USER_B = "user_b_updated_state"
16
16
 
17
17
 
18
- def test_user_storage():
18
+ def test_user_storage(setup_validators):
19
+ setup_validators()
19
20
  general_config = get_general_config()
20
21
  chain = general_config.get_chain()
21
22
 
22
23
  # Account Setup
23
24
  if chain.id == testnet_asimov.id:
24
- from_account_a = get_accounts()[0]
25
- from_account_b = get_accounts()[1]
25
+ accounts = get_accounts()
26
+ if len(accounts) < 2:
27
+ raise ValueError(
28
+ f"Test requires at least 2 accounts, but only {len(accounts)} available"
29
+ )
30
+ from_account_a = accounts[0]
31
+ from_account_b = accounts[1]
26
32
  else:
27
33
  from_account_a = get_default_account()
28
34
  from_account_b = create_account()
@@ -1,8 +1,23 @@
1
1
  from gltest import get_contract_factory
2
2
  from gltest.assertions import tx_execution_succeeded
3
+ import json
3
4
 
4
5
 
5
- def test_wizard_of_coin():
6
+ def test_wizard_of_coin(setup_validators):
7
+ mock_response = {
8
+ "response": {
9
+ "wizard": json.dumps(
10
+ {
11
+ "reasoning": "I am a grumpy wizard and I never give away my coins!",
12
+ "give_coin": False,
13
+ }
14
+ ),
15
+ },
16
+ "eq_principle_prompt_comparative": {
17
+ "The value of give_coin has to match": True
18
+ },
19
+ }
20
+ setup_validators(mock_response)
6
21
  factory = get_contract_factory("WizardOfCoin")
7
22
  contract = factory.deploy(args=[True])
8
23
 
@@ -1,65 +0,0 @@
1
- genlayer_test-0.3.1.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.1.dist-info/METADATA,sha256=zW6QEyxquLwgMY9UJb9kVq9MHtxgqcnyAY8Nm9avV4M,17231
62
- genlayer_test-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
63
- genlayer_test-0.3.1.dist-info/entry_points.txt,sha256=RWPcSArBpz_G4BYioh5L8Q8hyClRbSgzLimjcWMp-BQ,94
64
- genlayer_test-0.3.1.dist-info/top_level.txt,sha256=-qiGZxTRBytujzgVcKpxjvQ-WNeUDjXa59ceGMwMpko,24
65
- genlayer_test-0.3.1.dist-info/RECORD,,