genlayer-test 0.4.0__py3-none-any.whl → 0.5.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.4.0.dist-info → genlayer_test-0.5.0.dist-info}/METADATA +257 -24
- genlayer_test-0.5.0.dist-info/RECORD +76 -0
- gltest/__init__.py +7 -6
- gltest/{glchain/client.py → clients.py} +1 -1
- gltest/contracts/__init__.py +4 -0
- gltest/contracts/contract.py +205 -0
- gltest/{glchain/contract.py → contracts/contract_factory.py} +47 -144
- gltest/contracts/contract_functions.py +62 -0
- gltest/contracts/method_stats.py +163 -0
- gltest/contracts/stats_collector.py +259 -0
- gltest/contracts/utils.py +12 -0
- gltest/fixtures.py +2 -6
- gltest/helpers/take_snapshot.py +1 -1
- gltest/logging.py +17 -0
- gltest/types.py +1 -0
- gltest_cli/config/constants.py +2 -0
- gltest_cli/config/plugin.py +121 -49
- gltest_cli/config/pytest_context.py +9 -0
- gltest_cli/config/types.py +73 -8
- gltest_cli/config/user.py +71 -28
- gltest_cli/logging.py +4 -3
- tests/examples/contracts/football_prediction_market.py +1 -1
- tests/examples/tests/test_football_prediction_market.py +2 -2
- tests/examples/tests/test_intelligent_oracle_factory.py +8 -24
- tests/examples/tests/test_llm_erc20.py +5 -5
- tests/examples/tests/test_llm_erc20_analyze.py +50 -0
- tests/examples/tests/test_log_indexer.py +23 -11
- tests/examples/tests/test_multi_file_contract.py +2 -2
- tests/examples/tests/test_multi_file_contract_legacy.py +2 -2
- tests/examples/tests/test_multi_read_erc20.py +14 -12
- tests/examples/tests/test_multi_tenant_storage.py +11 -7
- tests/examples/tests/test_read_erc20.py +1 -1
- tests/examples/tests/test_storage.py +4 -4
- tests/examples/tests/test_storage_legacy.py +5 -3
- tests/examples/tests/test_user_storage.py +20 -10
- tests/examples/tests/test_wizard_of_coin.py +1 -1
- tests/gltest_cli/config/test_config_integration.py +432 -0
- tests/gltest_cli/config/test_general_config.py +406 -0
- tests/gltest_cli/config/test_plugin.py +164 -1
- tests/gltest_cli/config/test_user.py +61 -1
- genlayer_test-0.4.0.dist-info/RECORD +0 -66
- gltest/glchain/__init__.py +0 -16
- {genlayer_test-0.4.0.dist-info → genlayer_test-0.5.0.dist-info}/WHEEL +0 -0
- {genlayer_test-0.4.0.dist-info → genlayer_test-0.5.0.dist-info}/entry_points.txt +0 -0
- {genlayer_test-0.4.0.dist-info → genlayer_test-0.5.0.dist-info}/licenses/LICENSE +0 -0
- {genlayer_test-0.4.0.dist-info → genlayer_test-0.5.0.dist-info}/top_level.txt +0 -0
- /gltest/{glchain/account.py → accounts.py} +0 -0
gltest_cli/config/types.py
CHANGED
@@ -2,24 +2,22 @@ from enum import Enum
|
|
2
2
|
from dataclasses import dataclass, field
|
3
3
|
from pathlib import Path
|
4
4
|
from typing import Dict, List, Optional
|
5
|
-
from genlayer_py.chains import localnet, testnet_asimov
|
5
|
+
from genlayer_py.chains import localnet, studionet, testnet_asimov
|
6
6
|
from genlayer_py.types import GenLayerChain
|
7
7
|
from urllib.parse import urlparse
|
8
|
-
|
9
|
-
|
10
|
-
class NetworkConfig(str, Enum):
|
11
|
-
LOCALNET = "localnet"
|
12
|
-
TESTNET_ASIMOV = "testnet_asimov"
|
8
|
+
from gltest_cli.config.constants import PRECONFIGURED_NETWORKS
|
13
9
|
|
14
10
|
|
15
11
|
@dataclass
|
16
12
|
class PluginConfig:
|
17
13
|
contracts_dir: Optional[Path] = None
|
14
|
+
artifacts_dir: Optional[Path] = None
|
18
15
|
rpc_url: Optional[str] = None
|
19
16
|
default_wait_interval: Optional[int] = None
|
20
17
|
default_wait_retries: Optional[int] = None
|
21
18
|
network_name: Optional[str] = None
|
22
19
|
test_with_mocks: bool = False
|
20
|
+
leader_only: bool = False
|
23
21
|
|
24
22
|
|
25
23
|
@dataclass
|
@@ -28,6 +26,7 @@ class NetworkConfigData:
|
|
28
26
|
url: Optional[str] = None
|
29
27
|
accounts: Optional[List[str]] = None
|
30
28
|
from_account: Optional[str] = None
|
29
|
+
leader_only: bool = False
|
31
30
|
|
32
31
|
def __post_init__(self):
|
33
32
|
if self.id is not None and not isinstance(self.id, int):
|
@@ -46,10 +45,13 @@ class NetworkConfigData:
|
|
46
45
|
@dataclass
|
47
46
|
class PathConfig:
|
48
47
|
contracts: Optional[Path] = None
|
48
|
+
artifacts: Optional[Path] = None
|
49
49
|
|
50
50
|
def __post_init__(self):
|
51
51
|
if self.contracts is not None and not isinstance(self.contracts, (str, Path)):
|
52
52
|
raise ValueError("contracts must be a string or Path")
|
53
|
+
if self.artifacts is not None and not isinstance(self.artifacts, (str, Path)):
|
54
|
+
raise ValueError("artifacts must be a string or Path")
|
53
55
|
|
54
56
|
|
55
57
|
@dataclass
|
@@ -93,10 +95,29 @@ class GeneralConfig:
|
|
93
95
|
def set_contracts_dir(self, contracts_dir: Path):
|
94
96
|
self.plugin_config.contracts_dir = contracts_dir
|
95
97
|
|
98
|
+
def get_artifacts_dir(self) -> Path:
|
99
|
+
if self.plugin_config.artifacts_dir is not None:
|
100
|
+
return self.plugin_config.artifacts_dir
|
101
|
+
return self.user_config.paths.artifacts
|
102
|
+
|
103
|
+
def set_artifacts_dir(self, artifacts_dir: Path):
|
104
|
+
self.plugin_config.artifacts_dir = artifacts_dir
|
105
|
+
|
106
|
+
def get_analysis_dir(self) -> Path:
|
107
|
+
artifacts_dir = self.get_artifacts_dir()
|
108
|
+
return artifacts_dir / "analysis"
|
109
|
+
|
110
|
+
def get_networks_keys(self) -> List[str]:
|
111
|
+
return list(self.user_config.networks.keys())
|
112
|
+
|
96
113
|
def get_rpc_url(self) -> str:
|
97
114
|
if self.plugin_config.rpc_url is not None:
|
98
115
|
return self.plugin_config.rpc_url
|
99
116
|
network_name = self.get_network_name()
|
117
|
+
if network_name not in self.user_config.networks:
|
118
|
+
raise ValueError(
|
119
|
+
f"Unknown network: {network_name}, possible values: {self.get_networks_keys()}"
|
120
|
+
)
|
100
121
|
return self.user_config.networks[network_name].url
|
101
122
|
|
102
123
|
def get_default_account_key(self, network_name: Optional[str] = None) -> str:
|
@@ -110,16 +131,37 @@ class GeneralConfig:
|
|
110
131
|
return self.user_config.networks[self.user_config.default_network].accounts
|
111
132
|
|
112
133
|
def get_chain(self) -> GenLayerChain:
|
134
|
+
network_name = self.get_network_name()
|
135
|
+
if network_name not in self.user_config.networks:
|
136
|
+
raise ValueError(
|
137
|
+
f"Unknown network: {network_name}, possible values: {self.get_networks_keys()}"
|
138
|
+
)
|
139
|
+
|
140
|
+
# Reserved network names
|
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
|
+
|
150
|
+
if network_name in PRECONFIGURED_NETWORKS:
|
151
|
+
raise ValueError(
|
152
|
+
f"Network {network_name} should be handled by reserved mapping"
|
153
|
+
)
|
154
|
+
|
155
|
+
# Custom networks
|
113
156
|
chain_map_by_id = {
|
114
157
|
61999: localnet,
|
115
158
|
4221: testnet_asimov,
|
116
159
|
}
|
117
|
-
network_name = self.get_network_name()
|
118
160
|
network_id = self.user_config.networks[network_name].id
|
119
161
|
if network_id not in chain_map_by_id:
|
120
162
|
known = ", ".join(map(str, chain_map_by_id.keys()))
|
121
163
|
raise ValueError(
|
122
|
-
f"Unknown network: {
|
164
|
+
f"Unknown network id: {network_id}, possible values: {known}"
|
123
165
|
)
|
124
166
|
return chain_map_by_id[network_id]
|
125
167
|
|
@@ -141,8 +183,31 @@ class GeneralConfig:
|
|
141
183
|
def get_test_with_mocks(self) -> bool:
|
142
184
|
return self.plugin_config.test_with_mocks
|
143
185
|
|
186
|
+
def get_leader_only(self) -> bool:
|
187
|
+
if self.plugin_config.leader_only:
|
188
|
+
return True
|
189
|
+
network_name = self.get_network_name()
|
190
|
+
if network_name in self.user_config.networks:
|
191
|
+
network_config = self.user_config.networks[network_name]
|
192
|
+
return network_config.leader_only
|
193
|
+
return False
|
194
|
+
|
144
195
|
def check_local_rpc(self) -> bool:
|
145
196
|
SUPPORTED_RPC_DOMAINS = ["localhost", "127.0.0.1"]
|
146
197
|
rpc_url = self.get_rpc_url()
|
147
198
|
domain = urlparse(rpc_url).netloc.split(":")[0] # Extract domain without port
|
148
199
|
return domain in SUPPORTED_RPC_DOMAINS
|
200
|
+
|
201
|
+
def check_studio_based_rpc(self) -> bool:
|
202
|
+
SUPPORTED_RPC_DOMAINS = ["localhost", "127.0.0.1"]
|
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
|
gltest_cli/config/user.py
CHANGED
@@ -4,20 +4,21 @@ import re
|
|
4
4
|
from dotenv import load_dotenv
|
5
5
|
from pathlib import Path
|
6
6
|
from functools import lru_cache
|
7
|
-
from gltest.
|
7
|
+
from gltest.accounts import create_accounts
|
8
8
|
from gltest_cli.config.constants import (
|
9
9
|
GLTEST_CONFIG_FILE,
|
10
10
|
DEFAULT_NETWORK,
|
11
|
-
DEFAULT_RPC_URL,
|
12
11
|
DEFAULT_ENVIRONMENT,
|
13
12
|
DEFAULT_CONTRACTS_DIR,
|
14
|
-
|
13
|
+
DEFAULT_ARTIFACTS_DIR,
|
14
|
+
PRECONFIGURED_NETWORKS,
|
15
15
|
)
|
16
|
+
from genlayer_py.chains import localnet, studionet, testnet_asimov
|
16
17
|
from gltest_cli.config.types import UserConfig, NetworkConfigData, PathConfig
|
17
18
|
|
18
19
|
VALID_ROOT_KEYS = ["networks", "paths", "environment"]
|
19
|
-
VALID_NETWORK_KEYS = ["id", "url", "accounts", "from"]
|
20
|
-
VALID_PATHS_KEYS = ["contracts"]
|
20
|
+
VALID_NETWORK_KEYS = ["id", "url", "accounts", "from", "leader_only"]
|
21
|
+
VALID_PATHS_KEYS = ["contracts", "artifacts"]
|
21
22
|
|
22
23
|
|
23
24
|
@lru_cache(maxsize=1)
|
@@ -25,16 +26,35 @@ def get_default_user_config() -> UserConfig:
|
|
25
26
|
accounts = create_accounts(n_accounts=10)
|
26
27
|
accounts_private_keys = [account.key.hex() for account in accounts]
|
27
28
|
|
29
|
+
networks = {
|
30
|
+
"localnet": NetworkConfigData(
|
31
|
+
id=localnet.id,
|
32
|
+
url=localnet.rpc_urls["default"]["http"][0],
|
33
|
+
accounts=accounts_private_keys,
|
34
|
+
from_account=accounts_private_keys[0],
|
35
|
+
leader_only=False,
|
36
|
+
),
|
37
|
+
"studionet": NetworkConfigData(
|
38
|
+
id=studionet.id,
|
39
|
+
url=studionet.rpc_urls["default"]["http"][0],
|
40
|
+
accounts=accounts_private_keys,
|
41
|
+
from_account=accounts_private_keys[0],
|
42
|
+
leader_only=False,
|
43
|
+
),
|
44
|
+
"testnet_asimov": NetworkConfigData(
|
45
|
+
id=testnet_asimov.id,
|
46
|
+
url=testnet_asimov.rpc_urls["default"]["http"][0],
|
47
|
+
accounts=None,
|
48
|
+
from_account=None,
|
49
|
+
leader_only=False,
|
50
|
+
),
|
51
|
+
}
|
52
|
+
|
28
53
|
return UserConfig(
|
29
|
-
networks=
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
accounts=accounts_private_keys,
|
34
|
-
from_account=accounts_private_keys[0],
|
35
|
-
),
|
36
|
-
},
|
37
|
-
paths=PathConfig(contracts=DEFAULT_CONTRACTS_DIR),
|
54
|
+
networks=networks,
|
55
|
+
paths=PathConfig(
|
56
|
+
contracts=DEFAULT_CONTRACTS_DIR, artifacts=DEFAULT_ARTIFACTS_DIR
|
57
|
+
),
|
38
58
|
environment=DEFAULT_ENVIRONMENT,
|
39
59
|
default_network=DEFAULT_NETWORK,
|
40
60
|
)
|
@@ -42,11 +62,26 @@ def get_default_user_config() -> UserConfig:
|
|
42
62
|
|
43
63
|
def resolve_env_vars(obj):
|
44
64
|
if isinstance(obj, str):
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
65
|
+
|
66
|
+
def replace_env_var(m):
|
67
|
+
try:
|
68
|
+
var_name = m.group(1)
|
69
|
+
if var_name is None:
|
70
|
+
raise ValueError(
|
71
|
+
f"Invalid environment variable pattern: {m.group(0)}"
|
72
|
+
)
|
73
|
+
var_value = os.getenv(var_name)
|
74
|
+
if var_value is None:
|
75
|
+
raise ValueError(
|
76
|
+
f"Environment variable {var_name} is not set, please check your environment file"
|
77
|
+
)
|
78
|
+
return var_value
|
79
|
+
except IndexError as e:
|
80
|
+
raise ValueError(
|
81
|
+
f"Invalid environment variable pattern: {m.group(0)}"
|
82
|
+
) from e
|
83
|
+
|
84
|
+
return re.sub(r"\${(\w+)}", replace_env_var, obj)
|
50
85
|
elif isinstance(obj, dict):
|
51
86
|
return {k: resolve_env_vars(v) for k, v in obj.items()}
|
52
87
|
elif isinstance(obj, list):
|
@@ -81,9 +116,13 @@ def validate_network_config(network_name: str, network_config: dict):
|
|
81
116
|
|
82
117
|
if "from" in network_config and not isinstance(network_config["from"], str):
|
83
118
|
raise ValueError(f"network {network_name} from must be a string")
|
119
|
+
if "leader_only" in network_config and not isinstance(
|
120
|
+
network_config["leader_only"], bool
|
121
|
+
):
|
122
|
+
raise ValueError(f"network {network_name} leader_only must be a boolean")
|
84
123
|
|
85
|
-
# For non-
|
86
|
-
if network_name
|
124
|
+
# For non-preconfigured networks, url and accounts are required
|
125
|
+
if network_name not in PRECONFIGURED_NETWORKS:
|
87
126
|
if "id" not in network_config:
|
88
127
|
raise ValueError(f"network {network_name} must have an id")
|
89
128
|
if "url" not in network_config:
|
@@ -131,7 +170,6 @@ def validate_raw_user_config(config: dict):
|
|
131
170
|
def load_user_config(path: str) -> UserConfig:
|
132
171
|
with open(path, "r") as f:
|
133
172
|
raw_config = yaml.safe_load(f) or {}
|
134
|
-
|
135
173
|
validate_raw_user_config(raw_config)
|
136
174
|
load_dotenv(
|
137
175
|
dotenv_path=raw_config.get("environment", DEFAULT_ENVIRONMENT), override=True
|
@@ -168,8 +206,8 @@ def _get_overridden_networks(raw_config: dict) -> tuple[dict, str]:
|
|
168
206
|
|
169
207
|
networks_config = {}
|
170
208
|
for network_name, network_config in networks.items():
|
171
|
-
if network_name
|
172
|
-
networks_config[network_name] = default_config.networks[
|
209
|
+
if network_name in PRECONFIGURED_NETWORKS:
|
210
|
+
networks_config[network_name] = default_config.networks[network_name]
|
173
211
|
if network_config is None:
|
174
212
|
continue
|
175
213
|
|
@@ -182,18 +220,23 @@ def _get_overridden_networks(raw_config: dict) -> tuple[dict, str]:
|
|
182
220
|
]
|
183
221
|
if "from" in network_config:
|
184
222
|
networks_config[network_name].from_account = network_config["from"]
|
223
|
+
if "leader_only" in network_config:
|
224
|
+
networks_config[network_name].leader_only = network_config[
|
225
|
+
"leader_only"
|
226
|
+
]
|
185
227
|
continue
|
186
228
|
|
187
229
|
url = network_config["url"]
|
188
230
|
accounts = network_config["accounts"]
|
189
231
|
from_account = network_config.get("from", accounts[0])
|
190
232
|
network_id = network_config.get("id")
|
191
|
-
|
233
|
+
leader_only = network_config.get("leader_only", False)
|
192
234
|
networks_config[network_name] = NetworkConfigData(
|
193
235
|
id=network_id,
|
194
236
|
url=url,
|
195
237
|
accounts=accounts,
|
196
238
|
from_account=from_account,
|
239
|
+
leader_only=leader_only,
|
197
240
|
)
|
198
241
|
return networks_config, user_default_network
|
199
242
|
|
@@ -208,10 +251,10 @@ def _get_overridden_environment(raw_config: dict) -> str:
|
|
208
251
|
def _get_overridden_paths(raw_config: dict) -> PathConfig:
|
209
252
|
default_config = get_default_user_config()
|
210
253
|
if "paths" in raw_config:
|
254
|
+
paths_config = raw_config.get("paths", {})
|
211
255
|
return PathConfig(
|
212
|
-
contracts=Path(
|
213
|
-
|
214
|
-
)
|
256
|
+
contracts=Path(paths_config.get("contracts", DEFAULT_CONTRACTS_DIR)),
|
257
|
+
artifacts=Path(paths_config.get("artifacts", DEFAULT_ARTIFACTS_DIR)),
|
215
258
|
)
|
216
259
|
return default_config.paths
|
217
260
|
|
gltest_cli/logging.py
CHANGED
@@ -30,14 +30,15 @@ class ColoredFormatter(logging.Formatter):
|
|
30
30
|
|
31
31
|
|
32
32
|
def setup_logger():
|
33
|
-
logger = logging.getLogger("
|
34
|
-
|
33
|
+
logger = logging.getLogger("gltest_cli")
|
34
|
+
log_level = logging.INFO
|
35
|
+
logger.setLevel(log_level)
|
35
36
|
|
36
37
|
if logger.handlers:
|
37
38
|
return logger
|
38
39
|
|
39
40
|
console_handler = logging.StreamHandler()
|
40
|
-
console_handler.setLevel(
|
41
|
+
console_handler.setLevel(log_level)
|
41
42
|
|
42
43
|
formatter = ColoredFormatter("%(levelname)s: %(message)s")
|
43
44
|
console_handler.setFormatter(formatter)
|
@@ -27,11 +27,11 @@ def test_football_prediction_market(setup_validators):
|
|
27
27
|
contract = factory.deploy(args=["2024-06-26", "Georgia", "Portugal"])
|
28
28
|
|
29
29
|
# Resolve match
|
30
|
-
transaction_response_call_1 = contract.resolve(args=[])
|
30
|
+
transaction_response_call_1 = contract.resolve(args=[]).transact()
|
31
31
|
assert tx_execution_succeeded(transaction_response_call_1)
|
32
32
|
|
33
33
|
# Get Updated State
|
34
|
-
contract_state_2 = contract.get_resolution_data(args=[])
|
34
|
+
contract_state_2 = contract.get_resolution_data(args=[]).call()
|
35
35
|
|
36
36
|
assert contract_state_2["winner"] == 1
|
37
37
|
assert contract_state_2["score"] == "2:0"
|
@@ -1,24 +1,10 @@
|
|
1
|
-
import time
|
2
1
|
import json
|
2
|
+
from gltest.types import TransactionStatus
|
3
3
|
|
4
4
|
from gltest import get_contract_factory
|
5
5
|
from gltest.assertions import tx_execution_succeeded
|
6
6
|
|
7
7
|
|
8
|
-
def wait_for_contract_deployment(intelligent_oracle_contract, max_retries=10, delay=5):
|
9
|
-
"""
|
10
|
-
Wait for intelligent oracle contract to be fully deployed by attempting to call a method.
|
11
|
-
This is used to check if the triggered deployment did deploy the contract.
|
12
|
-
"""
|
13
|
-
for _ in range(max_retries):
|
14
|
-
try:
|
15
|
-
intelligent_oracle_contract.get_dict(args=[])
|
16
|
-
return True # If successful, contract is deployed
|
17
|
-
except Exception:
|
18
|
-
time.sleep(delay)
|
19
|
-
return False
|
20
|
-
|
21
|
-
|
22
8
|
def create_mock_response(markets_data):
|
23
9
|
reasoning_single_source_marathon = "The HTML content contains the results of the Madrid Marathon 2024, which occurred on April 28, 2024. Mitku Tafa won and matches the name 'Tafa Mitku' in the list of potential outcomes."
|
24
10
|
reasoning_all_sources_marathon = "The URL indicates that the Madrid Marathon 2024 has occurred on April 28, 2024, and Mitku Tafa was the winner. The name matches one of the potential outcomes. There are no conflicting sources."
|
@@ -124,28 +110,26 @@ def test_intelligent_oracle_factory_pattern(setup_validators):
|
|
124
110
|
market_data["resolution_urls"],
|
125
111
|
market_data["earliest_resolution_date"],
|
126
112
|
],
|
113
|
+
).transact(
|
114
|
+
wait_triggered_transactions=True,
|
115
|
+
wait_triggered_transactions_status=TransactionStatus.ACCEPTED,
|
127
116
|
)
|
128
117
|
assert tx_execution_succeeded(create_result)
|
129
118
|
|
130
119
|
# Get the latest contract address from factory
|
131
|
-
registered_addresses = registry_contract.get_contract_addresses(args=[])
|
120
|
+
registered_addresses = registry_contract.get_contract_addresses(args=[]).call()
|
132
121
|
new_market_address = registered_addresses[-1]
|
133
122
|
|
134
123
|
# Build a contract object
|
135
124
|
market_contract = intelligent_oracle_factory.build_contract(new_market_address)
|
136
125
|
created_market_contracts.append(market_contract)
|
137
126
|
|
138
|
-
# Wait for the new market contract to be deployed
|
139
|
-
assert wait_for_contract_deployment(
|
140
|
-
market_contract
|
141
|
-
), f"Market contract deployment timeout for {market_data['prediction_market_id']}"
|
142
|
-
|
143
127
|
# Verify all markets were registered
|
144
128
|
assert len(registered_addresses) == len(markets_data)
|
145
129
|
|
146
130
|
# Verify each market's state
|
147
131
|
for i, market_contract in enumerate(created_market_contracts):
|
148
|
-
market_state = market_contract.get_dict(args=[])
|
132
|
+
market_state = market_contract.get_dict(args=[]).call()
|
149
133
|
expected_data = markets_data[i]
|
150
134
|
|
151
135
|
# Verify key market properties
|
@@ -171,10 +155,10 @@ def test_intelligent_oracle_factory_pattern(setup_validators):
|
|
171
155
|
for i, market_contract in enumerate(created_market_contracts):
|
172
156
|
resolve_result = market_contract.resolve(
|
173
157
|
args=[markets_data[i]["evidence_urls"]],
|
174
|
-
)
|
158
|
+
).transact()
|
175
159
|
assert tx_execution_succeeded(resolve_result)
|
176
160
|
|
177
161
|
# Verify market was resolved and has the correct outcome
|
178
|
-
market_state = market_contract.get_dict(args=[])
|
162
|
+
market_state = market_contract.get_dict(args=[]).call()
|
179
163
|
assert market_state["status"] == "Resolved"
|
180
164
|
assert market_state["outcome"] == markets_data[i]["outcome"]
|
@@ -34,17 +34,17 @@ def test_llm_erc20(setup_validators):
|
|
34
34
|
contract = factory.deploy(args=[TOKEN_TOTAL_SUPPLY])
|
35
35
|
|
36
36
|
# Get Initial State
|
37
|
-
contract_state_1 = contract.get_balances(args=[])
|
37
|
+
contract_state_1 = contract.get_balances(args=[]).call()
|
38
38
|
assert contract_state_1[from_account_a.address] == TOKEN_TOTAL_SUPPLY
|
39
39
|
|
40
40
|
# Transfer from User A to User B
|
41
41
|
transaction_response_call_1 = contract.transfer(
|
42
42
|
args=[TRANSFER_AMOUNT, from_account_b.address]
|
43
|
-
)
|
43
|
+
).transact()
|
44
44
|
assert tx_execution_succeeded(transaction_response_call_1)
|
45
45
|
|
46
46
|
# Get Updated State
|
47
|
-
contract_state_2_1 = contract.get_balances(args=[])
|
47
|
+
contract_state_2_1 = contract.get_balances(args=[]).call()
|
48
48
|
assert (
|
49
49
|
contract_state_2_1[from_account_a.address]
|
50
50
|
== TOKEN_TOTAL_SUPPLY - TRANSFER_AMOUNT
|
@@ -52,9 +52,9 @@ def test_llm_erc20(setup_validators):
|
|
52
52
|
assert contract_state_2_1[from_account_b.address] == TRANSFER_AMOUNT
|
53
53
|
|
54
54
|
# Get Updated State
|
55
|
-
contract_state_2_2 = contract.get_balance_of(args=[from_account_a.address])
|
55
|
+
contract_state_2_2 = contract.get_balance_of(args=[from_account_a.address]).call()
|
56
56
|
assert contract_state_2_2 == TOKEN_TOTAL_SUPPLY - TRANSFER_AMOUNT
|
57
57
|
|
58
58
|
# Get Updated State
|
59
|
-
contract_state_2_3 = contract.get_balance_of(args=[from_account_b.address])
|
59
|
+
contract_state_2_3 = contract.get_balance_of(args=[from_account_b.address]).call()
|
60
60
|
assert contract_state_2_3 == TRANSFER_AMOUNT
|
@@ -0,0 +1,50 @@
|
|
1
|
+
from gltest import get_contract_factory, get_default_account, create_account
|
2
|
+
|
3
|
+
|
4
|
+
TOKEN_TOTAL_SUPPLY = 1000
|
5
|
+
TRANSFER_AMOUNT = 100
|
6
|
+
|
7
|
+
|
8
|
+
def test_llm_erc20_analyze(setup_validators):
|
9
|
+
setup_validators()
|
10
|
+
# Account Setup
|
11
|
+
from_account_a = get_default_account()
|
12
|
+
from_account_b = create_account()
|
13
|
+
|
14
|
+
# Deploy Contract
|
15
|
+
factory = get_contract_factory("LlmErc20")
|
16
|
+
contract = factory.deploy(args=[TOKEN_TOTAL_SUPPLY])
|
17
|
+
|
18
|
+
# Get Initial State
|
19
|
+
contract_state_1 = contract.get_balances(args=[]).call()
|
20
|
+
assert contract_state_1[from_account_a.address] == TOKEN_TOTAL_SUPPLY
|
21
|
+
|
22
|
+
# Transfer from User A to User B
|
23
|
+
stats = contract.transfer(args=[TRANSFER_AMOUNT, from_account_b.address]).analyze(
|
24
|
+
provider="openai", model="gpt-4o", runs=3
|
25
|
+
)
|
26
|
+
|
27
|
+
# Verify it's a MethodStatsSummary object
|
28
|
+
assert hasattr(stats, "method")
|
29
|
+
assert hasattr(stats, "args")
|
30
|
+
assert hasattr(stats, "total_runs")
|
31
|
+
assert hasattr(stats, "execution_time")
|
32
|
+
assert hasattr(stats, "provider")
|
33
|
+
assert hasattr(stats, "model")
|
34
|
+
|
35
|
+
# Check basic properties
|
36
|
+
assert stats.method == "transfer"
|
37
|
+
assert stats.args == [TRANSFER_AMOUNT, from_account_b.address]
|
38
|
+
assert stats.total_runs == 3
|
39
|
+
assert stats.provider == "openai"
|
40
|
+
assert stats.model == "gpt-4o"
|
41
|
+
assert isinstance(stats.execution_time, float)
|
42
|
+
|
43
|
+
# Check string representation
|
44
|
+
stats_str = str(stats)
|
45
|
+
assert "Method analysis summary" in stats_str
|
46
|
+
assert "Method: transfer" in stats_str
|
47
|
+
assert f"Args: [{TRANSFER_AMOUNT}, '{from_account_b.address}']" in stats_str
|
48
|
+
assert f"Total runs: {stats.total_runs}" in stats_str
|
49
|
+
assert f"Provider: {stats.provider}" in stats_str
|
50
|
+
assert f"Model: {stats.model}" in stats_str
|
@@ -9,56 +9,68 @@ def test_log_indexer(setup_validators):
|
|
9
9
|
contract = factory.deploy(args=[])
|
10
10
|
|
11
11
|
# Get closest vector when empty
|
12
|
-
closest_vector_log_0 = contract.get_closest_vector(args=["I like mango"])
|
12
|
+
closest_vector_log_0 = contract.get_closest_vector(args=["I like mango"]).call()
|
13
13
|
assert closest_vector_log_0 is None
|
14
14
|
|
15
15
|
# Add log 0
|
16
|
-
transaction_response_add_log_0 = contract.add_log(
|
16
|
+
transaction_response_add_log_0 = contract.add_log(
|
17
|
+
args=["I like to eat mango", 0]
|
18
|
+
).transact()
|
17
19
|
assert tx_execution_succeeded(transaction_response_add_log_0)
|
18
20
|
|
19
21
|
# Get closest vector to log 0
|
20
|
-
closest_vector_log_0 = contract.get_closest_vector(args=["I like mango"])
|
22
|
+
closest_vector_log_0 = contract.get_closest_vector(args=["I like mango"]).call()
|
21
23
|
closest_vector_log_0 = closest_vector_log_0
|
22
24
|
assert float(closest_vector_log_0["similarity"]) > 0.94
|
23
25
|
assert float(closest_vector_log_0["similarity"]) < 0.95
|
24
26
|
|
25
27
|
# Add log 1
|
26
|
-
transaction_response_add_log_1 = contract.add_log(
|
28
|
+
transaction_response_add_log_1 = contract.add_log(
|
29
|
+
args=["I like carrots", 1]
|
30
|
+
).transact()
|
27
31
|
assert tx_execution_succeeded(transaction_response_add_log_1)
|
28
32
|
|
29
33
|
# Get closest vector to log 1
|
30
|
-
closest_vector_log_1 = contract.get_closest_vector(args=["I like carrots"])
|
34
|
+
closest_vector_log_1 = contract.get_closest_vector(args=["I like carrots"]).call()
|
31
35
|
closest_vector_log_1 = closest_vector_log_1
|
32
36
|
assert float(closest_vector_log_1["similarity"]) == 1
|
33
37
|
|
34
38
|
# Update log 0
|
35
39
|
transaction_response_update_log_0 = contract.update_log(
|
36
40
|
args=[0, "I like to eat a lot of mangoes"]
|
37
|
-
)
|
41
|
+
).transact()
|
38
42
|
assert tx_execution_succeeded(transaction_response_update_log_0)
|
39
43
|
|
40
44
|
# Get closest vector to log 0
|
41
|
-
closest_vector_log_0_2 = contract.get_closest_vector(
|
45
|
+
closest_vector_log_0_2 = contract.get_closest_vector(
|
46
|
+
args=["I like mango a lot"]
|
47
|
+
).call()
|
42
48
|
closest_vector_log_0_2 = closest_vector_log_0_2
|
43
49
|
assert float(closest_vector_log_0_2["similarity"]) > 0.94
|
44
50
|
assert float(closest_vector_log_0_2["similarity"]) < 0.95
|
45
51
|
|
46
52
|
# Remove log 0
|
47
|
-
transaction_response_remove_log_0 = contract.remove_log(args=[0])
|
53
|
+
transaction_response_remove_log_0 = contract.remove_log(args=[0]).transact()
|
48
54
|
assert tx_execution_succeeded(transaction_response_remove_log_0)
|
49
55
|
|
50
56
|
# Get closest vector to log 0
|
51
|
-
closest_vector_log_0_3 = contract.get_closest_vector(
|
57
|
+
closest_vector_log_0_3 = contract.get_closest_vector(
|
58
|
+
args=["I like to eat mango"]
|
59
|
+
).call()
|
52
60
|
closest_vector_log_0_3 = closest_vector_log_0_3
|
53
61
|
assert float(closest_vector_log_0_3["similarity"]) > 0.67
|
54
62
|
assert float(closest_vector_log_0_3["similarity"]) < 0.68
|
55
63
|
|
56
64
|
# Add third log
|
57
|
-
transaction_response_add_log_2 = contract.add_log(
|
65
|
+
transaction_response_add_log_2 = contract.add_log(
|
66
|
+
args=["This is the third log", 3]
|
67
|
+
).transact()
|
58
68
|
assert tx_execution_succeeded(transaction_response_add_log_2)
|
59
69
|
|
60
70
|
# Check if new item got id 2
|
61
|
-
closest_vector_log_2 = contract.get_closest_vector(
|
71
|
+
closest_vector_log_2 = contract.get_closest_vector(
|
72
|
+
args=["This is the third log"]
|
73
|
+
).call()
|
62
74
|
assert float(closest_vector_log_2["similarity"]) > 0.99
|
63
75
|
assert closest_vector_log_2["id"] == 3
|
64
76
|
assert closest_vector_log_2["text"] == "This is the third log"
|
@@ -9,8 +9,8 @@ def test_multi_file_contract(setup_validators):
|
|
9
9
|
factory = get_contract_factory("MultiFileContract")
|
10
10
|
contract = factory.deploy(args=[])
|
11
11
|
|
12
|
-
wait_response = contract.wait(args=[])
|
12
|
+
wait_response = contract.wait(args=[]).transact()
|
13
13
|
assert tx_execution_succeeded(wait_response)
|
14
14
|
|
15
|
-
res = contract.test(args=[])
|
15
|
+
res = contract.test(args=[]).call()
|
16
16
|
assert res == "123"
|
@@ -9,8 +9,8 @@ def test_multi_file_contract_legacy(setup_validators):
|
|
9
9
|
factory = get_contract_factory("MultiFileContractLegacy")
|
10
10
|
contract = factory.deploy(args=[])
|
11
11
|
|
12
|
-
wait_response = contract.wait(args=[])
|
12
|
+
wait_response = contract.wait(args=[]).transact()
|
13
13
|
assert tx_execution_succeeded(wait_response)
|
14
14
|
|
15
|
-
res = contract.test(args=[])
|
15
|
+
res = contract.test(args=[]).call()
|
16
16
|
assert res == "123"
|