genlayer-test 0.0.1__py3-none-any.whl → 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. genlayer_test-0.1.0.dist-info/METADATA +419 -0
  2. genlayer_test-0.1.0.dist-info/RECORD +35 -0
  3. {genlayer_test-0.0.1.dist-info → genlayer_test-0.1.0.dist-info}/WHEEL +1 -1
  4. genlayer_test-0.1.0.dist-info/entry_points.txt +5 -0
  5. genlayer_test-0.1.0.dist-info/licenses/LICENSE +21 -0
  6. genlayer_test-0.1.0.dist-info/top_level.txt +3 -0
  7. gltest/__init__.py +18 -0
  8. gltest/artifacts/__init__.py +3 -0
  9. gltest/artifacts/contract.py +86 -0
  10. gltest/assertions.py +17 -0
  11. gltest/exceptions.py +20 -0
  12. gltest/glchain/__init__.py +16 -0
  13. gltest/glchain/account.py +17 -0
  14. gltest/glchain/client.py +23 -0
  15. gltest/glchain/contract.py +244 -0
  16. gltest/helpers/__init__.py +8 -0
  17. gltest/helpers/fixture_snapshot.py +67 -0
  18. gltest/helpers/take_snapshot.py +41 -0
  19. gltest/plugin_config.py +42 -0
  20. gltest/plugin_hooks.py +51 -0
  21. gltest/types.py +7 -0
  22. gltest_cli/main.py +5 -0
  23. tests/examples/tests/test_football_prediction_market.py +19 -0
  24. tests/examples/tests/test_intelligent_oracle_factory.py +129 -0
  25. tests/examples/tests/test_llm_erc20.py +41 -0
  26. tests/examples/tests/test_log_indexer.py +64 -0
  27. tests/examples/tests/test_multi_file_contract.py +15 -0
  28. tests/examples/tests/test_multi_read_erc20.py +85 -0
  29. tests/examples/tests/test_multi_tenant_storage.py +58 -0
  30. tests/examples/tests/test_read_erc20.py +37 -0
  31. tests/examples/tests/test_storage.py +23 -0
  32. tests/examples/tests/test_user_storage.py +60 -0
  33. tests/examples/tests/test_wizard_of_coin.py +12 -0
  34. tests/plugin/conftest.py +1 -0
  35. tests/plugin/test_plugin_hooks.py +78 -0
  36. genlayer_test-0.0.1.dist-info/METADATA +0 -17
  37. genlayer_test-0.0.1.dist-info/RECORD +0 -4
  38. genlayer_test-0.0.1.dist-info/top_level.txt +0 -1
@@ -0,0 +1,23 @@
1
+ from genlayer_py.chains import localnet
2
+ from genlayer_py import create_client
3
+ from .account import default_account
4
+ from functools import lru_cache
5
+ from gltest.plugin_config import get_rpc_url
6
+
7
+
8
+ @lru_cache(maxsize=1)
9
+ def get_gl_client():
10
+ """
11
+ Get the GenLayer client instance.
12
+ """
13
+ return create_client(
14
+ chain=localnet, account=default_account, endpoint=get_rpc_url()
15
+ )
16
+
17
+
18
+ def get_gl_provider():
19
+ """
20
+ Get the GenLayer provider instance.
21
+ """
22
+ client = get_gl_client()
23
+ return client.provider
@@ -0,0 +1,244 @@
1
+ from eth_typing import (
2
+ Address,
3
+ ChecksumAddress,
4
+ )
5
+ from eth_account.signers.local import LocalAccount
6
+ from typing import Union
7
+ from dataclasses import dataclass
8
+ from gltest.artifacts import find_contract_definition
9
+ from gltest.assertions import tx_execution_failed
10
+ from gltest.exceptions import DeploymentError
11
+ from .client import get_gl_client
12
+ from gltest.types import CalldataEncodable, GenLayerTransaction, TransactionStatus
13
+ from typing import List, Any, Type, Optional, Dict, Callable
14
+ import types
15
+ from gltest.plugin_config import get_default_wait_interval, get_default_wait_retries
16
+
17
+
18
+ @dataclass
19
+ class Contract:
20
+ """
21
+ Class to interact with a contract, its methods
22
+ are implemented dynamically at build time.
23
+ """
24
+
25
+ address: str
26
+ account: Optional[LocalAccount] = None
27
+ _schema: Optional[Dict[str, Any]] = None
28
+
29
+ @classmethod
30
+ def new(
31
+ cls,
32
+ address: str,
33
+ schema: Dict[str, Any],
34
+ account: Optional[LocalAccount] = None,
35
+ ) -> "Contract":
36
+ """
37
+ Build the methods from the schema.
38
+ """
39
+ if not isinstance(schema, dict) or "methods" not in schema:
40
+ raise ValueError("Invalid schema: must contain 'methods' field")
41
+ instance = cls(address=address, _schema=schema, account=account)
42
+ instance._build_methods_from_schema()
43
+ return instance
44
+
45
+ def _build_methods_from_schema(self):
46
+ if self._schema is None:
47
+ raise ValueError("No schema provided")
48
+ for method_name, method_info in self._schema["methods"].items():
49
+ if not isinstance(method_info, dict) or "readonly" not in method_info:
50
+ raise ValueError(
51
+ f"Invalid method info for '{method_name}': must contain 'readonly' field"
52
+ )
53
+ method_func = self.contract_method_factory(
54
+ method_name, method_info["readonly"]
55
+ )
56
+ bound_method = types.MethodType(method_func, self)
57
+ setattr(self, method_name, bound_method)
58
+
59
+ def connect(self, account: LocalAccount) -> "Contract":
60
+ """
61
+ Create a new instance of the contract with the same methods and a different account.
62
+ """
63
+ new_contract = self.__class__(
64
+ address=self.address, account=account, _schema=self._schema
65
+ )
66
+ new_contract._build_methods_from_schema()
67
+ return new_contract
68
+
69
+ @staticmethod
70
+ def contract_method_factory(method_name: str, read_only: bool) -> Callable:
71
+ """
72
+ Create a function that interacts with a specific contract method.
73
+ """
74
+
75
+ def read_contract_wrapper(
76
+ self,
77
+ args: Optional[List[CalldataEncodable]] = None,
78
+ ) -> Any:
79
+ """
80
+ Wrapper to the contract read method.
81
+ """
82
+ client = get_gl_client()
83
+ return client.read_contract(
84
+ address=self.address,
85
+ function_name=method_name,
86
+ account=self.account,
87
+ args=args,
88
+ )
89
+
90
+ def write_contract_wrapper(
91
+ self,
92
+ args: Optional[List[CalldataEncodable]] = None,
93
+ value: int = 0,
94
+ consensus_max_rotations: Optional[int] = None,
95
+ leader_only: bool = False,
96
+ wait_transaction_status: TransactionStatus = TransactionStatus.FINALIZED,
97
+ wait_interval: Optional[int] = None,
98
+ wait_retries: Optional[int] = None,
99
+ wait_triggered_transactions: bool = True,
100
+ wait_triggered_transactions_status: TransactionStatus = TransactionStatus.ACCEPTED,
101
+ ) -> GenLayerTransaction:
102
+ """
103
+ Wrapper to the contract write method.
104
+ """
105
+ if wait_interval is None:
106
+ wait_interval = get_default_wait_interval()
107
+ if wait_retries is None:
108
+ wait_retries = get_default_wait_retries()
109
+ client = get_gl_client()
110
+ tx_hash = client.write_contract(
111
+ address=self.address,
112
+ function_name=method_name,
113
+ account=self.account,
114
+ value=value,
115
+ consensus_max_rotations=consensus_max_rotations,
116
+ leader_only=leader_only,
117
+ args=args,
118
+ )
119
+ receipt = client.wait_for_transaction_receipt(
120
+ transaction_hash=tx_hash,
121
+ status=wait_transaction_status,
122
+ interval=wait_interval,
123
+ retries=wait_retries,
124
+ )
125
+ if wait_triggered_transactions:
126
+ triggered_transactions = receipt["triggered_transactions"]
127
+ for triggered_transaction in triggered_transactions:
128
+ client.wait_for_transaction_receipt(
129
+ transaction_hash=triggered_transaction,
130
+ status=wait_triggered_transactions_status,
131
+ interval=wait_interval,
132
+ retries=wait_retries,
133
+ )
134
+ return receipt
135
+
136
+ return read_contract_wrapper if read_only else write_contract_wrapper
137
+
138
+
139
+ @dataclass
140
+ class ContractFactory:
141
+ """
142
+ A factory for deploying contracts.
143
+ """
144
+
145
+ contract_name: str
146
+ contract_code: str
147
+
148
+ @classmethod
149
+ def from_artifact(
150
+ cls: Type["ContractFactory"], contract_name: str
151
+ ) -> "ContractFactory":
152
+ """
153
+ Create a ContractFactory instance given the contract name.
154
+ """
155
+ contract_info = find_contract_definition(contract_name)
156
+ if contract_info is None:
157
+ raise ValueError(
158
+ f"Contract {contract_name} not found in the contracts directory"
159
+ )
160
+ return cls(
161
+ contract_name=contract_name, contract_code=contract_info.contract_code
162
+ )
163
+
164
+ def build_contract(
165
+ self,
166
+ contract_address: Union[Address, ChecksumAddress],
167
+ account: Optional[LocalAccount] = None,
168
+ ) -> Contract:
169
+ """
170
+ Build contract from address
171
+ """
172
+ client = get_gl_client()
173
+ try:
174
+ schema = client.get_contract_schema(address=contract_address)
175
+ return Contract.new(
176
+ address=contract_address, schema=schema, account=account
177
+ )
178
+ except Exception as e:
179
+ raise ValueError(
180
+ f"Failed to build contract {self.contract_name}: {str(e)}"
181
+ ) from e
182
+
183
+ def deploy(
184
+ self,
185
+ args: List[Any] = [],
186
+ account: Optional[LocalAccount] = None,
187
+ consensus_max_rotations: Optional[int] = None,
188
+ leader_only: bool = False,
189
+ wait_interval: Optional[int] = None,
190
+ wait_retries: Optional[int] = None,
191
+ wait_transaction_status: TransactionStatus = TransactionStatus.FINALIZED,
192
+ ) -> Contract:
193
+ """
194
+ Deploy the contract
195
+ """
196
+ if wait_interval is None:
197
+ wait_interval = get_default_wait_interval()
198
+ if wait_retries is None:
199
+ wait_retries = get_default_wait_retries()
200
+ client = get_gl_client()
201
+ try:
202
+ tx_hash = client.deploy_contract(
203
+ code=self.contract_code,
204
+ args=args,
205
+ account=account,
206
+ consensus_max_rotations=consensus_max_rotations,
207
+ leader_only=leader_only,
208
+ )
209
+ tx_receipt = client.wait_for_transaction_receipt(
210
+ transaction_hash=tx_hash,
211
+ status=wait_transaction_status,
212
+ interval=wait_interval,
213
+ retries=wait_retries,
214
+ )
215
+ if (
216
+ not tx_receipt
217
+ or "data" not in tx_receipt
218
+ or "contract_address" not in tx_receipt["data"]
219
+ ):
220
+ raise ValueError(
221
+ "Invalid transaction receipt: missing contract address"
222
+ )
223
+
224
+ if tx_execution_failed(tx_receipt):
225
+ raise ValueError(
226
+ f"Deployment transaction finalized with error: {tx_receipt}"
227
+ )
228
+
229
+ contract_address = tx_receipt["data"]["contract_address"]
230
+ schema = client.get_contract_schema(address=contract_address)
231
+ return Contract.new(
232
+ address=contract_address, schema=schema, account=account
233
+ )
234
+ except Exception as e:
235
+ raise DeploymentError(
236
+ f"Failed to deploy contract {self.contract_name}: {str(e)}"
237
+ ) from e
238
+
239
+
240
+ def get_contract_factory(contract_name: str) -> ContractFactory:
241
+ """
242
+ Get a ContractFactory instance for a contract.
243
+ """
244
+ return ContractFactory.from_artifact(contract_name)
@@ -0,0 +1,8 @@
1
+ from .take_snapshot import take_snapshot
2
+ from .fixture_snapshot import load_fixture, clear_snapshots
3
+
4
+ __all__ = [
5
+ "take_snapshot",
6
+ "load_fixture",
7
+ "clear_snapshots",
8
+ ]
@@ -0,0 +1,67 @@
1
+ from typing import TypeVar, Callable, List, Any
2
+ from dataclasses import dataclass
3
+ from .take_snapshot import SnapshotRestorer, take_snapshot
4
+ from gltest.exceptions import (
5
+ FixtureSnapshotError,
6
+ InvalidSnapshotError,
7
+ FixtureAnonymousFunctionError,
8
+ )
9
+
10
+
11
+ T = TypeVar("T")
12
+
13
+
14
+ @dataclass
15
+ class Snapshot:
16
+ """Represents a snapshot of the blockchain state."""
17
+
18
+ restorer: SnapshotRestorer
19
+ fixture: Callable[[], Any]
20
+ data: Any
21
+
22
+
23
+ # Global storage for snapshots
24
+ _snapshots: List[Snapshot] = []
25
+
26
+
27
+ def load_fixture(fixture: Callable[[], T]) -> T:
28
+ """
29
+ Useful in tests for setting up the desired state of the network.
30
+ """
31
+ if fixture.__name__ == "<lambda>":
32
+ raise FixtureAnonymousFunctionError("Fixtures must be named functions")
33
+
34
+ # Find existing snapshot for this fixture
35
+ global _snapshots
36
+ snapshot = next((s for s in _snapshots if s.fixture == fixture), None)
37
+
38
+ if snapshot is not None:
39
+ try:
40
+ snapshot.restorer.restore()
41
+ # Remove snapshots that were taken after this one
42
+
43
+ _snapshots = [
44
+ s
45
+ for s in _snapshots
46
+ if int(s.restorer.snapshot_id) <= int(snapshot.restorer.snapshot_id)
47
+ ]
48
+ except Exception as e:
49
+ if isinstance(e, InvalidSnapshotError):
50
+ raise FixtureSnapshotError(e) from e
51
+ raise e
52
+
53
+ return snapshot.data
54
+ else:
55
+ # Execute the fixture and take a snapshot
56
+ data = fixture()
57
+ restorer = take_snapshot()
58
+
59
+ _snapshots.append(Snapshot(restorer=restorer, fixture=fixture, data=data))
60
+
61
+ return data
62
+
63
+
64
+ def clear_snapshots() -> None:
65
+ """Clears every existing snapshot."""
66
+ global _snapshots
67
+ _snapshots = []
@@ -0,0 +1,41 @@
1
+ from gltest.glchain import get_gl_provider
2
+ from dataclasses import dataclass
3
+ from typing import Callable
4
+ from gltest.exceptions import HelperError, InvalidSnapshotError
5
+
6
+
7
+ @dataclass
8
+ class SnapshotRestorer:
9
+ """Class responsible for restoring blockchain state to a snapshot."""
10
+
11
+ restore: Callable[[], None]
12
+ snapshot_id: int
13
+
14
+
15
+ def take_snapshot() -> SnapshotRestorer:
16
+ """
17
+ Take a snapshot of the current blockchain state and return a function to restore the state and the snapshot ID.
18
+ """
19
+ provider = get_gl_provider()
20
+ snapshot_id = provider.make_request(method="sim_createSnapshot", params=[])[
21
+ "result"
22
+ ]
23
+ if not isinstance(snapshot_id, int):
24
+ raise HelperError(
25
+ "Assertion error: the value returned by evm_snapshot should be a int"
26
+ )
27
+
28
+ def restore() -> None:
29
+ reverted = provider.make_request(
30
+ method="sim_restoreSnapshot", params=[snapshot_id]
31
+ )["result"]
32
+
33
+ if not isinstance(reverted, bool):
34
+ raise HelperError(
35
+ "Assertion error: the value returned by evm_revert should be a boolean"
36
+ )
37
+
38
+ if not reverted:
39
+ raise InvalidSnapshotError("")
40
+
41
+ return SnapshotRestorer(restore=restore, snapshot_id=snapshot_id)
@@ -0,0 +1,42 @@
1
+ from pathlib import Path
2
+
3
+ _contracts_dir = None
4
+ _rpc_url = None
5
+ _default_wait_interval = None
6
+ _default_wait_retries = None
7
+
8
+
9
+ def set_contracts_dir(path: Path):
10
+ global _contracts_dir
11
+ _contracts_dir = path
12
+
13
+
14
+ def get_contracts_dir() -> Path:
15
+ return Path(_contracts_dir)
16
+
17
+
18
+ def set_rpc_url(rpc_url: str):
19
+ global _rpc_url
20
+ _rpc_url = rpc_url
21
+
22
+
23
+ def get_rpc_url() -> str:
24
+ return _rpc_url
25
+
26
+
27
+ def set_default_wait_interval(default_wait_interval: int):
28
+ global _default_wait_interval
29
+ _default_wait_interval = default_wait_interval
30
+
31
+
32
+ def get_default_wait_interval() -> int:
33
+ return _default_wait_interval
34
+
35
+
36
+ def set_default_wait_retries(default_wait_retries: int):
37
+ global _default_wait_retries
38
+ _default_wait_retries = default_wait_retries
39
+
40
+
41
+ def get_default_wait_retries() -> int:
42
+ return _default_wait_retries
gltest/plugin_hooks.py ADDED
@@ -0,0 +1,51 @@
1
+ from gltest.plugin_config import (
2
+ set_contracts_dir,
3
+ set_default_wait_interval,
4
+ set_default_wait_retries,
5
+ set_rpc_url,
6
+ )
7
+ from pathlib import Path
8
+ from genlayer_py.chains.localnet import SIMULATOR_JSON_RPC_URL
9
+
10
+
11
+ def pytest_addoption(parser):
12
+ group = parser.getgroup("gltest")
13
+ group.addoption(
14
+ "--contracts-dir",
15
+ action="store",
16
+ default="contracts",
17
+ help="Directory containing contract files",
18
+ )
19
+
20
+ group.addoption(
21
+ "--default-wait-interval",
22
+ action="store",
23
+ default=10000,
24
+ help="Default wait interval for waiting transaction receipts",
25
+ )
26
+
27
+ group.addoption(
28
+ "--default-wait-retries",
29
+ action="store",
30
+ default=15,
31
+ help="Default wait retries for waiting transaction receipts",
32
+ )
33
+
34
+ group.addoption(
35
+ "--rpc-url",
36
+ action="store",
37
+ default=SIMULATOR_JSON_RPC_URL,
38
+ help="RPC URL for the genlayer network",
39
+ )
40
+
41
+
42
+ def pytest_configure(config):
43
+ contracts_dir = config.getoption("--contracts-dir")
44
+ default_wait_interval = config.getoption("--default-wait-interval")
45
+ default_wait_retries = config.getoption("--default-wait-retries")
46
+ rpc_url = config.getoption("--rpc-url")
47
+
48
+ set_contracts_dir(Path(contracts_dir))
49
+ set_default_wait_interval(int(default_wait_interval))
50
+ set_default_wait_retries(int(default_wait_retries))
51
+ set_rpc_url(str(rpc_url))
gltest/types.py ADDED
@@ -0,0 +1,7 @@
1
+ # Re-export genlayer-py types
2
+ from genlayer_py.types import (
3
+ CalldataAddress,
4
+ GenLayerTransaction,
5
+ TransactionStatus,
6
+ CalldataEncodable,
7
+ )
gltest_cli/main.py ADDED
@@ -0,0 +1,5 @@
1
+ import pytest
2
+
3
+
4
+ def main():
5
+ return pytest.main()
@@ -0,0 +1,19 @@
1
+ from gltest import get_contract_factory
2
+ from gltest.assertions import tx_execution_succeeded
3
+
4
+
5
+ def test_football_prediction_market():
6
+ # Deploy Contract
7
+ factory = get_contract_factory("PredictionMarket")
8
+ contract = factory.deploy(args=["2024-06-26", "Georgia", "Portugal"])
9
+
10
+ # Resolve match
11
+ transaction_response_call_1 = contract.resolve(args=[])
12
+ assert tx_execution_succeeded(transaction_response_call_1)
13
+
14
+ # Get Updated State
15
+ contract_state_2 = contract.get_resolution_data(args=[])
16
+
17
+ assert contract_state_2["winner"] == 1
18
+ assert contract_state_2["score"] == "2:0"
19
+ assert contract_state_2["has_resolved"] == True
@@ -0,0 +1,129 @@
1
+ import time
2
+
3
+ from gltest import get_contract_factory
4
+ from gltest.assertions import tx_execution_succeeded
5
+
6
+
7
+ def wait_for_contract_deployment(intelligent_oracle_contract, max_retries=10, delay=5):
8
+ """
9
+ Wait for intelligent oracle contract to be fully deployed by attempting to call a method.
10
+ This is used to check if the triggered deployment did deploy the contract.
11
+ """
12
+ for _ in range(max_retries):
13
+ try:
14
+ intelligent_oracle_contract.get_dict(args=[])
15
+ return True # If successful, contract is deployed
16
+ except Exception:
17
+ time.sleep(delay)
18
+ return False
19
+
20
+
21
+ def test_intelligent_oracle_factory_pattern():
22
+ # Get the intelligent oracle factory
23
+ intelligent_oracle_factory = get_contract_factory("IntelligentOracle")
24
+
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
+
31
+ markets_data = [
32
+ {
33
+ "prediction_market_id": "marathon2024",
34
+ "title": "Marathon Winner Prediction",
35
+ "description": "Predict the male winner of a major marathon event.",
36
+ "potential_outcomes": ["Bekele Fikre", "Tafa Mitku", "Chebii Douglas"],
37
+ "rules": [
38
+ "The outcome is based on the official race results announced by the marathon organizers."
39
+ ],
40
+ "data_source_domains": ["thepostrace.com"],
41
+ "resolution_urls": [],
42
+ "earliest_resolution_date": "2024-01-01T00:00:00+00:00",
43
+ "outcome": "Tafa Mitku",
44
+ "evidence_urls": "https://thepostrace.com/en/blog/marathon-de-madrid-2024-results-and-rankings/?srsltid=AfmBOor1uG6O3_4oJ447hkah_ilOYuy0XXMvl8j70EApe1Z7Bzd94XJl",
45
+ },
46
+ {
47
+ "prediction_market_id": "election2024",
48
+ "title": "Election Prediction",
49
+ "description": "Predict the winner of the 2024 US presidential election.",
50
+ "potential_outcomes": ["Kamala Harris", "Donald Trump"],
51
+ "rules": ["The outcome is based on official election results."],
52
+ "data_source_domains": ["bbc.com"],
53
+ "resolution_urls": [],
54
+ "earliest_resolution_date": "2024-01-01T00:00:00+00:00",
55
+ "outcome": "Donald Trump",
56
+ "evidence_urls": "https://www.bbc.com/news/election/2024/us/results",
57
+ },
58
+ ]
59
+ created_market_contracts = []
60
+
61
+ # Create markets through factory
62
+ for market_data in markets_data:
63
+ create_result = registry_contract.create_new_prediction_market(
64
+ args=[
65
+ market_data["prediction_market_id"],
66
+ market_data["title"],
67
+ market_data["description"],
68
+ market_data["potential_outcomes"],
69
+ market_data["rules"],
70
+ market_data["data_source_domains"],
71
+ market_data["resolution_urls"],
72
+ market_data["earliest_resolution_date"],
73
+ ],
74
+ )
75
+ assert tx_execution_succeeded(create_result)
76
+
77
+ # Get the latest contract address from factory
78
+ registered_addresses = registry_contract.get_contract_addresses(args=[])
79
+ new_market_address = registered_addresses[-1]
80
+
81
+ # Build a contract object
82
+ market_contract = intelligent_oracle_factory.build_contract(
83
+ new_market_address
84
+ )
85
+ created_market_contracts.append(market_contract)
86
+
87
+ # Wait for the new market contract to be deployed
88
+ assert wait_for_contract_deployment(
89
+ market_contract
90
+ ), f"Market contract deployment timeout for {market_data['prediction_market_id']}"
91
+
92
+ # Verify all markets were registered
93
+ assert len(registered_addresses) == len(markets_data)
94
+
95
+ # Verify each market's state
96
+ for i, market_contract in enumerate(created_market_contracts):
97
+ market_state = market_contract.get_dict(args=[])
98
+ expected_data = markets_data[i]
99
+
100
+ # Verify key market properties
101
+ assert market_state["title"] == expected_data["title"]
102
+ assert market_state["description"] == expected_data["description"]
103
+ assert market_state["potential_outcomes"] == expected_data["potential_outcomes"]
104
+ assert market_state["rules"] == expected_data["rules"]
105
+ assert (
106
+ market_state["data_source_domains"] == expected_data["data_source_domains"]
107
+ )
108
+ assert market_state["resolution_urls"] == expected_data["resolution_urls"]
109
+ assert market_state["status"] == "Active"
110
+ assert (
111
+ market_state["earliest_resolution_date"]
112
+ == expected_data["earliest_resolution_date"]
113
+ )
114
+ assert (
115
+ market_state["prediction_market_id"]
116
+ == expected_data["prediction_market_id"]
117
+ )
118
+
119
+ # Resolve markets
120
+ for i, market_contract in enumerate(created_market_contracts):
121
+ resolve_result = market_contract.resolve(
122
+ args=[markets_data[i]["evidence_urls"]],
123
+ )
124
+ assert tx_execution_succeeded(resolve_result)
125
+
126
+ # Verify market was resolved and has the correct outcome
127
+ market_state = market_contract.get_dict(args=[])
128
+ assert market_state["status"] == "Resolved"
129
+ assert market_state["outcome"] == markets_data[i]["outcome"]
@@ -0,0 +1,41 @@
1
+ from gltest import get_contract_factory, default_account, create_account
2
+ from gltest.assertions import tx_execution_succeeded
3
+
4
+ TOKEN_TOTAL_SUPPLY = 1000
5
+ TRANSFER_AMOUNT = 100
6
+
7
+
8
+ def test_llm_erc20():
9
+ # Account Setup
10
+ from_account_a = default_account
11
+ from_account_b = create_account()
12
+
13
+ # Deploy Contract
14
+ factory = get_contract_factory("LlmErc20")
15
+ contract = factory.deploy(args=[TOKEN_TOTAL_SUPPLY])
16
+
17
+ # Get Initial State
18
+ contract_state_1 = contract.get_balances(args=[])
19
+ assert contract_state_1[from_account_a.address] == TOKEN_TOTAL_SUPPLY
20
+
21
+ # Transfer from User A to User B
22
+ transaction_response_call_1 = contract.transfer(
23
+ args=[TRANSFER_AMOUNT, from_account_b.address]
24
+ )
25
+ assert tx_execution_succeeded(transaction_response_call_1)
26
+
27
+ # Get Updated State
28
+ contract_state_2_1 = contract.get_balances(args=[])
29
+ assert (
30
+ contract_state_2_1[from_account_a.address]
31
+ == TOKEN_TOTAL_SUPPLY - TRANSFER_AMOUNT
32
+ )
33
+ assert contract_state_2_1[from_account_b.address] == TRANSFER_AMOUNT
34
+
35
+ # Get Updated State
36
+ contract_state_2_2 = contract.get_balance_of(args=[from_account_a.address])
37
+ assert contract_state_2_2 == TOKEN_TOTAL_SUPPLY - TRANSFER_AMOUNT
38
+
39
+ # Get Updated State
40
+ contract_state_2_3 = contract.get_balance_of(args=[from_account_b.address])
41
+ assert contract_state_2_3 == TRANSFER_AMOUNT