genlayer-test 0.1.0b6__py3-none-any.whl → 0.1.2__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 (46) hide show
  1. {genlayer_test-0.1.0b6.dist-info → genlayer_test-0.1.2.dist-info}/METADATA +19 -2
  2. genlayer_test-0.1.2.dist-info/RECORD +53 -0
  3. {genlayer_test-0.1.0b6.dist-info → genlayer_test-0.1.2.dist-info}/WHEEL +1 -1
  4. gltest/artifacts/__init__.py +1 -1
  5. gltest/artifacts/contract.py +14 -5
  6. gltest/assertions.py +4 -3
  7. gltest/exceptions.py +9 -1
  8. gltest/glchain/account.py +1 -0
  9. gltest/helpers/__init__.py +1 -1
  10. gltest/helpers/fixture_snapshot.py +9 -1
  11. tests/artifact/contracts/not_ic_contract.py +22 -0
  12. tests/artifact/test_contract_definition.py +92 -0
  13. tests/assertions/test_assertions.py +31 -0
  14. tests/examples/contracts/football_prediction_market.py +97 -0
  15. tests/examples/contracts/intelligent_oracle.py +369 -0
  16. tests/examples/contracts/intelligent_oracle_factory.py +47 -0
  17. tests/examples/contracts/llm_erc20.py +69 -0
  18. tests/examples/contracts/log_indexer.py +67 -0
  19. tests/examples/contracts/multi_file_contract/__init__.py +20 -0
  20. tests/examples/contracts/multi_file_contract/other.py +14 -0
  21. tests/examples/contracts/multi_read_erc20.py +28 -0
  22. tests/examples/contracts/multi_tenant_storage.py +48 -0
  23. tests/examples/contracts/read_erc20.py +14 -0
  24. tests/examples/contracts/storage.py +22 -0
  25. tests/examples/contracts/user_storage.py +24 -0
  26. tests/examples/contracts/wizard_of_coin.py +56 -0
  27. tests/examples/tests/test_football_prediction_market.py +19 -0
  28. tests/examples/tests/test_intelligent_oracle_factory.py +127 -0
  29. tests/examples/tests/test_llm_erc20.py +41 -0
  30. tests/examples/tests/test_log_indexer.py +63 -0
  31. tests/examples/tests/test_multi_file_contract.py +15 -0
  32. tests/examples/tests/test_multi_file_contract_legacy.py +15 -0
  33. tests/examples/tests/test_multi_read_erc20.py +85 -0
  34. tests/examples/tests/test_multi_tenant_storage.py +58 -0
  35. tests/examples/tests/test_read_erc20.py +37 -0
  36. tests/examples/tests/test_storage.py +23 -0
  37. tests/examples/tests/test_storage_legacy.py +23 -0
  38. tests/examples/tests/test_user_storage.py +57 -0
  39. tests/examples/tests/test_wizard_of_coin.py +12 -0
  40. tests/plugin/conftest.py +1 -0
  41. genlayer_test-0.1.0b6.dist-info/RECORD +0 -24
  42. tests/conftest.py +0 -1
  43. {genlayer_test-0.1.0b6.dist-info → genlayer_test-0.1.2.dist-info}/entry_points.txt +0 -0
  44. {genlayer_test-0.1.0b6.dist-info → genlayer_test-0.1.2.dist-info}/licenses/LICENSE +0 -0
  45. {genlayer_test-0.1.0b6.dist-info → genlayer_test-0.1.2.dist-info}/top_level.txt +0 -0
  46. /tests/{test_plugin_hooks.py → plugin/test_plugin_hooks.py} +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: genlayer-test
3
- Version: 0.1.0b6
3
+ Version: 0.1.2
4
4
  Summary: GenLayer Testing Suite
5
5
  Author: GenLayer
6
6
  License-Expression: MIT
@@ -16,7 +16,7 @@ Requires-Python: >=3.8
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Requires-Dist: pytest
19
- Requires-Dist: genlayer-py==0.1.0b1
19
+ Requires-Dist: genlayer-py==0.3.0
20
20
  Dynamic: license-file
21
21
 
22
22
  # GenLayer Testing Suite
@@ -128,6 +128,21 @@ $ gltest -v
128
128
  $ gltest --contracts-dir <path_to_contracts>
129
129
  ```
130
130
 
131
+ 6. Run tests with a custom RPC url
132
+ ```bash
133
+ $ gltest --rpc-url <custom_rpc_url>
134
+ ```
135
+
136
+ 6. Run tests with a default wait interval for waiting transaction receipts
137
+ ```bash
138
+ $ gltest --default-wait-interval <default_wait_interval>
139
+ ```
140
+
141
+ 6. Run tests with a default wait retries for waiting transaction receipts
142
+ ```bash
143
+ $ gltest --default-wait-retries <default_wait_retries>
144
+ ```
145
+
131
146
  ## 🚀 Key Features
132
147
 
133
148
  - **Pytest Integration** – Extends pytest to support intelligent contract testing, making it familiar and easy to adopt.
@@ -264,6 +279,8 @@ def test_write_methods():
264
279
  assert contract.get_storage() == "new_value"
265
280
  ```
266
281
 
282
+ For more example contracts, check out the [contracts directory](tests/examples/contracts) which contains various sample contracts demonstrating different features and use cases.
283
+
267
284
  ## 📝 Best Practices
268
285
 
269
286
  1. **Test Organization**
@@ -0,0 +1,53 @@
1
+ genlayer_test-0.1.2.dist-info/licenses/LICENSE,sha256=che_H4vE0QUx3HvWrAa1_jDEVInift0U6VO15-QqEls,1064
2
+ gltest/__init__.py,sha256=AK_YfRvwlhrOheOelUG8qIRG17on0-nFCF747dopg2w,332
3
+ gltest/assertions.py,sha256=dBjiK5-LuxrrktkNDP7n-t6i43UNCL_cq7M4BLqRyFk,678
4
+ gltest/exceptions.py,sha256=deJPmrTe5gF33qkkKF2IVJY7lc_knI7Ql3N7jZ8aLZs,510
5
+ gltest/plugin_config.py,sha256=8Z97RtEJ89OcRbki_oRuBBVct_q56BFmKvthan1y9Y4,840
6
+ gltest/plugin_hooks.py,sha256=py1rzIR9QSsFOt8SEePPL96e-8DeiPFxvcPZurRlExM,1436
7
+ gltest/types.py,sha256=BODmwTr2gAUEiO9FjiuTiWwuKvXgo4xZWstQWNUfnlw,156
8
+ gltest/artifacts/__init__.py,sha256=qiJN5F1cVh_3fmxZeDFznoABxAdLhLqBfUUKwqXqvgo,87
9
+ gltest/artifacts/contract.py,sha256=CBRfUTltKv2tPy--LcmVbP_4hbXYt9VrunvJlMzNd5s,3566
10
+ gltest/glchain/__init__.py,sha256=X-mEbREoAOe9K4n74C55gCiXH4wItzY5HTJcg3_F3mI,412
11
+ gltest/glchain/account.py,sha256=ZxYsfbtBXKVC5vV4pko3yyL6lhPljqIb68NgIgvInSc,403
12
+ gltest/glchain/client.py,sha256=q04LIQy5SCIrYZflZiTapfeQ-AaSTa0w369ehnVbJLM,532
13
+ gltest/glchain/contract.py,sha256=1pd4eAQlHXjnRF7hBvnoR-9f-HORUaYKVyV5P42io4o,8747
14
+ gltest/helpers/__init__.py,sha256=I7HiTu_H7_hP65zY6Wl02r-5eAMr2eZvqBVmusuQLX4,180
15
+ gltest/helpers/fixture_snapshot.py,sha256=DWLTsMbTnfhpv0_7_gkJpDKX4hJx-tlruX7x3FWL6UI,2073
16
+ gltest/helpers/take_snapshot.py,sha256=eXqEKXM2hcox3pLGIcNddobU8zXPQvD-Iwf87eHqW2s,1276
17
+ gltest_cli/main.py,sha256=Ti2-0Ev1x5_cM0D1UKqdgaDt80CDHEQGtdRne2qLm4M,53
18
+ tests/artifact/test_contract_definition.py,sha256=8X829MsNfEObtIMmotk6nRVLDEp5KfJE6zrAK4IPfCc,3323
19
+ tests/artifact/contracts/not_ic_contract.py,sha256=hQyGnYiiVceYdLI2WrvcFgPqzy1S4-YMb9FPhiHEGSA,510
20
+ tests/assertions/test_assertions.py,sha256=y1XE15908Rv3RjWNxU7DtRF2gEGM9eEiHPh9jJHbR4g,1046
21
+ tests/examples/contracts/football_prediction_market.py,sha256=kdouFijjeCdIJyaVJlgXcqbBAXecA9_YdhklSsIW-QM,3219
22
+ tests/examples/contracts/intelligent_oracle.py,sha256=WrNZWWoi1sz22Azt2EXgdWHDg5Ihca2pWUHrM9pVfQE,12319
23
+ tests/examples/contracts/intelligent_oracle_factory.py,sha256=ax496IZuDCA728rRcbjwTaM4Q4E-Y1jGkHsEcyf1cig,1490
24
+ tests/examples/contracts/llm_erc20.py,sha256=nfIs-7A79L46NgHQzWbPyEOUlzAlFLsf4K05acwKr_M,2523
25
+ tests/examples/contracts/log_indexer.py,sha256=VwMC8_Gy1Z1qjuy5GeEMyepjZ3Z5y7VAOrHMl5MrjxI,1852
26
+ tests/examples/contracts/multi_read_erc20.py,sha256=HsMJKGT9a9eZAO43Em7hCRfh1yyHDgcUbQ0gmOE1MXs,850
27
+ tests/examples/contracts/multi_tenant_storage.py,sha256=aGLPC76FegXdnIjMjeGsu3s3AbKK9dtV6t1d_KoI8rI,1897
28
+ tests/examples/contracts/read_erc20.py,sha256=kstiB93JHHajJe1GldzeawxnVYutjT8KE2d1bYTgggU,390
29
+ tests/examples/contracts/storage.py,sha256=GZHBXhjc94eEkdSO1UWgcop0fEo0hD57KZM0ds3pUFM,490
30
+ tests/examples/contracts/user_storage.py,sha256=j-RXxTIqb1dePYqP_pkeoCxxDq07VURryvzF_Q-sZmI,638
31
+ tests/examples/contracts/wizard_of_coin.py,sha256=BJ0Nv6N-JJP_Pk7YUSXPPRxX5_mDRBDlfL6nabeaoyA,1606
32
+ tests/examples/contracts/multi_file_contract/__init__.py,sha256=8O3BvoUrLSmc4uTf2jm7MyrmcaiGD0w8wPwotdAqZHQ,485
33
+ tests/examples/contracts/multi_file_contract/other.py,sha256=jHDtjUL3eAUgE6yOYKFw_RfAH7kIwk8CvxUjbWHNruk,236
34
+ tests/examples/tests/test_football_prediction_market.py,sha256=wFu024sq3IURLL1zyLyO_G1sRCjPTV7iImi87__dZ4Y,657
35
+ tests/examples/tests/test_intelligent_oracle_factory.py,sha256=Nw7jO9bjD79AETT2QQl0Vun-yxSAAuqGSdkQn2Y3WUw,5377
36
+ tests/examples/tests/test_llm_erc20.py,sha256=yL_5bbH2VC7jL3E6dDvSI6PfZ36bPtA4OxoysZpuLFc,1390
37
+ tests/examples/tests/test_log_indexer.py,sha256=Km44SiA8dlA4WBqwugXVBCQUlODdf1dB4p4nt24HG9k,2649
38
+ tests/examples/tests/test_multi_file_contract.py,sha256=pWmK6lcZrSAnDH09Z6Q-cXs8V6VGFhHkvgThvJKEB4U,512
39
+ tests/examples/tests/test_multi_file_contract_legacy.py,sha256=Jx_u0rDrQJspQgFo1KUddcFgTcOhcE-YLuLgk3tKrCA,527
40
+ tests/examples/tests/test_multi_read_erc20.py,sha256=Q3AKK7OZyTKRrG-tXmkPkoQOzQqVVDnFEWKDVVNVQLI,3062
41
+ tests/examples/tests/test_multi_tenant_storage.py,sha256=XNR1AUpxkzXlRv_ltdgAF-HUkpAvWqIQ7Fb93zEeR2o,2376
42
+ tests/examples/tests/test_read_erc20.py,sha256=_dXwdZoUTSMKwPhEmU3N2X3wNu2ke9ob0L3JKEyNjdE,1198
43
+ tests/examples/tests/test_storage.py,sha256=FmA-pJohMBHlNFVzLlY3-asnq0kV33E5SRDCM-lWzoQ,664
44
+ tests/examples/tests/test_storage_legacy.py,sha256=RNVnD0G9ilb4I2s0CPAAgJEuKUgEkkbItuesOfmv-pg,677
45
+ tests/examples/tests/test_user_storage.py,sha256=QEgt2p22LAyzBnBb0YW4BWa_Jasrt15vrr1GuxXqqbI,2180
46
+ tests/examples/tests/test_wizard_of_coin.py,sha256=aUDeV5w0XONMMS71Vzw80lHfcSM0z8RKPJSXAuDwRto,392
47
+ tests/plugin/conftest.py,sha256=RKdoE5_zcMimeojAoA_GSFI9du4pMzMi1vZ1njtfoAs,28
48
+ tests/plugin/test_plugin_hooks.py,sha256=FQOrkhoXLinq0sjvoYjr63Oqg-ZVPcNFeUrK4bqrn4E,2020
49
+ genlayer_test-0.1.2.dist-info/METADATA,sha256=05aK4xzg2NrGQIAcFkWS6NNzvFyxVkF_jCqSZhgk8po,13471
50
+ genlayer_test-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
51
+ genlayer_test-0.1.2.dist-info/entry_points.txt,sha256=rXhrPVq2IhVsd4uWzxzwCTx7jA1KcQIVNxDCUuxq4f8,89
52
+ genlayer_test-0.1.2.dist-info/top_level.txt,sha256=-qiGZxTRBytujzgVcKpxjvQ-WNeUDjXa59ceGMwMpko,24
53
+ genlayer_test-0.1.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.3.1)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,3 +1,3 @@
1
1
  from .contract import find_contract_definition
2
2
 
3
- __all__ = ["find_contract_definition"]
3
+ __all__ = ["find_contract_definition"]
@@ -20,7 +20,9 @@ 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
- for file_path in contracts_dir.rglob("*.gpy"):
23
+ for file_path in contracts_dir.rglob("*"):
24
+ if not file_path.suffix in [".gpy", ".py"]:
25
+ continue
24
26
  try:
25
27
  # Read the file content
26
28
  with open(file_path, "r") as f:
@@ -30,8 +32,15 @@ def search_path_by_class_name(contracts_dir: Path, contract_name: str) -> Path:
30
32
  # Search for class definitions
31
33
  for node in ast.walk(tree):
32
34
  if isinstance(node, ast.ClassDef) and node.name == contract_name:
33
- # Found the contract class
34
- return file_path
35
+ # Check if the class directly inherits from gl.Contract
36
+ for base in node.bases:
37
+ if isinstance(base, ast.Attribute):
38
+ if (
39
+ isinstance(base.value, ast.Name)
40
+ and base.value.id == "gl"
41
+ and base.attr == "Contract"
42
+ ):
43
+ return file_path
35
44
  except Exception as e:
36
45
  raise ValueError(f"Error reading file {file_path}: {e}")
37
46
  raise FileNotFoundError(f"Contract {contract_name} not found at: {contracts_dir}")
@@ -53,7 +62,7 @@ def compute_contract_code(
53
62
  with zipfile.ZipFile(buffer, mode="w") as zip:
54
63
  zip.write(main_file_path, "contract/__init__.py")
55
64
  for file_path in main_file_dir.rglob("*"):
56
- if file_path.name in ["runner.json", "__init__.gpy"]:
65
+ if file_path.name in ["runner.json", "__init__.py"]:
57
66
  continue
58
67
  rel_path = file_path.relative_to(main_file_dir)
59
68
  zip.write(file_path, f"contract/{rel_path}")
@@ -72,7 +81,7 @@ def find_contract_definition(contract_name: str) -> Optional[ContractDefinition]
72
81
  main_file_path = search_path_by_class_name(contracts_dir, contract_name)
73
82
  main_file_dir = main_file_path.parent
74
83
  runner_file_path = None
75
- if main_file_path.name == "__init__.gpy":
84
+ if main_file_path.name in ["__init__.py", "__init__.gpy"]:
76
85
  # Likely a multifile contract
77
86
  runner_file_path = main_file_dir.joinpath("runner.json")
78
87
  if not runner_file_path.exists():
gltest/assertions.py CHANGED
@@ -6,12 +6,13 @@ def tx_execution_succeeded(result: GenLayerTransaction) -> bool:
6
6
  return False
7
7
  if "leader_receipt" not in result["consensus_data"]:
8
8
  return False
9
- if "execution_result" not in result["consensus_data"]["leader_receipt"]:
9
+ if len(result["consensus_data"]["leader_receipt"]) == 0:
10
10
  return False
11
- execution_result = result["consensus_data"]["leader_receipt"]["execution_result"]
11
+ if "execution_result" not in result["consensus_data"]["leader_receipt"][0]:
12
+ return False
13
+ execution_result = result["consensus_data"]["leader_receipt"][0]["execution_result"]
12
14
  return execution_result == "SUCCESS"
13
15
 
14
16
 
15
17
  def tx_execution_failed(result: GenLayerTransaction) -> bool:
16
18
  return not tx_execution_succeeded(result)
17
-
gltest/exceptions.py CHANGED
@@ -2,19 +2,27 @@ class DeploymentError(Exception):
2
2
  """Raised when a contract deployment fails."""
3
3
 
4
4
  pass
5
+
6
+
5
7
  class FixtureSnapshotError(Exception):
6
8
  """Raised when there's an error restoring a snapshot."""
9
+
7
10
  pass
8
11
 
12
+
9
13
  class FixtureAnonymousFunctionError(Exception):
10
14
  """Raised when a fixture is an anonymous function."""
15
+
11
16
  pass
12
17
 
18
+
13
19
  class InvalidSnapshotError(Exception):
14
20
  """Raised when a snapshot is invalid."""
21
+
15
22
  pass
16
23
 
24
+
17
25
  class HelperError(Exception):
18
26
  """Raised when a helper function fails."""
19
- pass
20
27
 
28
+ pass
gltest/glchain/account.py CHANGED
@@ -10,6 +10,7 @@ def create_accounts(n_accounts: int):
10
10
  accounts.append(create_account())
11
11
  return accounts
12
12
 
13
+
13
14
  # Accounts for testing
14
15
  accounts = create_accounts(n_accounts=10)
15
16
 
@@ -5,4 +5,4 @@ __all__ = [
5
5
  "take_snapshot",
6
6
  "load_fixture",
7
7
  "clear_snapshots",
8
- ]
8
+ ]
@@ -1,12 +1,15 @@
1
1
  from typing import TypeVar, Callable, List, Any
2
2
  from dataclasses import dataclass
3
+ from urllib.parse import urlparse
3
4
  from .take_snapshot import SnapshotRestorer, take_snapshot
4
5
  from gltest.exceptions import (
5
6
  FixtureSnapshotError,
6
7
  InvalidSnapshotError,
7
8
  FixtureAnonymousFunctionError,
8
9
  )
10
+ from gltest.plugin_config import get_rpc_url
9
11
 
12
+ SUPPORTED_RPC_DOMAINS = ["localhost", "127.0.0.1"]
10
13
 
11
14
  T = TypeVar("T")
12
15
 
@@ -31,6 +34,11 @@ def load_fixture(fixture: Callable[[], T]) -> T:
31
34
  if fixture.__name__ == "<lambda>":
32
35
  raise FixtureAnonymousFunctionError("Fixtures must be named functions")
33
36
 
37
+ rpc_url = get_rpc_url()
38
+ domain = urlparse(rpc_url).netloc.split(":")[0] # Extract domain without port
39
+ if domain not in SUPPORTED_RPC_DOMAINS:
40
+ return fixture()
41
+
34
42
  # Find existing snapshot for this fixture
35
43
  global _snapshots
36
44
  snapshot = next((s for s in _snapshots if s.fixture == fixture), None)
@@ -38,8 +46,8 @@ def load_fixture(fixture: Callable[[], T]) -> T:
38
46
  if snapshot is not None:
39
47
  try:
40
48
  snapshot.restorer.restore()
49
+
41
50
  # Remove snapshots that were taken after this one
42
-
43
51
  _snapshots = [
44
52
  s
45
53
  for s in _snapshots
@@ -0,0 +1,22 @@
1
+ # { "Depends": "py-genlayer:test" }
2
+
3
+ from genlayer import *
4
+
5
+
6
+ # contract class that is not an IC contract
7
+ class NotICContract:
8
+ storage: str
9
+
10
+ # constructor
11
+ def __init__(self, initial_storage: str):
12
+ self.storage = initial_storage
13
+
14
+ # read methods must be annotated with view
15
+ @gl.public.view
16
+ def get_storage(self) -> str:
17
+ return self.storage
18
+
19
+ # write method
20
+ @gl.public.write
21
+ def update_storage(self, new_storage: str) -> None:
22
+ self.storage = new_storage
@@ -0,0 +1,92 @@
1
+ import pytest
2
+ from gltest.artifacts.contract import (
3
+ find_contract_definition,
4
+ compute_contract_code,
5
+ )
6
+ from gltest.plugin_config import set_contracts_dir
7
+ from pathlib import Path
8
+
9
+
10
+ def test_single_file():
11
+ set_contracts_dir(".")
12
+ contract_definition = find_contract_definition("PredictionMarket")
13
+
14
+ assert contract_definition.contract_name == "PredictionMarket"
15
+
16
+ # Assert complete contract definition
17
+ expected_main_file_path = Path("examples/contracts/football_prediction_market.py")
18
+ expected_runner_file_path = None
19
+ contract_code = compute_contract_code(
20
+ expected_main_file_path, expected_runner_file_path
21
+ )
22
+ assert contract_definition.contract_code == contract_code
23
+ assert (
24
+ str(contract_definition.main_file_path)
25
+ == "examples/contracts/football_prediction_market.py"
26
+ )
27
+ assert contract_definition.runner_file_path is None
28
+
29
+
30
+ def test_multiple_files():
31
+ set_contracts_dir(".")
32
+ contract_definition = find_contract_definition("MultiFileContract")
33
+
34
+ assert contract_definition.contract_name == "MultiFileContract"
35
+
36
+ # Assert complete contract definition
37
+ expected_main_file_path = Path("examples/contracts/multi_file_contract/__init__.py")
38
+ expected_runner_file_path = Path(
39
+ "examples/contracts/multi_file_contract/runner.json"
40
+ )
41
+ assert contract_definition.main_file_path == expected_main_file_path
42
+ assert contract_definition.runner_file_path == expected_runner_file_path
43
+ contract_code = compute_contract_code(
44
+ expected_main_file_path, expected_runner_file_path
45
+ )
46
+ assert contract_definition.contract_code == contract_code
47
+
48
+
49
+ def test_single_file_legacy():
50
+ set_contracts_dir(".")
51
+ contract_definition = find_contract_definition("StorageLegacy")
52
+
53
+ # Assert complete contract definition
54
+ assert contract_definition.contract_name == "StorageLegacy"
55
+ expected_main_file_path = Path("examples/contracts/storage_legacy.gpy")
56
+ expected_runner_file_path = None
57
+ contract_code = compute_contract_code(
58
+ expected_main_file_path, expected_runner_file_path
59
+ )
60
+ assert contract_definition.contract_code == contract_code
61
+ assert (
62
+ str(contract_definition.main_file_path)
63
+ == "examples/contracts/storage_legacy.gpy"
64
+ )
65
+ assert contract_definition.runner_file_path is None
66
+
67
+
68
+ def test_multiple_files_legacy():
69
+ set_contracts_dir(".")
70
+ contract_definition = find_contract_definition("MultiFileContractLegacy")
71
+
72
+ # Assert complete contract definition
73
+ assert contract_definition.contract_name == "MultiFileContractLegacy"
74
+ expected_main_file_path = Path(
75
+ "examples/contracts/multi_file_contract_legacy/__init__.gpy"
76
+ )
77
+ expected_runner_file_path = Path(
78
+ "examples/contracts/multi_file_contract_legacy/runner.json"
79
+ )
80
+ assert contract_definition.main_file_path == expected_main_file_path
81
+ assert contract_definition.runner_file_path == expected_runner_file_path
82
+ contract_code = compute_contract_code(
83
+ expected_main_file_path, expected_runner_file_path
84
+ )
85
+ assert contract_definition.contract_code == contract_code
86
+
87
+
88
+ def test_class_is_not_intelligent_contract():
89
+ set_contracts_dir(".")
90
+
91
+ with pytest.raises(FileNotFoundError):
92
+ _ = find_contract_definition("NotICContract")
@@ -0,0 +1,31 @@
1
+ from gltest.assertions import tx_execution_succeeded, tx_execution_failed
2
+
3
+ GENLAYER_SUCCESS_TRANSACTION = {
4
+ "consensus_data": {"leader_receipt": [{"execution_result": "SUCCESS"}]}
5
+ }
6
+
7
+ GENLAYER_FAILED_TRANSACTION = {
8
+ "consensus_data": {"leader_receipt": [{"execution_result": "ERROR"}]}
9
+ }
10
+
11
+ GENLAYER_EMPTY_LEADER_RECEIPT = {"consensus_data": {"leader_receipt": []}}
12
+
13
+
14
+ def test_with_successful_transaction():
15
+ assert tx_execution_succeeded(GENLAYER_SUCCESS_TRANSACTION) is True
16
+ assert tx_execution_failed(GENLAYER_SUCCESS_TRANSACTION) is False
17
+
18
+
19
+ def test_with_failed_transaction():
20
+ assert tx_execution_succeeded(GENLAYER_FAILED_TRANSACTION) is False
21
+ assert tx_execution_failed(GENLAYER_FAILED_TRANSACTION) is True
22
+
23
+
24
+ def test_with_empty_leader_receipt():
25
+ assert tx_execution_succeeded(GENLAYER_EMPTY_LEADER_RECEIPT) is False
26
+ assert tx_execution_failed(GENLAYER_EMPTY_LEADER_RECEIPT) is True
27
+
28
+
29
+ def test_with_invalid_transaction():
30
+ assert tx_execution_succeeded({}) is False
31
+ assert tx_execution_failed({}) is True
@@ -0,0 +1,97 @@
1
+ # { "Depends": "py-genlayer:test" }
2
+
3
+ from genlayer import *
4
+
5
+ import json
6
+ import typing
7
+
8
+
9
+ class PredictionMarket(gl.Contract):
10
+ has_resolved: bool
11
+ team1: str
12
+ team2: str
13
+ resolution_url: str
14
+ winner: u256
15
+ score: str
16
+
17
+ def __init__(self, game_date: str, team1: str, team2: str):
18
+ """
19
+ Initializes a new instance of the prediction market with the specified game date and teams.
20
+
21
+ Args:
22
+ game_date (str): The date of the game in the format 'YYYY-MM-DD'.
23
+ team1 (str): The name of the first team.
24
+ team2 (str): The name of the second team.
25
+
26
+ Attributes:
27
+ has_resolved (bool): Indicates whether the game's resolution has been processed. Default is False.
28
+ game_date (str): The date of the game.
29
+ resolution_url (str): The URL to the game's resolution on BBC Sport.
30
+ team1 (str): The name of the first team.
31
+ team2 (str): The name of the second team.
32
+ """
33
+ self.has_resolved = False
34
+ self.resolution_url = (
35
+ "https://www.bbc.com/sport/football/scores-fixtures/" + game_date
36
+ )
37
+ self.team1 = team1
38
+ self.team2 = team2
39
+ self.winner = 0
40
+ self.score = ""
41
+
42
+ @gl.public.write
43
+ def resolve(self) -> typing.Any:
44
+
45
+ if self.has_resolved:
46
+ return "Already resolved"
47
+
48
+ market_resolution_url = self.resolution_url
49
+ team1 = self.team1
50
+ team2 = self.team2
51
+
52
+ def get_match_result() -> str:
53
+ web_data = gl.get_webpage(market_resolution_url, mode="text")
54
+ print(web_data)
55
+
56
+ task = f"""
57
+ In the following web page, find the winning team in a matchup between the following teams:
58
+ Team 1: {team1}
59
+ Team 2: {team2}
60
+
61
+ Web page content:
62
+ {web_data}
63
+ End of web page data.
64
+
65
+ If it says "Kick off [time]" between the names of the two teams, it means the game hasn't started yet.
66
+ If you fail to extract the score, assume the game is not resolved yet.
67
+
68
+ Respond with the following JSON format:
69
+ {{
70
+ "score": str, // The score with numbers only, e.g, "1:2", or "-" if the game is not resolved yet
71
+ "winner": int, // The number of the winning team, 0 for draw, or -1 if the game is not yet finished
72
+ }}
73
+ It is mandatory that you respond only using the JSON format above,
74
+ nothing else. Don't include any other words or characters,
75
+ your output must be only JSON without any formatting prefix or suffix.
76
+ This result should be perfectly parsable by a JSON parser without errors.
77
+ """
78
+ result = gl.exec_prompt(task).replace("```json", "").replace("```", "")
79
+ print(result)
80
+ return json.dumps(json.loads(result), sort_keys=True)
81
+
82
+ result_json = json.loads(gl.eq_principle_strict_eq(get_match_result))
83
+
84
+ if result_json["winner"] > -1:
85
+ self.has_resolved = True
86
+ self.winner = result_json["winner"]
87
+ self.score = result_json["score"]
88
+
89
+ return result_json
90
+
91
+ @gl.public.view
92
+ def get_resolution_data(self) -> dict[str, typing.Any]:
93
+ return {
94
+ "winner": self.winner,
95
+ "score": self.score,
96
+ "has_resolved": self.has_resolved,
97
+ }