genlayer-test 0.8.0__py3-none-any.whl → 0.10.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.
- {genlayer_test-0.8.0.dist-info → genlayer_test-0.10.0.dist-info}/METADATA +77 -177
- genlayer_test-0.10.0.dist-info/RECORD +38 -0
- {genlayer_test-0.8.0.dist-info → genlayer_test-0.10.0.dist-info}/top_level.txt +0 -1
- gltest/fixtures.py +1 -50
- gltest_cli/config/constants.py +6 -0
- gltest_cli/config/plugin.py +19 -12
- gltest_cli/config/types.py +70 -49
- gltest_cli/config/user.py +79 -7
- genlayer_test-0.8.0.dist-info/RECORD +0 -82
- tests/__init__.py +0 -0
- tests/conftest.py +0 -1
- tests/examples/contracts/football_prediction_market.py +0 -100
- tests/examples/contracts/intelligent_oracle.py +0 -370
- tests/examples/contracts/intelligent_oracle_factory.py +0 -49
- tests/examples/contracts/invalid_deploy.py +0 -10
- tests/examples/contracts/llm_erc20.py +0 -70
- tests/examples/contracts/log_indexer.py +0 -69
- tests/examples/contracts/multi_file_contract/__init__.py +0 -24
- tests/examples/contracts/multi_file_contract/other.py +0 -14
- tests/examples/contracts/multi_read_erc20.py +0 -29
- tests/examples/contracts/multi_tenant_storage.py +0 -51
- tests/examples/contracts/read_erc20.py +0 -19
- tests/examples/contracts/simple_time_contract.py +0 -85
- tests/examples/contracts/storage.py +0 -23
- tests/examples/contracts/user_storage.py +0 -25
- tests/examples/contracts/wizard_of_coin.py +0 -57
- tests/examples/tests/test_custom_validators.py +0 -65
- tests/examples/tests/test_football_prediction_market.py +0 -38
- tests/examples/tests/test_intelligent_oracle_factory.py +0 -162
- tests/examples/tests/test_invalid_deploy.py +0 -24
- tests/examples/tests/test_llm_erc20.py +0 -60
- tests/examples/tests/test_llm_erc20_analyze.py +0 -54
- tests/examples/tests/test_log_indexer.py +0 -76
- tests/examples/tests/test_multi_file_contract.py +0 -15
- tests/examples/tests/test_multi_read_erc20.py +0 -103
- tests/examples/tests/test_multi_tenant_storage.py +0 -76
- tests/examples/tests/test_read_erc20.py +0 -38
- tests/examples/tests/test_simple_time_contract.py +0 -90
- tests/examples/tests/test_storage.py +0 -26
- tests/examples/tests/test_user_storage.py +0 -87
- tests/examples/tests/test_wizard_of_coin.py +0 -27
- tests/gltest/__init__.py +0 -0
- tests/gltest/artifact/__init__.py +0 -0
- tests/gltest/artifact/contracts/duplicate_ic_contract_1.py +0 -22
- tests/gltest/artifact/contracts/duplicate_ic_contract_2.py +0 -22
- tests/gltest/artifact/contracts/not_ic_contract.py +0 -22
- tests/gltest/artifact/test_contract_definition.py +0 -55
- tests/gltest/assertions/test_assertions.py +0 -344
- tests/gltest_cli/__init__.py +0 -0
- tests/gltest_cli/config/test_config_integration.py +0 -432
- tests/gltest_cli/config/test_general_config.py +0 -406
- tests/gltest_cli/config/test_plugin.py +0 -290
- tests/gltest_cli/config/test_user.py +0 -411
- {genlayer_test-0.8.0.dist-info → genlayer_test-0.10.0.dist-info}/WHEEL +0 -0
- {genlayer_test-0.8.0.dist-info → genlayer_test-0.10.0.dist-info}/entry_points.txt +0 -0
- {genlayer_test-0.8.0.dist-info → genlayer_test-0.10.0.dist-info}/licenses/LICENSE +0 -0
gltest_cli/config/types.py
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
from enum import Enum
|
|
2
1
|
from dataclasses import dataclass, field
|
|
3
2
|
from pathlib import Path
|
|
4
3
|
from typing import Dict, List, Optional
|
|
5
4
|
from genlayer_py.chains import localnet, studionet, testnet_asimov
|
|
6
5
|
from genlayer_py.types import GenLayerChain
|
|
7
|
-
from urllib.parse import urlparse
|
|
8
6
|
from gltest_cli.config.constants import PRECONFIGURED_NETWORKS
|
|
7
|
+
from gltest_cli.config.constants import (
|
|
8
|
+
DEFAULT_WAIT_INTERVAL,
|
|
9
|
+
DEFAULT_WAIT_RETRIES,
|
|
10
|
+
DEFAULT_LEADER_ONLY,
|
|
11
|
+
CHAINS,
|
|
12
|
+
)
|
|
9
13
|
|
|
10
14
|
|
|
11
15
|
@dataclass
|
|
@@ -16,8 +20,8 @@ class PluginConfig:
|
|
|
16
20
|
default_wait_interval: Optional[int] = None
|
|
17
21
|
default_wait_retries: Optional[int] = None
|
|
18
22
|
network_name: Optional[str] = None
|
|
19
|
-
test_with_mocks: bool = False
|
|
20
23
|
leader_only: bool = False
|
|
24
|
+
chain_type: Optional[str] = None
|
|
21
25
|
|
|
22
26
|
|
|
23
27
|
@dataclass
|
|
@@ -27,6 +31,9 @@ class NetworkConfigData:
|
|
|
27
31
|
accounts: Optional[List[str]] = None
|
|
28
32
|
from_account: Optional[str] = None
|
|
29
33
|
leader_only: bool = False
|
|
34
|
+
default_wait_interval: Optional[int] = None
|
|
35
|
+
default_wait_retries: Optional[int] = None
|
|
36
|
+
chain_type: Optional[str] = None
|
|
30
37
|
|
|
31
38
|
def __post_init__(self):
|
|
32
39
|
if self.id is not None and not isinstance(self.id, int):
|
|
@@ -40,6 +47,18 @@ class NetworkConfigData:
|
|
|
40
47
|
raise ValueError("accounts must be strings")
|
|
41
48
|
if self.from_account is not None and not isinstance(self.from_account, str):
|
|
42
49
|
raise ValueError("from_account must be a string")
|
|
50
|
+
if not isinstance(self.leader_only, bool):
|
|
51
|
+
raise TypeError("leader_only must be a boolean")
|
|
52
|
+
if self.default_wait_interval is not None and not isinstance(
|
|
53
|
+
self.default_wait_interval, int
|
|
54
|
+
):
|
|
55
|
+
raise ValueError("default_wait_interval must be an integer")
|
|
56
|
+
if self.default_wait_retries is not None and not isinstance(
|
|
57
|
+
self.default_wait_retries, int
|
|
58
|
+
):
|
|
59
|
+
raise ValueError("default_wait_retries must be an integer")
|
|
60
|
+
if self.chain_type is not None and not isinstance(self.chain_type, str):
|
|
61
|
+
raise ValueError("chain_type must be a string")
|
|
43
62
|
|
|
44
63
|
|
|
45
64
|
@dataclass
|
|
@@ -130,59 +149,75 @@ class GeneralConfig:
|
|
|
130
149
|
return self.user_config.networks[network_name].accounts
|
|
131
150
|
return self.user_config.networks[self.user_config.default_network].accounts
|
|
132
151
|
|
|
133
|
-
def
|
|
152
|
+
def get_chain_type(self) -> str:
|
|
153
|
+
# If chain_type is explicitly set via CLI, use it
|
|
154
|
+
if self.plugin_config.chain_type is not None:
|
|
155
|
+
if self.plugin_config.chain_type not in CHAINS:
|
|
156
|
+
raise ValueError(
|
|
157
|
+
f"Unknown chain type: {self.plugin_config.chain_type}. "
|
|
158
|
+
f"Valid values: {', '.join(CHAINS)}"
|
|
159
|
+
)
|
|
160
|
+
return self.plugin_config.chain_type
|
|
161
|
+
|
|
134
162
|
network_name = self.get_network_name()
|
|
135
163
|
if network_name not in self.user_config.networks:
|
|
136
164
|
raise ValueError(
|
|
137
165
|
f"Unknown network: {network_name}, possible values: {self.get_networks_keys()}"
|
|
138
166
|
)
|
|
139
|
-
|
|
140
|
-
#
|
|
141
|
-
chain_map_by_name = {
|
|
142
|
-
"localnet": localnet,
|
|
143
|
-
"studionet": studionet,
|
|
144
|
-
"testnet_asimov": testnet_asimov,
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if network_name in chain_map_by_name:
|
|
148
|
-
return chain_map_by_name[network_name]
|
|
149
|
-
|
|
167
|
+
network_config = self.user_config.networks[network_name]
|
|
168
|
+
# For preconfigured networks, use its chain type
|
|
150
169
|
if network_name in PRECONFIGURED_NETWORKS:
|
|
170
|
+
chain_type = network_config.chain_type
|
|
171
|
+
else:
|
|
172
|
+
# For custom networks, chain_type field is required
|
|
173
|
+
chain_type = network_config.chain_type
|
|
174
|
+
if not chain_type:
|
|
175
|
+
raise ValueError(
|
|
176
|
+
f"Custom network {network_name} must specify a 'chain_type' field. "
|
|
177
|
+
f"Valid values: {', '.join(CHAINS)}"
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
if chain_type not in CHAINS:
|
|
151
181
|
raise ValueError(
|
|
152
|
-
f"
|
|
182
|
+
f"Unknown chain type: {chain_type}. "
|
|
183
|
+
f"Valid values: {', '.join(CHAINS)}"
|
|
153
184
|
)
|
|
185
|
+
return chain_type
|
|
154
186
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
187
|
+
def get_chain(self) -> GenLayerChain:
|
|
188
|
+
chain_map = {
|
|
189
|
+
"localnet": localnet,
|
|
190
|
+
"studionet": studionet,
|
|
191
|
+
"testnet_asimov": testnet_asimov,
|
|
159
192
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
known = ", ".join(map(str, chain_map_by_id.keys()))
|
|
163
|
-
raise ValueError(
|
|
164
|
-
f"Unknown network id: {network_id}, possible values: {known}"
|
|
165
|
-
)
|
|
166
|
-
return chain_map_by_id[network_id]
|
|
193
|
+
chain_type = self.get_chain_type()
|
|
194
|
+
return chain_map[chain_type]
|
|
167
195
|
|
|
168
196
|
def get_default_wait_interval(self) -> int:
|
|
169
197
|
if self.plugin_config.default_wait_interval is not None:
|
|
170
198
|
return self.plugin_config.default_wait_interval
|
|
171
|
-
|
|
199
|
+
network_name = self.get_network_name()
|
|
200
|
+
if network_name in self.user_config.networks:
|
|
201
|
+
network_config = self.user_config.networks[network_name]
|
|
202
|
+
if network_config.default_wait_interval is not None:
|
|
203
|
+
return network_config.default_wait_interval
|
|
204
|
+
return DEFAULT_WAIT_INTERVAL
|
|
172
205
|
|
|
173
206
|
def get_default_wait_retries(self) -> int:
|
|
174
207
|
if self.plugin_config.default_wait_retries is not None:
|
|
175
208
|
return self.plugin_config.default_wait_retries
|
|
176
|
-
|
|
209
|
+
network_name = self.get_network_name()
|
|
210
|
+
if network_name in self.user_config.networks:
|
|
211
|
+
network_config = self.user_config.networks[network_name]
|
|
212
|
+
if network_config.default_wait_retries is not None:
|
|
213
|
+
return network_config.default_wait_retries
|
|
214
|
+
return DEFAULT_WAIT_RETRIES
|
|
177
215
|
|
|
178
216
|
def get_network_name(self) -> str:
|
|
179
217
|
if self.plugin_config.network_name is not None:
|
|
180
218
|
return self.plugin_config.network_name
|
|
181
219
|
return self.user_config.default_network
|
|
182
220
|
|
|
183
|
-
def get_test_with_mocks(self) -> bool:
|
|
184
|
-
return self.plugin_config.test_with_mocks
|
|
185
|
-
|
|
186
221
|
def get_leader_only(self) -> bool:
|
|
187
222
|
if self.plugin_config.leader_only:
|
|
188
223
|
return True
|
|
@@ -190,24 +225,10 @@ class GeneralConfig:
|
|
|
190
225
|
if network_name in self.user_config.networks:
|
|
191
226
|
network_config = self.user_config.networks[network_name]
|
|
192
227
|
return network_config.leader_only
|
|
193
|
-
return
|
|
228
|
+
return DEFAULT_LEADER_ONLY
|
|
194
229
|
|
|
195
230
|
def check_local_rpc(self) -> bool:
|
|
196
|
-
|
|
197
|
-
rpc_url = self.get_rpc_url()
|
|
198
|
-
domain = urlparse(rpc_url).netloc.split(":")[0] # Extract domain without port
|
|
199
|
-
return domain in SUPPORTED_RPC_DOMAINS
|
|
231
|
+
return self.get_chain_type() == "localnet"
|
|
200
232
|
|
|
201
233
|
def check_studio_based_rpc(self) -> bool:
|
|
202
|
-
|
|
203
|
-
rpc_url = self.get_rpc_url()
|
|
204
|
-
domain = urlparse(rpc_url).netloc.split(":")[0] # Extract domain without port
|
|
205
|
-
|
|
206
|
-
if domain in SUPPORTED_RPC_DOMAINS:
|
|
207
|
-
return True
|
|
208
|
-
|
|
209
|
-
# Check .genlayer.com or .genlayerlabs.com subdomains
|
|
210
|
-
if domain.endswith(".genlayer.com") or domain.endswith(".genlayerlabs.com"):
|
|
211
|
-
return True
|
|
212
|
-
|
|
213
|
-
return False
|
|
234
|
+
return self.get_chain_type() == "studionet"
|
gltest_cli/config/user.py
CHANGED
|
@@ -4,6 +4,7 @@ import re
|
|
|
4
4
|
from dotenv import load_dotenv
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from functools import lru_cache
|
|
7
|
+
from dataclasses import replace
|
|
7
8
|
from gltest.accounts import create_accounts
|
|
8
9
|
from gltest_cli.config.constants import (
|
|
9
10
|
GLTEST_CONFIG_FILE,
|
|
@@ -12,12 +13,25 @@ from gltest_cli.config.constants import (
|
|
|
12
13
|
DEFAULT_CONTRACTS_DIR,
|
|
13
14
|
DEFAULT_ARTIFACTS_DIR,
|
|
14
15
|
PRECONFIGURED_NETWORKS,
|
|
16
|
+
DEFAULT_WAIT_INTERVAL,
|
|
17
|
+
DEFAULT_WAIT_RETRIES,
|
|
18
|
+
DEFAULT_LEADER_ONLY,
|
|
19
|
+
CHAINS,
|
|
15
20
|
)
|
|
16
21
|
from genlayer_py.chains import localnet, studionet, testnet_asimov
|
|
17
22
|
from gltest_cli.config.types import UserConfig, NetworkConfigData, PathConfig
|
|
18
23
|
|
|
19
24
|
VALID_ROOT_KEYS = ["networks", "paths", "environment"]
|
|
20
|
-
VALID_NETWORK_KEYS = [
|
|
25
|
+
VALID_NETWORK_KEYS = [
|
|
26
|
+
"id",
|
|
27
|
+
"url",
|
|
28
|
+
"accounts",
|
|
29
|
+
"from",
|
|
30
|
+
"leader_only",
|
|
31
|
+
"default_wait_interval",
|
|
32
|
+
"default_wait_retries",
|
|
33
|
+
"chain_type",
|
|
34
|
+
]
|
|
21
35
|
VALID_PATHS_KEYS = ["contracts", "artifacts"]
|
|
22
36
|
|
|
23
37
|
|
|
@@ -32,21 +46,30 @@ def get_default_user_config() -> UserConfig:
|
|
|
32
46
|
url=localnet.rpc_urls["default"]["http"][0],
|
|
33
47
|
accounts=accounts_private_keys,
|
|
34
48
|
from_account=accounts_private_keys[0],
|
|
35
|
-
leader_only=
|
|
49
|
+
leader_only=DEFAULT_LEADER_ONLY,
|
|
50
|
+
default_wait_interval=DEFAULT_WAIT_INTERVAL,
|
|
51
|
+
default_wait_retries=DEFAULT_WAIT_RETRIES,
|
|
52
|
+
chain_type="localnet",
|
|
36
53
|
),
|
|
37
54
|
"studionet": NetworkConfigData(
|
|
38
55
|
id=studionet.id,
|
|
39
56
|
url=studionet.rpc_urls["default"]["http"][0],
|
|
40
57
|
accounts=accounts_private_keys,
|
|
41
58
|
from_account=accounts_private_keys[0],
|
|
42
|
-
leader_only=
|
|
59
|
+
leader_only=DEFAULT_LEADER_ONLY,
|
|
60
|
+
default_wait_interval=DEFAULT_WAIT_INTERVAL,
|
|
61
|
+
default_wait_retries=DEFAULT_WAIT_RETRIES,
|
|
62
|
+
chain_type="studionet",
|
|
43
63
|
),
|
|
44
64
|
"testnet_asimov": NetworkConfigData(
|
|
45
65
|
id=testnet_asimov.id,
|
|
46
66
|
url=testnet_asimov.rpc_urls["default"]["http"][0],
|
|
47
67
|
accounts=None,
|
|
48
68
|
from_account=None,
|
|
49
|
-
leader_only=
|
|
69
|
+
leader_only=DEFAULT_LEADER_ONLY,
|
|
70
|
+
default_wait_interval=DEFAULT_WAIT_INTERVAL,
|
|
71
|
+
default_wait_retries=DEFAULT_WAIT_RETRIES,
|
|
72
|
+
chain_type="testnet_asimov",
|
|
50
73
|
),
|
|
51
74
|
}
|
|
52
75
|
|
|
@@ -121,7 +144,29 @@ def validate_network_config(network_name: str, network_config: dict):
|
|
|
121
144
|
):
|
|
122
145
|
raise ValueError(f"network {network_name} leader_only must be a boolean")
|
|
123
146
|
|
|
124
|
-
|
|
147
|
+
if "default_wait_interval" in network_config and not isinstance(
|
|
148
|
+
network_config["default_wait_interval"], int
|
|
149
|
+
):
|
|
150
|
+
raise ValueError(
|
|
151
|
+
f"network {network_name} default_wait_interval must be an integer"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
if "default_wait_retries" in network_config and not isinstance(
|
|
155
|
+
network_config["default_wait_retries"], int
|
|
156
|
+
):
|
|
157
|
+
raise ValueError(
|
|
158
|
+
f"network {network_name} default_wait_retries must be an integer"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
if "chain_type" in network_config:
|
|
162
|
+
if not isinstance(network_config["chain_type"], str):
|
|
163
|
+
raise ValueError(f"network {network_name} chain_type must be a string")
|
|
164
|
+
if network_config["chain_type"] not in CHAINS:
|
|
165
|
+
raise ValueError(
|
|
166
|
+
f"network {network_name} chain_type must be one of: {', '.join(CHAINS)}"
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
# For non-preconfigured networks, url, accounts, and chain are required
|
|
125
170
|
if network_name not in PRECONFIGURED_NETWORKS:
|
|
126
171
|
if "id" not in network_config:
|
|
127
172
|
raise ValueError(f"network {network_name} must have an id")
|
|
@@ -129,6 +174,10 @@ def validate_network_config(network_name: str, network_config: dict):
|
|
|
129
174
|
raise ValueError(f"network {network_name} must have a url")
|
|
130
175
|
if "accounts" not in network_config:
|
|
131
176
|
raise ValueError(f"network {network_name} must have accounts")
|
|
177
|
+
if "chain_type" not in network_config:
|
|
178
|
+
raise ValueError(
|
|
179
|
+
f"network {network_name} must have a chain_type. Valid values: localnet, studionet, testnet_asimov"
|
|
180
|
+
)
|
|
132
181
|
|
|
133
182
|
|
|
134
183
|
def validate_raw_user_config(config: dict):
|
|
@@ -207,7 +256,10 @@ def _get_overridden_networks(raw_config: dict) -> tuple[dict, str]:
|
|
|
207
256
|
networks_config = {}
|
|
208
257
|
for network_name, network_config in networks.items():
|
|
209
258
|
if network_name in PRECONFIGURED_NETWORKS:
|
|
210
|
-
|
|
259
|
+
# Clone to avoid mutating the cached default instance
|
|
260
|
+
networks_config[network_name] = replace(
|
|
261
|
+
default_config.networks[network_name]
|
|
262
|
+
)
|
|
211
263
|
if network_config is None:
|
|
212
264
|
continue
|
|
213
265
|
|
|
@@ -224,19 +276,39 @@ def _get_overridden_networks(raw_config: dict) -> tuple[dict, str]:
|
|
|
224
276
|
networks_config[network_name].leader_only = network_config[
|
|
225
277
|
"leader_only"
|
|
226
278
|
]
|
|
279
|
+
if "default_wait_interval" in network_config:
|
|
280
|
+
networks_config[network_name].default_wait_interval = network_config[
|
|
281
|
+
"default_wait_interval"
|
|
282
|
+
]
|
|
283
|
+
if "default_wait_retries" in network_config:
|
|
284
|
+
networks_config[network_name].default_wait_retries = network_config[
|
|
285
|
+
"default_wait_retries"
|
|
286
|
+
]
|
|
287
|
+
if "chain_type" in network_config:
|
|
288
|
+
networks_config[network_name].chain_type = network_config["chain_type"]
|
|
227
289
|
continue
|
|
228
290
|
|
|
229
291
|
url = network_config["url"]
|
|
230
292
|
accounts = network_config["accounts"]
|
|
231
293
|
from_account = network_config.get("from", accounts[0])
|
|
232
294
|
network_id = network_config.get("id")
|
|
233
|
-
leader_only = network_config.get("leader_only",
|
|
295
|
+
leader_only = network_config.get("leader_only", DEFAULT_LEADER_ONLY)
|
|
296
|
+
default_wait_interval = network_config.get(
|
|
297
|
+
"default_wait_interval", DEFAULT_WAIT_INTERVAL
|
|
298
|
+
)
|
|
299
|
+
default_wait_retries = network_config.get(
|
|
300
|
+
"default_wait_retries", DEFAULT_WAIT_RETRIES
|
|
301
|
+
)
|
|
302
|
+
chain_type = network_config["chain_type"] # Required for custom networks
|
|
234
303
|
networks_config[network_name] = NetworkConfigData(
|
|
235
304
|
id=network_id,
|
|
236
305
|
url=url,
|
|
237
306
|
accounts=accounts,
|
|
238
307
|
from_account=from_account,
|
|
239
308
|
leader_only=leader_only,
|
|
309
|
+
default_wait_interval=default_wait_interval,
|
|
310
|
+
default_wait_retries=default_wait_retries,
|
|
311
|
+
chain_type=chain_type,
|
|
240
312
|
)
|
|
241
313
|
return networks_config, user_default_network
|
|
242
314
|
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
genlayer_test-0.8.0.dist-info/licenses/LICENSE,sha256=che_H4vE0QUx3HvWrAa1_jDEVInift0U6VO15-QqEls,1064
|
|
2
|
-
gltest/__init__.py,sha256=49112x2CLdYwvCbBZ1laJmMk0NQ7S3u5YUbxPefqhrk,454
|
|
3
|
-
gltest/accounts.py,sha256=HUmWguJMolggQaZNRPw-LGlRlQCjLLdUanKRowMv6pI,812
|
|
4
|
-
gltest/assertions.py,sha256=0dEk0VxcHK4I7GZPHxJmz-2jaA60V499gOSR74rZbfM,1748
|
|
5
|
-
gltest/clients.py,sha256=1dX6wmG3QCevQRLbSaFlHymZSb-sJ5aYwet1IoX2nbA,1554
|
|
6
|
-
gltest/exceptions.py,sha256=deJPmrTe5gF33qkkKF2IVJY7lc_knI7Ql3N7jZ8aLZs,510
|
|
7
|
-
gltest/fixtures.py,sha256=EJXmqcC3LD03v07mepacFl58lAdhbLj6bP5rtALYISk,2507
|
|
8
|
-
gltest/logging.py,sha256=jAkHsuMm-AEx1Xu1srU6W-0YzTwXJB48mCK-OVzAiN4,342
|
|
9
|
-
gltest/types.py,sha256=H32fHrU5aFMaPHXgEWcHAmLWOZ9pBFVp8PK_ncpVOgM,940
|
|
10
|
-
gltest/utils.py,sha256=-gHhjrS7i_GhDG3sKOq2qsTtYBt4HHgXHEXh-3RB_rI,573
|
|
11
|
-
gltest/artifacts/__init__.py,sha256=qTt3TE19gVNWnQLUlt5aDe4nNvJ2YJ1jzDkMmYIsCG0,194
|
|
12
|
-
gltest/artifacts/contract.py,sha256=KChpmfjZod_0dVB8y-dvWz6IVm7QlIJsgG2ArtvVDaU,6457
|
|
13
|
-
gltest/contracts/__init__.py,sha256=A9bvEtYOoqoHS8TLlFBfmNOnfwdsJPEf-AZuikagCHM,166
|
|
14
|
-
gltest/contracts/contract.py,sha256=jLF_ojSM6IIbdGO2_DhsO79r2wZ2Z8eBAJRrZk2qVTI,7748
|
|
15
|
-
gltest/contracts/contract_factory.py,sha256=PpWh4mKf1hDMv_yms5lwFV_EoXxXiuNfdXbwD74hbAU,8929
|
|
16
|
-
gltest/contracts/contract_functions.py,sha256=W6Dpw1z-n9EeJxlNtIbeVnzpv4BPABhtgmgjnS8-P0w,2573
|
|
17
|
-
gltest/contracts/method_stats.py,sha256=zWWjvf7K5VC4yrHpDIR717VF7LYp1RaZ1Hr_RZvWxJA,5150
|
|
18
|
-
gltest/contracts/stats_collector.py,sha256=iwsnoYo5aZbI4SVMH7dR-5CQgkglExXfsvaUDpwcdss,9286
|
|
19
|
-
gltest/contracts/utils.py,sha256=TTXgcXn9BuRIlKJrjwmU7R3l1IgXsXk2luM-r3lfbbg,296
|
|
20
|
-
gltest/helpers/__init__.py,sha256=I7HiTu_H7_hP65zY6Wl02r-5eAMr2eZvqBVmusuQLX4,180
|
|
21
|
-
gltest/helpers/fixture_snapshot.py,sha256=bMgvlEVQBGIQzj7NOyosXWlphI1H2C1o75Zo0C-kGfQ,1931
|
|
22
|
-
gltest/helpers/take_snapshot.py,sha256=-QkaBvFG4ZsNKv_nCSEsy5Ze1pICOHxVhReSeQmZUlY,1276
|
|
23
|
-
gltest/validators/__init__.py,sha256=AXboXORF5a8MVtG7jWMT1fJcwGXNzcX6txXQstwX2EU,152
|
|
24
|
-
gltest/validators/validator_factory.py,sha256=fpb-YyAKuWo4-pXBjrZ_TApYLsm6HHa6kGpbFByRucs,3886
|
|
25
|
-
gltest_cli/logging.py,sha256=WXVhfq9vT6FtV_jxDqGEGia1ZWSIUKAfmWRnZd_gWQk,1266
|
|
26
|
-
gltest_cli/main.py,sha256=Ti2-0Ev1x5_cM0D1UKqdgaDt80CDHEQGtdRne2qLm4M,53
|
|
27
|
-
gltest_cli/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
-
gltest_cli/config/constants.py,sha256=LG74S_65OXhqweL__PGRV6Ms8UkMFYSeK7Sq88viBis,411
|
|
29
|
-
gltest_cli/config/general.py,sha256=ezpoGsT8grO9zQH6RugV14b1GzeFt-htYToHQBJhNvY,186
|
|
30
|
-
gltest_cli/config/plugin.py,sha256=TsK3JnKKz_9azASHcKKSY5ohCl5TmxVUk_YEGIc4A28,6469
|
|
31
|
-
gltest_cli/config/pytest_context.py,sha256=Ze8JSkrwMTCE8jIhpzU_71CEXg92SiEPvSgNTp-gbS4,243
|
|
32
|
-
gltest_cli/config/types.py,sha256=0x8I-Xvzul9lGkPL0GusxJPhJCNajx-ghm0N-V5P594,8206
|
|
33
|
-
gltest_cli/config/user.py,sha256=SXGWQnA6422vRhQ9Xwxuzts7ZARcBIJZcRFSxN56PV4,9970
|
|
34
|
-
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
-
tests/conftest.py,sha256=RKdoE5_zcMimeojAoA_GSFI9du4pMzMi1vZ1njtfoAs,28
|
|
36
|
-
tests/examples/contracts/football_prediction_market.py,sha256=9xwU8f3q73Hae-ByHy_wauhMPLRnLZd4XKNrClnjOJM,3248
|
|
37
|
-
tests/examples/contracts/intelligent_oracle.py,sha256=cZNGbjKMXY-pimVmPIKIlS963Gd3L1JAipq0VBR1J5Q,12360
|
|
38
|
-
tests/examples/contracts/intelligent_oracle_factory.py,sha256=6UApEdPzcUXR18wMpaQXtWpEKeQjU0zDkI5ezghuJUo,1526
|
|
39
|
-
tests/examples/contracts/invalid_deploy.py,sha256=cHXV0aq8gfbWdvjchnjSeoZDCCC-5iNdLGUkJi-tQfo,228
|
|
40
|
-
tests/examples/contracts/llm_erc20.py,sha256=pOvSUszCtC_f5yDX0tZnj494Ce10uESZ09JLLE8V67o,2534
|
|
41
|
-
tests/examples/contracts/log_indexer.py,sha256=Nlf8XUt13ujam3k6hbbVrPHK-KJ366Csz1TBjc4P07g,1901
|
|
42
|
-
tests/examples/contracts/multi_read_erc20.py,sha256=28qYqn191Ro3rP7YJtZwL6Sc7JDXTeh8_QoqvdVPdqM,864
|
|
43
|
-
tests/examples/contracts/multi_tenant_storage.py,sha256=ceq3X4E7pkvSdy7eQMhAoHme4KFedjAcpkfUYBmcgVM,1941
|
|
44
|
-
tests/examples/contracts/read_erc20.py,sha256=RgH269F0x482WuLLYcacBnZsGJjhgJp6sG_33cV6Z-w,454
|
|
45
|
-
tests/examples/contracts/simple_time_contract.py,sha256=-9p_umlzUW5X2NL6IknO6Khs_114izSWifP5D2bWCMo,2512
|
|
46
|
-
tests/examples/contracts/storage.py,sha256=3DD3qvzb0JkVcBtu240e5kaZWgkh-bu6YExqBUYvfaw,501
|
|
47
|
-
tests/examples/contracts/user_storage.py,sha256=2W2Iv-hQZMkAaPl2RY_F-OeJpD4IlPxgWzN6e1bTkKE,649
|
|
48
|
-
tests/examples/contracts/wizard_of_coin.py,sha256=Y8daPpoSKdM8wfbCPOIgEdpkLIA1ZMmeg6Hu5fBB-kU,1624
|
|
49
|
-
tests/examples/contracts/multi_file_contract/__init__.py,sha256=xDn_wS62GhCmnYoI6xIqlic2i882SoPnR2TEauKc9tQ,575
|
|
50
|
-
tests/examples/contracts/multi_file_contract/other.py,sha256=jHDtjUL3eAUgE6yOYKFw_RfAH7kIwk8CvxUjbWHNruk,236
|
|
51
|
-
tests/examples/tests/test_custom_validators.py,sha256=ounk3fBqDexAI3eRUqscMqKf5vz77tbSxW4Cz8tzfF0,2172
|
|
52
|
-
tests/examples/tests/test_football_prediction_market.py,sha256=f2hfDK76WrNJZtFkTPKoPRR6bkmFLEssnlwwltSnU9A,1111
|
|
53
|
-
tests/examples/tests/test_intelligent_oracle_factory.py,sha256=sL26aeb84XpJPCSUSIX3yrbwQE8GZtvNcsaKTpngFmY,7611
|
|
54
|
-
tests/examples/tests/test_invalid_deploy.py,sha256=pppM8_Vn4DXcWq9iyJXb0SpZnKXkIyJxoIDW5ApCS94,814
|
|
55
|
-
tests/examples/tests/test_llm_erc20.py,sha256=zb5F_7NgvZXhvqL2nULwzuTT6LGDprSy0WgrdjY7pZc,2096
|
|
56
|
-
tests/examples/tests/test_llm_erc20_analyze.py,sha256=rVnC3iQW_1J3P6cczEVOOG84K6ldCzlZbMO9WXQdRds,1849
|
|
57
|
-
tests/examples/tests/test_log_indexer.py,sha256=46AqL7qquNc9GX2wxFxVcQXLqruMnPmxXl1yeB0-KZ4,2869
|
|
58
|
-
tests/examples/tests/test_multi_file_contract.py,sha256=1Emj6ze4f-OrpxvqExeJhPHjK0cNAQW54MXf6fy2Yuc,469
|
|
59
|
-
tests/examples/tests/test_multi_read_erc20.py,sha256=pSZUxoB33Z2EBtcvXxfUgwGSi_h7ryPoovkiNIfNAVQ,3713
|
|
60
|
-
tests/examples/tests/test_multi_tenant_storage.py,sha256=8B3tjnRbT8ATN5obtWkGsN3nOtBU9OSjuaH9aEat3vc,2935
|
|
61
|
-
tests/examples/tests/test_read_erc20.py,sha256=vLGQwguaNnT497nSq-vt4LrXj4ehn5ZSgfPt0GVFoPc,1254
|
|
62
|
-
tests/examples/tests/test_simple_time_contract.py,sha256=HQCJNheFyaHh73jZHyGOhNItzg045o8XsW-jLnNp-xc,3199
|
|
63
|
-
tests/examples/tests/test_storage.py,sha256=y46nPjM-Jd9FVJmaNE29RPqamzxVwYtPPWE_GlXUsls,774
|
|
64
|
-
tests/examples/tests/test_user_storage.py,sha256=wk0r0AXfKNgI7Eeyc8noNlJKvZBFXDbXTQE_u19XxBQ,2927
|
|
65
|
-
tests/examples/tests/test_wizard_of_coin.py,sha256=AOQTanDsfZt9zIGkqZass_4BsGcVKTHzqRejN4KhSPI,854
|
|
66
|
-
tests/gltest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
67
|
-
tests/gltest/artifact/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
68
|
-
tests/gltest/artifact/test_contract_definition.py,sha256=riNNZ5Bu18zn5yuKXvJ5djRDmBNsFZTT0sdw9vX4Js8,2066
|
|
69
|
-
tests/gltest/artifact/contracts/duplicate_ic_contract_1.py,sha256=bSWsUVjBy5cGtI72cjnkstsMzuUJbB3IG5JjTxOF-dc,500
|
|
70
|
-
tests/gltest/artifact/contracts/duplicate_ic_contract_2.py,sha256=bSWsUVjBy5cGtI72cjnkstsMzuUJbB3IG5JjTxOF-dc,500
|
|
71
|
-
tests/gltest/artifact/contracts/not_ic_contract.py,sha256=hQyGnYiiVceYdLI2WrvcFgPqzy1S4-YMb9FPhiHEGSA,510
|
|
72
|
-
tests/gltest/assertions/test_assertions.py,sha256=qzVrOdOM4xYtIy1sFHVAD_-naDHOequ23tEN0MELh0k,10781
|
|
73
|
-
tests/gltest_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
74
|
-
tests/gltest_cli/config/test_config_integration.py,sha256=vPTzr3_h9UMw7m72HogBJE2ZPhRduXoLSq18Z7FoCWQ,10105
|
|
75
|
-
tests/gltest_cli/config/test_general_config.py,sha256=UHtSwVnso-ZwNtYM0Z4v2sCLKwyrVbHlk6b1leVfV84,14703
|
|
76
|
-
tests/gltest_cli/config/test_plugin.py,sha256=COrEK5tHP1BSzanWbZHmN3EQgE9VuTcPvB95pgOvKS4,7974
|
|
77
|
-
tests/gltest_cli/config/test_user.py,sha256=JxR655oUFoM9quWQO68CVPKRpT0TMpzS3bF6j6NWyT4,14401
|
|
78
|
-
genlayer_test-0.8.0.dist-info/METADATA,sha256=6LQF4o37U3qg9rmmLLoZps0XpC0T5gFsg_l4NZr7z4g,39178
|
|
79
|
-
genlayer_test-0.8.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
80
|
-
genlayer_test-0.8.0.dist-info/entry_points.txt,sha256=RWPcSArBpz_G4BYioh5L8Q8hyClRbSgzLimjcWMp-BQ,94
|
|
81
|
-
genlayer_test-0.8.0.dist-info/top_level.txt,sha256=-qiGZxTRBytujzgVcKpxjvQ-WNeUDjXa59ceGMwMpko,24
|
|
82
|
-
genlayer_test-0.8.0.dist-info/RECORD,,
|
tests/__init__.py
DELETED
|
File without changes
|
tests/conftest.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pytest_plugins = "pytester"
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
# v0.1.0
|
|
2
|
-
# { "Depends": "py-genlayer:latest" }
|
|
3
|
-
|
|
4
|
-
from genlayer import *
|
|
5
|
-
|
|
6
|
-
import json
|
|
7
|
-
import typing
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class PredictionMarket(gl.Contract):
|
|
11
|
-
has_resolved: bool
|
|
12
|
-
team1: str
|
|
13
|
-
team2: str
|
|
14
|
-
resolution_url: str
|
|
15
|
-
winner: u256
|
|
16
|
-
score: str
|
|
17
|
-
|
|
18
|
-
def __init__(self, game_date: str, team1: str, team2: str):
|
|
19
|
-
"""
|
|
20
|
-
Initializes a new instance of the prediction market with the specified game date and teams.
|
|
21
|
-
|
|
22
|
-
Args:
|
|
23
|
-
game_date (str): The date of the game in the format 'YYYY-MM-DD'.
|
|
24
|
-
team1 (str): The name of the first team.
|
|
25
|
-
team2 (str): The name of the second team.
|
|
26
|
-
|
|
27
|
-
Attributes:
|
|
28
|
-
has_resolved (bool): Indicates whether the game's resolution has been processed. Default is False.
|
|
29
|
-
game_date (str): The date of the game.
|
|
30
|
-
resolution_url (str): The URL to the game's resolution on BBC Sport.
|
|
31
|
-
team1 (str): The name of the first team.
|
|
32
|
-
team2 (str): The name of the second team.
|
|
33
|
-
"""
|
|
34
|
-
self.has_resolved = False
|
|
35
|
-
self.resolution_url = (
|
|
36
|
-
"https://www.bbc.com/sport/football/scores-fixtures/" + game_date
|
|
37
|
-
)
|
|
38
|
-
self.team1 = team1
|
|
39
|
-
self.team2 = team2
|
|
40
|
-
self.winner = u256(0)
|
|
41
|
-
self.score = ""
|
|
42
|
-
|
|
43
|
-
@gl.public.write
|
|
44
|
-
def resolve(self) -> typing.Any:
|
|
45
|
-
|
|
46
|
-
if self.has_resolved:
|
|
47
|
-
return "Already resolved"
|
|
48
|
-
|
|
49
|
-
market_resolution_url = self.resolution_url
|
|
50
|
-
team1 = self.team1
|
|
51
|
-
team2 = self.team2
|
|
52
|
-
|
|
53
|
-
def get_match_result() -> typing.Any:
|
|
54
|
-
web_data = gl.nondet.web.render(market_resolution_url, mode="text")
|
|
55
|
-
print(web_data)
|
|
56
|
-
|
|
57
|
-
task = f"""
|
|
58
|
-
In the following web page, find the winning team in a matchup between the following teams:
|
|
59
|
-
Team 1: {team1}
|
|
60
|
-
Team 2: {team2}
|
|
61
|
-
|
|
62
|
-
Web page content:
|
|
63
|
-
{web_data}
|
|
64
|
-
End of web page data.
|
|
65
|
-
|
|
66
|
-
If it says "Kick off [time]" between the names of the two teams, it means the game hasn't started yet.
|
|
67
|
-
If you fail to extract the score, assume the game is not resolved yet.
|
|
68
|
-
|
|
69
|
-
Respond with the following JSON format:
|
|
70
|
-
{{
|
|
71
|
-
"score": str, // The score with numbers only, e.g, "1:2", or "-" if the game is not resolved yet
|
|
72
|
-
"winner": int, // The number of the winning team, 0 for draw, or -1 if the game is not yet finished
|
|
73
|
-
}}
|
|
74
|
-
It is mandatory that you respond only using the JSON format above,
|
|
75
|
-
nothing else. Don't include any other words or characters,
|
|
76
|
-
your output must be only JSON without any formatting prefix or suffix.
|
|
77
|
-
This result should be perfectly parsable by a JSON parser without errors.
|
|
78
|
-
"""
|
|
79
|
-
result = (
|
|
80
|
-
gl.nondet.exec_prompt(task).replace("```json", "").replace("```", "")
|
|
81
|
-
)
|
|
82
|
-
print(result)
|
|
83
|
-
return json.loads(result)
|
|
84
|
-
|
|
85
|
-
result_json = gl.eq_principle.strict_eq(get_match_result)
|
|
86
|
-
|
|
87
|
-
if result_json["winner"] > -1:
|
|
88
|
-
self.has_resolved = True
|
|
89
|
-
self.winner = result_json["winner"]
|
|
90
|
-
self.score = result_json["score"]
|
|
91
|
-
|
|
92
|
-
return result_json
|
|
93
|
-
|
|
94
|
-
@gl.public.view
|
|
95
|
-
def get_resolution_data(self) -> dict[str, typing.Any]:
|
|
96
|
-
return {
|
|
97
|
-
"winner": self.winner,
|
|
98
|
-
"score": self.score,
|
|
99
|
-
"has_resolved": self.has_resolved,
|
|
100
|
-
}
|