genlayer-test 0.4.1__tar.gz → 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/PKG-INFO +75 -14
  2. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/README.md +73 -12
  3. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/genlayer_test.egg-info/PKG-INFO +75 -14
  4. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/genlayer_test.egg-info/SOURCES.txt +13 -4
  5. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/genlayer_test.egg-info/requires.txt +1 -1
  6. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest/__init__.py +7 -6
  7. genlayer_test-0.4.1/gltest/glchain/client.py → genlayer_test-2.0.0/gltest/clients.py +1 -1
  8. genlayer_test-2.0.0/gltest/contracts/__init__.py +4 -0
  9. genlayer_test-2.0.0/gltest/contracts/contract.py +197 -0
  10. genlayer_test-0.4.1/gltest/glchain/contract.py → genlayer_test-2.0.0/gltest/contracts/contract_factory.py +22 -137
  11. genlayer_test-2.0.0/gltest/contracts/contract_functions.py +59 -0
  12. genlayer_test-2.0.0/gltest/contracts/method_stats.py +163 -0
  13. genlayer_test-2.0.0/gltest/contracts/stats_collector.py +259 -0
  14. genlayer_test-2.0.0/gltest/contracts/utils.py +12 -0
  15. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest/fixtures.py +2 -6
  16. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest/helpers/take_snapshot.py +1 -1
  17. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest_cli/config/constants.py +1 -0
  18. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest_cli/config/plugin.py +53 -0
  19. genlayer_test-2.0.0/gltest_cli/config/pytest_context.py +9 -0
  20. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest_cli/config/types.py +41 -0
  21. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest_cli/config/user.py +21 -8
  22. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/pyproject.toml +2 -2
  23. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/contracts/football_prediction_market.py +1 -1
  24. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/tests/test_football_prediction_market.py +2 -2
  25. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/tests/test_intelligent_oracle_factory.py +6 -6
  26. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/tests/test_llm_erc20.py +5 -5
  27. genlayer_test-2.0.0/tests/examples/tests/test_llm_erc20_analyze.py +50 -0
  28. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/tests/test_log_indexer.py +23 -11
  29. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/tests/test_multi_file_contract.py +2 -2
  30. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/tests/test_multi_file_contract_legacy.py +2 -2
  31. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/tests/test_multi_read_erc20.py +14 -12
  32. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/tests/test_multi_tenant_storage.py +11 -7
  33. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/tests/test_read_erc20.py +1 -1
  34. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/tests/test_storage.py +4 -4
  35. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/tests/test_storage_legacy.py +5 -3
  36. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/tests/test_user_storage.py +20 -10
  37. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/tests/test_wizard_of_coin.py +1 -1
  38. genlayer_test-2.0.0/tests/gltest_cli/config/test_config_integration.py +432 -0
  39. genlayer_test-2.0.0/tests/gltest_cli/config/test_general_config.py +406 -0
  40. genlayer_test-2.0.0/tests/gltest_cli/config/test_plugin.py +294 -0
  41. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/gltest_cli/config/test_user.py +61 -1
  42. genlayer_test-0.4.1/gltest/glchain/__init__.py +0 -16
  43. genlayer_test-0.4.1/tests/gltest_cli/config/test_plugin.py +0 -127
  44. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/LICENSE +0 -0
  45. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/genlayer_test.egg-info/dependency_links.txt +0 -0
  46. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/genlayer_test.egg-info/entry_points.txt +0 -0
  47. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/genlayer_test.egg-info/top_level.txt +0 -0
  48. /genlayer_test-0.4.1/gltest/glchain/account.py → /genlayer_test-2.0.0/gltest/accounts.py +0 -0
  49. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest/artifacts/__init__.py +0 -0
  50. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest/artifacts/contract.py +0 -0
  51. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest/assertions.py +0 -0
  52. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest/exceptions.py +0 -0
  53. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest/helpers/__init__.py +0 -0
  54. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest/helpers/fixture_snapshot.py +0 -0
  55. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest/logging.py +0 -0
  56. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest/types.py +0 -0
  57. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest_cli/config/__init__.py +0 -0
  58. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest_cli/config/general.py +0 -0
  59. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest_cli/logging.py +0 -0
  60. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/gltest_cli/main.py +0 -0
  61. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/setup.cfg +0 -0
  62. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/__init__.py +0 -0
  63. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/conftest.py +0 -0
  64. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/contracts/intelligent_oracle.py +0 -0
  65. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/contracts/intelligent_oracle_factory.py +0 -0
  66. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/contracts/llm_erc20.py +0 -0
  67. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/contracts/log_indexer.py +0 -0
  68. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/contracts/multi_file_contract/__init__.py +0 -0
  69. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/contracts/multi_file_contract/other.py +0 -0
  70. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/contracts/multi_read_erc20.py +0 -0
  71. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/contracts/multi_tenant_storage.py +0 -0
  72. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/contracts/read_erc20.py +0 -0
  73. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/contracts/storage.py +0 -0
  74. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/contracts/user_storage.py +0 -0
  75. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/examples/contracts/wizard_of_coin.py +0 -0
  76. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/gltest/__init__.py +0 -0
  77. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/gltest/artifact/__init__.py +0 -0
  78. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/gltest/artifact/contracts/duplicate_ic_contract_1.py +0 -0
  79. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/gltest/artifact/contracts/duplicate_ic_contract_2.py +0 -0
  80. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/gltest/artifact/contracts/not_ic_contract.py +0 -0
  81. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/gltest/artifact/test_contract_definition.py +0 -0
  82. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/gltest/assertions/test_assertions.py +0 -0
  83. {genlayer_test-0.4.1 → genlayer_test-2.0.0}/tests/gltest_cli/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: genlayer-test
3
- Version: 0.4.1
3
+ Version: 2.0.0
4
4
  Summary: GenLayer Testing Suite
5
5
  Author: GenLayer
6
6
  License-Expression: MIT
@@ -15,7 +15,7 @@ Description-Content-Type: text/markdown
15
15
  License-File: LICENSE
16
16
  Requires-Dist: pytest
17
17
  Requires-Dist: setuptools>=77.0
18
- Requires-Dist: genlayer-py==0.6.1
18
+ Requires-Dist: genlayer-py==0.7.2
19
19
  Requires-Dist: colorama>=0.4.6
20
20
  Requires-Dist: pyyaml
21
21
  Requires-Dist: python-dotenv
@@ -59,8 +59,8 @@ contract = factory.deploy(account=other_account)
59
59
  assert contract.account == other_account
60
60
 
61
61
  # Interact with the contract
62
- result = contract.get_value() # Read method
63
- tx_receipt = contract.set_value(args=["new_value"]) # Write method
62
+ result = contract.get_value().call() # Read method
63
+ tx_receipt = contract.set_value(args=["new_value"]).transact() # Write method
64
64
 
65
65
  assert tx_execution_succeeded(tx_receipt)
66
66
  ```
@@ -114,6 +114,7 @@ networks:
114
114
 
115
115
  localnet: # Local development network configuration
116
116
  url: "http://127.0.0.1:4000/api"
117
+ leader_only: false # Set to true to run all contracts in leader-only mode by default
117
118
 
118
119
  testnet_asimov: # Test network configuration
119
120
  id: 4221
@@ -125,6 +126,7 @@ networks:
125
126
 
126
127
  paths:
127
128
  contracts: "contracts" # Path to your contracts directory
129
+ artifacts: "artifacts" # Path to your artifacts directory
128
130
 
129
131
  environment: .env # Path to your environment file containing private keys and other secrets
130
132
  ```
@@ -137,12 +139,14 @@ Key configuration sections:
137
139
  - `url`: The RPC endpoint for the network
138
140
  - `id`: Chain ID
139
141
  - `accounts`: List of account private keys (using environment variables)
142
+ - `leader_only`: Leader only mode
140
143
  - Special case for `localnet`:
141
144
  - If a network is named `localnet`, missing fields will be filled with default values
142
145
  - For all other network names, `id`, `url`, and `accounts` are required fields
143
146
 
144
147
  2. **Paths**: Define important directory paths
145
148
  - `contracts`: Location of your contract files
149
+ - `artifacts`: Location of your artifacts files (analysis results will be stored here)
146
150
 
147
151
  3. **Environment**: Path to your `.env` file containing sensitive information like private keys
148
152
 
@@ -231,6 +235,20 @@ def test_with_mocked_llm(setup_validators):
231
235
 
232
236
  Note: This feature is only available when running tests on localnet.
233
237
 
238
+ 11. Run tests with leader-only mode enabled
239
+ ```bash
240
+ $ gltest --leader-only
241
+ ```
242
+ The `--leader-only` flag configures all contract deployments and write operations to run only on the leader node. This is useful for:
243
+ - Faster test execution by avoiding consensus
244
+ - Testing specific leader-only scenarios
245
+ - Development and debugging purposes
246
+ - Reducing computational overhead in test environments
247
+
248
+ When this flag is enabled, all contracts deployed and all write transactions will automatically use leader-only mode, regardless of individual method parameters.
249
+
250
+ **Note:** Leader-only mode is only available for studio-based networks (localhost, 127.0.0.1, *.genlayer.com, *.genlayerlabs.com). When enabled on other networks, it will have no effect and a warning will be logged.
251
+
234
252
  ## 🚀 Key Features
235
253
 
236
254
  - **Pytest Integration** – Extends pytest to support intelligent contract testing, making it familiar and easy to adopt.
@@ -251,8 +269,9 @@ Before diving into the examples, let's understand the basic project structure:
251
269
  genlayer-example/
252
270
  ├── contracts/ # Contract definitions
253
271
  │ └── storage.py # Example storage contract
254
- └── test/ # Test files
255
- └── test_contract.py # Contract test cases
272
+ ├── test/ # Test files
273
+ └── test_contract.py # Contract test cases
274
+ └── gltest.config.yaml # Configuration file
256
275
  ```
257
276
 
258
277
  ### Storage Contract Example
@@ -311,7 +330,6 @@ def test_deployment():
311
330
  args=["initial_value"], # Constructor arguments
312
331
  account=get_default_account(), # Account to deploy from
313
332
  consensus_max_rotations=3, # Optional: max consensus rotations
314
- leader_only=False, # Optional: whether to run only on leader
315
333
  )
316
334
 
317
335
  # Contract is now deployed and ready to use
@@ -320,7 +338,7 @@ def test_deployment():
320
338
 
321
339
  ### Read Methods
322
340
 
323
- Reading from the contract is straightforward:
341
+ Reading from the contract requires calling `.call()` on the method:
324
342
 
325
343
  ```python
326
344
  from gltest import get_contract_factory
@@ -332,7 +350,7 @@ def test_read_methods():
332
350
  contract = factory.deploy()
333
351
 
334
352
  # Call a read-only method
335
- result = contract.get_value(args=[])
353
+ result = contract.get_storage(args=[]).call()
336
354
 
337
355
  # Assert the result matches the initial value
338
356
  assert result == "initial_value"
@@ -340,7 +358,7 @@ def test_read_methods():
340
358
 
341
359
  ### Write Methods
342
360
 
343
- Writing to the contract requires transaction handling:
361
+ Writing to the contract requires calling `.transact()` on the method. Method arguments are passed to the write method, while transaction parameters are passed to `.transact()`:
344
362
 
345
363
  ```python
346
364
  from gltest import get_contract_factory
@@ -354,9 +372,9 @@ def test_write_methods():
354
372
  # Call a write method with arguments
355
373
  tx_receipt = contract.update_storage(
356
374
  args=["new_value"], # Method arguments
375
+ ).transact(
357
376
  value=0, # Optional: amount of native currency to send
358
377
  consensus_max_rotations=3, # Optional: max consensus rotations
359
- leader_only=False, # Optional: whether to run only on leader
360
378
  wait_interval=1, # Optional: seconds between status checks
361
379
  wait_retries=10, # Optional: max number of retries
362
380
  )
@@ -365,7 +383,7 @@ def test_write_methods():
365
383
  assert tx_execution_succeeded(tx_receipt)
366
384
 
367
385
  # Verify the value was updated
368
- assert contract.get_storage() == "new_value"
386
+ assert contract.get_storage().call() == "new_value"
369
387
  ```
370
388
 
371
389
  ### Assertions
@@ -503,6 +521,50 @@ Fixtures help maintain clean, DRY test code by:
503
521
  - Ensuring consistent test environments
504
522
  - Managing resource cleanup automatically
505
523
  - Providing appropriate scoping for performance
524
+ ### Statistical Analysis with `.analyze()`
525
+
526
+ The GenLayer Testing Suite provides a powerful `.analyze()` method for write operations that performs statistical analysis through multiple simulation runs. This is particularly useful for testing LLM-based contracts where outputs may vary:
527
+
528
+ ```python
529
+ from gltest import get_contract_factory
530
+
531
+ def test_analyze_method():
532
+ factory = get_contract_factory("LlmContract")
533
+ contract = factory.deploy()
534
+
535
+ # Analyze a write method's behavior across multiple runs
536
+ analysis = contract.process_with_llm(args=["input_data"]).analyze(
537
+ provider="openai", # LLM provider
538
+ model="gpt-4o", # Model to use
539
+ runs=100, # Number of simulation runs (default: 100)
540
+ config=None, # Optional: provider-specific config
541
+ plugin=None, # Optional: plugin name
542
+ plugin_config=None, # Optional: plugin configuration
543
+ )
544
+
545
+ # Access analysis results
546
+ print(f"Method: {analysis.method}")
547
+ print(f"Success rate: {analysis.success_rate:.2f}%")
548
+ print(f"Reliability score: {analysis.reliability_score:.2f}%")
549
+ print(f"Unique states: {analysis.unique_states}")
550
+ print(f"Execution time: {analysis.execution_time:.1f}s")
551
+
552
+ # The analysis returns a MethodStatsSummary object with:
553
+ # - method: The contract method name
554
+ # - args: Arguments passed to the method
555
+ # - total_runs: Total number of simulation runs
556
+ # - successful_runs: Number of successful executions
557
+ # - failed_runs: Number of failed executions
558
+ # - unique_states: Number of unique contract states observed
559
+ # - reliability_score: Percentage of runs with the most common state
560
+ # - execution_time: Total time for all simulations
561
+ ```
562
+
563
+ The `.analyze()` method helps you:
564
+ - Test non-deterministic contract methods
565
+ - Measure consistency of LLM-based operations
566
+ - Identify edge cases and failure patterns
567
+ - Benchmark performance across multiple runs
506
568
 
507
569
  ## 📝 Best Practices
508
570
 
@@ -546,6 +608,7 @@ Fixtures help maintain clean, DRY test code by:
546
608
  ```python
547
609
  tx_receipt = contract.set_value(
548
610
  args=["new_value"],
611
+ ).transact(
549
612
  wait_interval=2, # Increase wait interval between status checks
550
613
  wait_retries=20, # Increase number of retry attempts
551
614
  )
@@ -558,13 +621,11 @@ Fixtures help maintain clean, DRY test code by:
558
621
  # Try with increased consensus parameters
559
622
  contract = factory.deploy(
560
623
  consensus_max_rotations=5, # Increase number of consensus rotations
561
- leader_only=True, # Try leader-only mode for faster execution
562
624
  )
563
625
 
564
626
  # For critical operations, use more conservative settings
565
627
  contract = factory.deploy(
566
628
  consensus_max_rotations=10, # More rotations for better reliability
567
- leader_only=False, # Full consensus for better security
568
629
  wait_interval=3, # Longer wait between checks
569
630
  wait_retries=30 # More retries for consensus
570
631
  )
@@ -36,8 +36,8 @@ contract = factory.deploy(account=other_account)
36
36
  assert contract.account == other_account
37
37
 
38
38
  # Interact with the contract
39
- result = contract.get_value() # Read method
40
- tx_receipt = contract.set_value(args=["new_value"]) # Write method
39
+ result = contract.get_value().call() # Read method
40
+ tx_receipt = contract.set_value(args=["new_value"]).transact() # Write method
41
41
 
42
42
  assert tx_execution_succeeded(tx_receipt)
43
43
  ```
@@ -91,6 +91,7 @@ networks:
91
91
 
92
92
  localnet: # Local development network configuration
93
93
  url: "http://127.0.0.1:4000/api"
94
+ leader_only: false # Set to true to run all contracts in leader-only mode by default
94
95
 
95
96
  testnet_asimov: # Test network configuration
96
97
  id: 4221
@@ -102,6 +103,7 @@ networks:
102
103
 
103
104
  paths:
104
105
  contracts: "contracts" # Path to your contracts directory
106
+ artifacts: "artifacts" # Path to your artifacts directory
105
107
 
106
108
  environment: .env # Path to your environment file containing private keys and other secrets
107
109
  ```
@@ -114,12 +116,14 @@ Key configuration sections:
114
116
  - `url`: The RPC endpoint for the network
115
117
  - `id`: Chain ID
116
118
  - `accounts`: List of account private keys (using environment variables)
119
+ - `leader_only`: Leader only mode
117
120
  - Special case for `localnet`:
118
121
  - If a network is named `localnet`, missing fields will be filled with default values
119
122
  - For all other network names, `id`, `url`, and `accounts` are required fields
120
123
 
121
124
  2. **Paths**: Define important directory paths
122
125
  - `contracts`: Location of your contract files
126
+ - `artifacts`: Location of your artifacts files (analysis results will be stored here)
123
127
 
124
128
  3. **Environment**: Path to your `.env` file containing sensitive information like private keys
125
129
 
@@ -208,6 +212,20 @@ def test_with_mocked_llm(setup_validators):
208
212
 
209
213
  Note: This feature is only available when running tests on localnet.
210
214
 
215
+ 11. Run tests with leader-only mode enabled
216
+ ```bash
217
+ $ gltest --leader-only
218
+ ```
219
+ The `--leader-only` flag configures all contract deployments and write operations to run only on the leader node. This is useful for:
220
+ - Faster test execution by avoiding consensus
221
+ - Testing specific leader-only scenarios
222
+ - Development and debugging purposes
223
+ - Reducing computational overhead in test environments
224
+
225
+ When this flag is enabled, all contracts deployed and all write transactions will automatically use leader-only mode, regardless of individual method parameters.
226
+
227
+ **Note:** Leader-only mode is only available for studio-based networks (localhost, 127.0.0.1, *.genlayer.com, *.genlayerlabs.com). When enabled on other networks, it will have no effect and a warning will be logged.
228
+
211
229
  ## 🚀 Key Features
212
230
 
213
231
  - **Pytest Integration** – Extends pytest to support intelligent contract testing, making it familiar and easy to adopt.
@@ -228,8 +246,9 @@ Before diving into the examples, let's understand the basic project structure:
228
246
  genlayer-example/
229
247
  ├── contracts/ # Contract definitions
230
248
  │ └── storage.py # Example storage contract
231
- └── test/ # Test files
232
- └── test_contract.py # Contract test cases
249
+ ├── test/ # Test files
250
+ └── test_contract.py # Contract test cases
251
+ └── gltest.config.yaml # Configuration file
233
252
  ```
234
253
 
235
254
  ### Storage Contract Example
@@ -288,7 +307,6 @@ def test_deployment():
288
307
  args=["initial_value"], # Constructor arguments
289
308
  account=get_default_account(), # Account to deploy from
290
309
  consensus_max_rotations=3, # Optional: max consensus rotations
291
- leader_only=False, # Optional: whether to run only on leader
292
310
  )
293
311
 
294
312
  # Contract is now deployed and ready to use
@@ -297,7 +315,7 @@ def test_deployment():
297
315
 
298
316
  ### Read Methods
299
317
 
300
- Reading from the contract is straightforward:
318
+ Reading from the contract requires calling `.call()` on the method:
301
319
 
302
320
  ```python
303
321
  from gltest import get_contract_factory
@@ -309,7 +327,7 @@ def test_read_methods():
309
327
  contract = factory.deploy()
310
328
 
311
329
  # Call a read-only method
312
- result = contract.get_value(args=[])
330
+ result = contract.get_storage(args=[]).call()
313
331
 
314
332
  # Assert the result matches the initial value
315
333
  assert result == "initial_value"
@@ -317,7 +335,7 @@ def test_read_methods():
317
335
 
318
336
  ### Write Methods
319
337
 
320
- Writing to the contract requires transaction handling:
338
+ Writing to the contract requires calling `.transact()` on the method. Method arguments are passed to the write method, while transaction parameters are passed to `.transact()`:
321
339
 
322
340
  ```python
323
341
  from gltest import get_contract_factory
@@ -331,9 +349,9 @@ def test_write_methods():
331
349
  # Call a write method with arguments
332
350
  tx_receipt = contract.update_storage(
333
351
  args=["new_value"], # Method arguments
352
+ ).transact(
334
353
  value=0, # Optional: amount of native currency to send
335
354
  consensus_max_rotations=3, # Optional: max consensus rotations
336
- leader_only=False, # Optional: whether to run only on leader
337
355
  wait_interval=1, # Optional: seconds between status checks
338
356
  wait_retries=10, # Optional: max number of retries
339
357
  )
@@ -342,7 +360,7 @@ def test_write_methods():
342
360
  assert tx_execution_succeeded(tx_receipt)
343
361
 
344
362
  # Verify the value was updated
345
- assert contract.get_storage() == "new_value"
363
+ assert contract.get_storage().call() == "new_value"
346
364
  ```
347
365
 
348
366
  ### Assertions
@@ -480,6 +498,50 @@ Fixtures help maintain clean, DRY test code by:
480
498
  - Ensuring consistent test environments
481
499
  - Managing resource cleanup automatically
482
500
  - Providing appropriate scoping for performance
501
+ ### Statistical Analysis with `.analyze()`
502
+
503
+ The GenLayer Testing Suite provides a powerful `.analyze()` method for write operations that performs statistical analysis through multiple simulation runs. This is particularly useful for testing LLM-based contracts where outputs may vary:
504
+
505
+ ```python
506
+ from gltest import get_contract_factory
507
+
508
+ def test_analyze_method():
509
+ factory = get_contract_factory("LlmContract")
510
+ contract = factory.deploy()
511
+
512
+ # Analyze a write method's behavior across multiple runs
513
+ analysis = contract.process_with_llm(args=["input_data"]).analyze(
514
+ provider="openai", # LLM provider
515
+ model="gpt-4o", # Model to use
516
+ runs=100, # Number of simulation runs (default: 100)
517
+ config=None, # Optional: provider-specific config
518
+ plugin=None, # Optional: plugin name
519
+ plugin_config=None, # Optional: plugin configuration
520
+ )
521
+
522
+ # Access analysis results
523
+ print(f"Method: {analysis.method}")
524
+ print(f"Success rate: {analysis.success_rate:.2f}%")
525
+ print(f"Reliability score: {analysis.reliability_score:.2f}%")
526
+ print(f"Unique states: {analysis.unique_states}")
527
+ print(f"Execution time: {analysis.execution_time:.1f}s")
528
+
529
+ # The analysis returns a MethodStatsSummary object with:
530
+ # - method: The contract method name
531
+ # - args: Arguments passed to the method
532
+ # - total_runs: Total number of simulation runs
533
+ # - successful_runs: Number of successful executions
534
+ # - failed_runs: Number of failed executions
535
+ # - unique_states: Number of unique contract states observed
536
+ # - reliability_score: Percentage of runs with the most common state
537
+ # - execution_time: Total time for all simulations
538
+ ```
539
+
540
+ The `.analyze()` method helps you:
541
+ - Test non-deterministic contract methods
542
+ - Measure consistency of LLM-based operations
543
+ - Identify edge cases and failure patterns
544
+ - Benchmark performance across multiple runs
483
545
 
484
546
  ## 📝 Best Practices
485
547
 
@@ -523,6 +585,7 @@ Fixtures help maintain clean, DRY test code by:
523
585
  ```python
524
586
  tx_receipt = contract.set_value(
525
587
  args=["new_value"],
588
+ ).transact(
526
589
  wait_interval=2, # Increase wait interval between status checks
527
590
  wait_retries=20, # Increase number of retry attempts
528
591
  )
@@ -535,13 +598,11 @@ Fixtures help maintain clean, DRY test code by:
535
598
  # Try with increased consensus parameters
536
599
  contract = factory.deploy(
537
600
  consensus_max_rotations=5, # Increase number of consensus rotations
538
- leader_only=True, # Try leader-only mode for faster execution
539
601
  )
540
602
 
541
603
  # For critical operations, use more conservative settings
542
604
  contract = factory.deploy(
543
605
  consensus_max_rotations=10, # More rotations for better reliability
544
- leader_only=False, # Full consensus for better security
545
606
  wait_interval=3, # Longer wait between checks
546
607
  wait_retries=30 # More retries for consensus
547
608
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: genlayer-test
3
- Version: 0.4.1
3
+ Version: 2.0.0
4
4
  Summary: GenLayer Testing Suite
5
5
  Author: GenLayer
6
6
  License-Expression: MIT
@@ -15,7 +15,7 @@ Description-Content-Type: text/markdown
15
15
  License-File: LICENSE
16
16
  Requires-Dist: pytest
17
17
  Requires-Dist: setuptools>=77.0
18
- Requires-Dist: genlayer-py==0.6.1
18
+ Requires-Dist: genlayer-py==0.7.2
19
19
  Requires-Dist: colorama>=0.4.6
20
20
  Requires-Dist: pyyaml
21
21
  Requires-Dist: python-dotenv
@@ -59,8 +59,8 @@ contract = factory.deploy(account=other_account)
59
59
  assert contract.account == other_account
60
60
 
61
61
  # Interact with the contract
62
- result = contract.get_value() # Read method
63
- tx_receipt = contract.set_value(args=["new_value"]) # Write method
62
+ result = contract.get_value().call() # Read method
63
+ tx_receipt = contract.set_value(args=["new_value"]).transact() # Write method
64
64
 
65
65
  assert tx_execution_succeeded(tx_receipt)
66
66
  ```
@@ -114,6 +114,7 @@ networks:
114
114
 
115
115
  localnet: # Local development network configuration
116
116
  url: "http://127.0.0.1:4000/api"
117
+ leader_only: false # Set to true to run all contracts in leader-only mode by default
117
118
 
118
119
  testnet_asimov: # Test network configuration
119
120
  id: 4221
@@ -125,6 +126,7 @@ networks:
125
126
 
126
127
  paths:
127
128
  contracts: "contracts" # Path to your contracts directory
129
+ artifacts: "artifacts" # Path to your artifacts directory
128
130
 
129
131
  environment: .env # Path to your environment file containing private keys and other secrets
130
132
  ```
@@ -137,12 +139,14 @@ Key configuration sections:
137
139
  - `url`: The RPC endpoint for the network
138
140
  - `id`: Chain ID
139
141
  - `accounts`: List of account private keys (using environment variables)
142
+ - `leader_only`: Leader only mode
140
143
  - Special case for `localnet`:
141
144
  - If a network is named `localnet`, missing fields will be filled with default values
142
145
  - For all other network names, `id`, `url`, and `accounts` are required fields
143
146
 
144
147
  2. **Paths**: Define important directory paths
145
148
  - `contracts`: Location of your contract files
149
+ - `artifacts`: Location of your artifacts files (analysis results will be stored here)
146
150
 
147
151
  3. **Environment**: Path to your `.env` file containing sensitive information like private keys
148
152
 
@@ -231,6 +235,20 @@ def test_with_mocked_llm(setup_validators):
231
235
 
232
236
  Note: This feature is only available when running tests on localnet.
233
237
 
238
+ 11. Run tests with leader-only mode enabled
239
+ ```bash
240
+ $ gltest --leader-only
241
+ ```
242
+ The `--leader-only` flag configures all contract deployments and write operations to run only on the leader node. This is useful for:
243
+ - Faster test execution by avoiding consensus
244
+ - Testing specific leader-only scenarios
245
+ - Development and debugging purposes
246
+ - Reducing computational overhead in test environments
247
+
248
+ When this flag is enabled, all contracts deployed and all write transactions will automatically use leader-only mode, regardless of individual method parameters.
249
+
250
+ **Note:** Leader-only mode is only available for studio-based networks (localhost, 127.0.0.1, *.genlayer.com, *.genlayerlabs.com). When enabled on other networks, it will have no effect and a warning will be logged.
251
+
234
252
  ## 🚀 Key Features
235
253
 
236
254
  - **Pytest Integration** – Extends pytest to support intelligent contract testing, making it familiar and easy to adopt.
@@ -251,8 +269,9 @@ Before diving into the examples, let's understand the basic project structure:
251
269
  genlayer-example/
252
270
  ├── contracts/ # Contract definitions
253
271
  │ └── storage.py # Example storage contract
254
- └── test/ # Test files
255
- └── test_contract.py # Contract test cases
272
+ ├── test/ # Test files
273
+ └── test_contract.py # Contract test cases
274
+ └── gltest.config.yaml # Configuration file
256
275
  ```
257
276
 
258
277
  ### Storage Contract Example
@@ -311,7 +330,6 @@ def test_deployment():
311
330
  args=["initial_value"], # Constructor arguments
312
331
  account=get_default_account(), # Account to deploy from
313
332
  consensus_max_rotations=3, # Optional: max consensus rotations
314
- leader_only=False, # Optional: whether to run only on leader
315
333
  )
316
334
 
317
335
  # Contract is now deployed and ready to use
@@ -320,7 +338,7 @@ def test_deployment():
320
338
 
321
339
  ### Read Methods
322
340
 
323
- Reading from the contract is straightforward:
341
+ Reading from the contract requires calling `.call()` on the method:
324
342
 
325
343
  ```python
326
344
  from gltest import get_contract_factory
@@ -332,7 +350,7 @@ def test_read_methods():
332
350
  contract = factory.deploy()
333
351
 
334
352
  # Call a read-only method
335
- result = contract.get_value(args=[])
353
+ result = contract.get_storage(args=[]).call()
336
354
 
337
355
  # Assert the result matches the initial value
338
356
  assert result == "initial_value"
@@ -340,7 +358,7 @@ def test_read_methods():
340
358
 
341
359
  ### Write Methods
342
360
 
343
- Writing to the contract requires transaction handling:
361
+ Writing to the contract requires calling `.transact()` on the method. Method arguments are passed to the write method, while transaction parameters are passed to `.transact()`:
344
362
 
345
363
  ```python
346
364
  from gltest import get_contract_factory
@@ -354,9 +372,9 @@ def test_write_methods():
354
372
  # Call a write method with arguments
355
373
  tx_receipt = contract.update_storage(
356
374
  args=["new_value"], # Method arguments
375
+ ).transact(
357
376
  value=0, # Optional: amount of native currency to send
358
377
  consensus_max_rotations=3, # Optional: max consensus rotations
359
- leader_only=False, # Optional: whether to run only on leader
360
378
  wait_interval=1, # Optional: seconds between status checks
361
379
  wait_retries=10, # Optional: max number of retries
362
380
  )
@@ -365,7 +383,7 @@ def test_write_methods():
365
383
  assert tx_execution_succeeded(tx_receipt)
366
384
 
367
385
  # Verify the value was updated
368
- assert contract.get_storage() == "new_value"
386
+ assert contract.get_storage().call() == "new_value"
369
387
  ```
370
388
 
371
389
  ### Assertions
@@ -503,6 +521,50 @@ Fixtures help maintain clean, DRY test code by:
503
521
  - Ensuring consistent test environments
504
522
  - Managing resource cleanup automatically
505
523
  - Providing appropriate scoping for performance
524
+ ### Statistical Analysis with `.analyze()`
525
+
526
+ The GenLayer Testing Suite provides a powerful `.analyze()` method for write operations that performs statistical analysis through multiple simulation runs. This is particularly useful for testing LLM-based contracts where outputs may vary:
527
+
528
+ ```python
529
+ from gltest import get_contract_factory
530
+
531
+ def test_analyze_method():
532
+ factory = get_contract_factory("LlmContract")
533
+ contract = factory.deploy()
534
+
535
+ # Analyze a write method's behavior across multiple runs
536
+ analysis = contract.process_with_llm(args=["input_data"]).analyze(
537
+ provider="openai", # LLM provider
538
+ model="gpt-4o", # Model to use
539
+ runs=100, # Number of simulation runs (default: 100)
540
+ config=None, # Optional: provider-specific config
541
+ plugin=None, # Optional: plugin name
542
+ plugin_config=None, # Optional: plugin configuration
543
+ )
544
+
545
+ # Access analysis results
546
+ print(f"Method: {analysis.method}")
547
+ print(f"Success rate: {analysis.success_rate:.2f}%")
548
+ print(f"Reliability score: {analysis.reliability_score:.2f}%")
549
+ print(f"Unique states: {analysis.unique_states}")
550
+ print(f"Execution time: {analysis.execution_time:.1f}s")
551
+
552
+ # The analysis returns a MethodStatsSummary object with:
553
+ # - method: The contract method name
554
+ # - args: Arguments passed to the method
555
+ # - total_runs: Total number of simulation runs
556
+ # - successful_runs: Number of successful executions
557
+ # - failed_runs: Number of failed executions
558
+ # - unique_states: Number of unique contract states observed
559
+ # - reliability_score: Percentage of runs with the most common state
560
+ # - execution_time: Total time for all simulations
561
+ ```
562
+
563
+ The `.analyze()` method helps you:
564
+ - Test non-deterministic contract methods
565
+ - Measure consistency of LLM-based operations
566
+ - Identify edge cases and failure patterns
567
+ - Benchmark performance across multiple runs
506
568
 
507
569
  ## 📝 Best Practices
508
570
 
@@ -546,6 +608,7 @@ Fixtures help maintain clean, DRY test code by:
546
608
  ```python
547
609
  tx_receipt = contract.set_value(
548
610
  args=["new_value"],
611
+ ).transact(
549
612
  wait_interval=2, # Increase wait interval between status checks
550
613
  wait_retries=20, # Increase number of retry attempts
551
614
  )
@@ -558,13 +621,11 @@ Fixtures help maintain clean, DRY test code by:
558
621
  # Try with increased consensus parameters
559
622
  contract = factory.deploy(
560
623
  consensus_max_rotations=5, # Increase number of consensus rotations
561
- leader_only=True, # Try leader-only mode for faster execution
562
624
  )
563
625
 
564
626
  # For critical operations, use more conservative settings
565
627
  contract = factory.deploy(
566
628
  consensus_max_rotations=10, # More rotations for better reliability
567
- leader_only=False, # Full consensus for better security
568
629
  wait_interval=3, # Longer wait between checks
569
630
  wait_retries=30 # More retries for consensus
570
631
  )
@@ -8,17 +8,22 @@ genlayer_test.egg-info/entry_points.txt
8
8
  genlayer_test.egg-info/requires.txt
9
9
  genlayer_test.egg-info/top_level.txt
10
10
  gltest/__init__.py
11
+ gltest/accounts.py
11
12
  gltest/assertions.py
13
+ gltest/clients.py
12
14
  gltest/exceptions.py
13
15
  gltest/fixtures.py
14
16
  gltest/logging.py
15
17
  gltest/types.py
16
18
  gltest/artifacts/__init__.py
17
19
  gltest/artifacts/contract.py
18
- gltest/glchain/__init__.py
19
- gltest/glchain/account.py
20
- gltest/glchain/client.py
21
- gltest/glchain/contract.py
20
+ gltest/contracts/__init__.py
21
+ gltest/contracts/contract.py
22
+ gltest/contracts/contract_factory.py
23
+ gltest/contracts/contract_functions.py
24
+ gltest/contracts/method_stats.py
25
+ gltest/contracts/stats_collector.py
26
+ gltest/contracts/utils.py
22
27
  gltest/helpers/__init__.py
23
28
  gltest/helpers/fixture_snapshot.py
24
29
  gltest/helpers/take_snapshot.py
@@ -28,6 +33,7 @@ gltest_cli/config/__init__.py
28
33
  gltest_cli/config/constants.py
29
34
  gltest_cli/config/general.py
30
35
  gltest_cli/config/plugin.py
36
+ gltest_cli/config/pytest_context.py
31
37
  gltest_cli/config/types.py
32
38
  gltest_cli/config/user.py
33
39
  tests/__init__.py
@@ -48,6 +54,7 @@ tests/examples/contracts/multi_file_contract/other.py
48
54
  tests/examples/tests/test_football_prediction_market.py
49
55
  tests/examples/tests/test_intelligent_oracle_factory.py
50
56
  tests/examples/tests/test_llm_erc20.py
57
+ tests/examples/tests/test_llm_erc20_analyze.py
51
58
  tests/examples/tests/test_log_indexer.py
52
59
  tests/examples/tests/test_multi_file_contract.py
53
60
  tests/examples/tests/test_multi_file_contract_legacy.py
@@ -66,5 +73,7 @@ tests/gltest/artifact/contracts/duplicate_ic_contract_2.py
66
73
  tests/gltest/artifact/contracts/not_ic_contract.py
67
74
  tests/gltest/assertions/test_assertions.py
68
75
  tests/gltest_cli/__init__.py
76
+ tests/gltest_cli/config/test_config_integration.py
77
+ tests/gltest_cli/config/test_general_config.py
69
78
  tests/gltest_cli/config/test_plugin.py
70
79
  tests/gltest_cli/config/test_user.py
@@ -1,6 +1,6 @@
1
1
  pytest
2
2
  setuptools>=77.0
3
- genlayer-py==0.6.1
3
+ genlayer-py==0.7.2
4
4
  colorama>=0.4.6
5
5
  pyyaml
6
6
  python-dotenv