genlayer-test 0.4.1__py3-none-any.whl → 2.0.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.1.dist-info → genlayer_test-2.0.0.dist-info}/METADATA +75 -14
- genlayer_test-2.0.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 +197 -0
- gltest/{glchain/contract.py → contracts/contract_factory.py} +22 -137
- gltest/contracts/contract_functions.py +59 -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_cli/config/constants.py +1 -0
- gltest_cli/config/plugin.py +53 -0
- gltest_cli/config/pytest_context.py +9 -0
- gltest_cli/config/types.py +41 -0
- gltest_cli/config/user.py +21 -8
- 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 +6 -6
- 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 +167 -0
- tests/gltest_cli/config/test_user.py +61 -1
- genlayer_test-0.4.1.dist-info/RECORD +0 -67
- gltest/glchain/__init__.py +0 -16
- {genlayer_test-0.4.1.dist-info → genlayer_test-2.0.0.dist-info}/WHEEL +0 -0
- {genlayer_test-0.4.1.dist-info → genlayer_test-2.0.0.dist-info}/entry_points.txt +0 -0
- {genlayer_test-0.4.1.dist-info → genlayer_test-2.0.0.dist-info}/licenses/LICENSE +0 -0
- {genlayer_test-0.4.1.dist-info → genlayer_test-2.0.0.dist-info}/top_level.txt +0 -0
- /gltest/{glchain/account.py → accounts.py} +0 -0
gltest/fixtures.py
CHANGED
@@ -4,12 +4,8 @@ These fixtures can be imported and used in test files.
|
|
4
4
|
"""
|
5
5
|
|
6
6
|
import pytest
|
7
|
-
from gltest.
|
8
|
-
|
9
|
-
get_accounts,
|
10
|
-
get_default_account,
|
11
|
-
get_gl_provider,
|
12
|
-
)
|
7
|
+
from gltest.clients import get_gl_client, get_gl_provider
|
8
|
+
from gltest.accounts import get_accounts, get_default_account
|
13
9
|
from gltest_cli.config.general import get_general_config
|
14
10
|
|
15
11
|
|
gltest/helpers/take_snapshot.py
CHANGED
gltest_cli/config/constants.py
CHANGED
gltest_cli/config/plugin.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
from pathlib import Path
|
2
|
+
import shutil
|
2
3
|
from gltest_cli.logging import logger
|
3
4
|
from gltest_cli.config.user import (
|
4
5
|
user_config_exists,
|
@@ -9,6 +10,7 @@ from gltest_cli.config.general import (
|
|
9
10
|
get_general_config,
|
10
11
|
)
|
11
12
|
from gltest_cli.config.types import PluginConfig
|
13
|
+
from gltest_cli.config.pytest_context import _pytest_context
|
12
14
|
|
13
15
|
|
14
16
|
def pytest_addoption(parser):
|
@@ -20,6 +22,13 @@ def pytest_addoption(parser):
|
|
20
22
|
help="Path to directory containing contract files",
|
21
23
|
)
|
22
24
|
|
25
|
+
group.addoption(
|
26
|
+
"--artifacts-dir",
|
27
|
+
action="store",
|
28
|
+
default=None,
|
29
|
+
help="Path to directory for storing contract artifacts",
|
30
|
+
)
|
31
|
+
|
23
32
|
group.addoption(
|
24
33
|
"--default-wait-interval",
|
25
34
|
action="store",
|
@@ -55,6 +64,13 @@ def pytest_addoption(parser):
|
|
55
64
|
help="Test with mocks",
|
56
65
|
)
|
57
66
|
|
67
|
+
group.addoption(
|
68
|
+
"--leader-only",
|
69
|
+
action="store_true",
|
70
|
+
default=False,
|
71
|
+
help="Run contracts in leader-only mode",
|
72
|
+
)
|
73
|
+
|
58
74
|
|
59
75
|
def pytest_configure(config):
|
60
76
|
general_config = get_general_config()
|
@@ -76,27 +92,45 @@ def pytest_configure(config):
|
|
76
92
|
|
77
93
|
# Handle plugin config from command line
|
78
94
|
contracts_dir = config.getoption("--contracts-dir")
|
95
|
+
artifacts_dir = config.getoption("--artifacts-dir")
|
79
96
|
default_wait_interval = config.getoption("--default-wait-interval")
|
80
97
|
default_wait_retries = config.getoption("--default-wait-retries")
|
81
98
|
rpc_url = config.getoption("--rpc-url")
|
82
99
|
network = config.getoption("--network")
|
83
100
|
test_with_mocks = config.getoption("--test-with-mocks")
|
101
|
+
leader_only = config.getoption("--leader-only")
|
84
102
|
|
85
103
|
plugin_config = PluginConfig()
|
86
104
|
plugin_config.contracts_dir = (
|
87
105
|
Path(contracts_dir) if contracts_dir is not None else None
|
88
106
|
)
|
107
|
+
plugin_config.artifacts_dir = (
|
108
|
+
Path(artifacts_dir) if artifacts_dir is not None else None
|
109
|
+
)
|
89
110
|
plugin_config.default_wait_interval = int(default_wait_interval)
|
90
111
|
plugin_config.default_wait_retries = int(default_wait_retries)
|
91
112
|
plugin_config.rpc_url = rpc_url
|
92
113
|
plugin_config.network_name = network
|
93
114
|
plugin_config.test_with_mocks = test_with_mocks
|
115
|
+
plugin_config.leader_only = leader_only
|
94
116
|
|
95
117
|
general_config.plugin_config = plugin_config
|
96
118
|
|
97
119
|
|
98
120
|
def pytest_sessionstart(session):
|
99
121
|
general_config = get_general_config()
|
122
|
+
|
123
|
+
artifacts_dir = general_config.get_artifacts_dir()
|
124
|
+
if artifacts_dir and artifacts_dir.exists():
|
125
|
+
logger.info(f"Clearing artifacts directory: {artifacts_dir}")
|
126
|
+
try:
|
127
|
+
shutil.rmtree(artifacts_dir)
|
128
|
+
artifacts_dir.mkdir(parents=True, exist_ok=True)
|
129
|
+
except Exception as e:
|
130
|
+
logger.warning(f"Failed to clear artifacts directory: {e}")
|
131
|
+
elif artifacts_dir:
|
132
|
+
artifacts_dir.mkdir(parents=True, exist_ok=True)
|
133
|
+
|
100
134
|
logger.info("Using the following configuration:")
|
101
135
|
logger.info(f" RPC URL: {general_config.get_rpc_url()}")
|
102
136
|
logger.info(f" Selected Network: {general_config.get_network_name()}")
|
@@ -104,6 +138,7 @@ def pytest_sessionstart(session):
|
|
104
138
|
f" Available networks: {list(general_config.user_config.networks.keys())}"
|
105
139
|
)
|
106
140
|
logger.info(f" Contracts directory: {general_config.get_contracts_dir()}")
|
141
|
+
logger.info(f" Artifacts directory: {general_config.get_artifacts_dir()}")
|
107
142
|
logger.info(f" Environment: {general_config.user_config.environment}")
|
108
143
|
logger.info(
|
109
144
|
f" Default wait interval: {general_config.get_default_wait_interval()} ms"
|
@@ -111,5 +146,23 @@ def pytest_sessionstart(session):
|
|
111
146
|
logger.info(f" Default wait retries: {general_config.get_default_wait_retries()}")
|
112
147
|
logger.info(f" Test with mocks: {general_config.get_test_with_mocks()}")
|
113
148
|
|
149
|
+
if general_config.get_leader_only() and not general_config.check_studio_based_rpc():
|
150
|
+
logger.warning(
|
151
|
+
"Leader only mode: True (enabled on non-studio network - will have no effect)"
|
152
|
+
)
|
153
|
+
else:
|
154
|
+
logger.info(f" Leader only mode: {general_config.get_leader_only()}")
|
155
|
+
|
156
|
+
|
157
|
+
def pytest_runtest_setup(item):
|
158
|
+
_pytest_context.current_item = item
|
159
|
+
|
160
|
+
|
161
|
+
def pytest_runtest_teardown(item):
|
162
|
+
try:
|
163
|
+
del _pytest_context.current_item
|
164
|
+
except AttributeError:
|
165
|
+
pass
|
166
|
+
|
114
167
|
|
115
168
|
pytest_plugins = ["gltest.fixtures"]
|
gltest_cli/config/types.py
CHANGED
@@ -15,11 +15,13 @@ class NetworkConfig(str, Enum):
|
|
15
15
|
@dataclass
|
16
16
|
class PluginConfig:
|
17
17
|
contracts_dir: Optional[Path] = None
|
18
|
+
artifacts_dir: Optional[Path] = None
|
18
19
|
rpc_url: Optional[str] = None
|
19
20
|
default_wait_interval: Optional[int] = None
|
20
21
|
default_wait_retries: Optional[int] = None
|
21
22
|
network_name: Optional[str] = None
|
22
23
|
test_with_mocks: bool = False
|
24
|
+
leader_only: bool = False
|
23
25
|
|
24
26
|
|
25
27
|
@dataclass
|
@@ -28,6 +30,7 @@ class NetworkConfigData:
|
|
28
30
|
url: Optional[str] = None
|
29
31
|
accounts: Optional[List[str]] = None
|
30
32
|
from_account: Optional[str] = None
|
33
|
+
leader_only: bool = False
|
31
34
|
|
32
35
|
def __post_init__(self):
|
33
36
|
if self.id is not None and not isinstance(self.id, int):
|
@@ -46,10 +49,13 @@ class NetworkConfigData:
|
|
46
49
|
@dataclass
|
47
50
|
class PathConfig:
|
48
51
|
contracts: Optional[Path] = None
|
52
|
+
artifacts: Optional[Path] = None
|
49
53
|
|
50
54
|
def __post_init__(self):
|
51
55
|
if self.contracts is not None and not isinstance(self.contracts, (str, Path)):
|
52
56
|
raise ValueError("contracts must be a string or Path")
|
57
|
+
if self.artifacts is not None and not isinstance(self.artifacts, (str, Path)):
|
58
|
+
raise ValueError("artifacts must be a string or Path")
|
53
59
|
|
54
60
|
|
55
61
|
@dataclass
|
@@ -93,6 +99,18 @@ class GeneralConfig:
|
|
93
99
|
def set_contracts_dir(self, contracts_dir: Path):
|
94
100
|
self.plugin_config.contracts_dir = contracts_dir
|
95
101
|
|
102
|
+
def get_artifacts_dir(self) -> Path:
|
103
|
+
if self.plugin_config.artifacts_dir is not None:
|
104
|
+
return self.plugin_config.artifacts_dir
|
105
|
+
return self.user_config.paths.artifacts
|
106
|
+
|
107
|
+
def set_artifacts_dir(self, artifacts_dir: Path):
|
108
|
+
self.plugin_config.artifacts_dir = artifacts_dir
|
109
|
+
|
110
|
+
def get_analysis_dir(self) -> Path:
|
111
|
+
artifacts_dir = self.get_artifacts_dir()
|
112
|
+
return artifacts_dir / "analysis"
|
113
|
+
|
96
114
|
def get_rpc_url(self) -> str:
|
97
115
|
if self.plugin_config.rpc_url is not None:
|
98
116
|
return self.plugin_config.rpc_url
|
@@ -141,8 +159,31 @@ class GeneralConfig:
|
|
141
159
|
def get_test_with_mocks(self) -> bool:
|
142
160
|
return self.plugin_config.test_with_mocks
|
143
161
|
|
162
|
+
def get_leader_only(self) -> bool:
|
163
|
+
if self.plugin_config.leader_only:
|
164
|
+
return True
|
165
|
+
network_name = self.get_network_name()
|
166
|
+
if network_name in self.user_config.networks:
|
167
|
+
network_config = self.user_config.networks[network_name]
|
168
|
+
return network_config.leader_only
|
169
|
+
return False
|
170
|
+
|
144
171
|
def check_local_rpc(self) -> bool:
|
145
172
|
SUPPORTED_RPC_DOMAINS = ["localhost", "127.0.0.1"]
|
146
173
|
rpc_url = self.get_rpc_url()
|
147
174
|
domain = urlparse(rpc_url).netloc.split(":")[0] # Extract domain without port
|
148
175
|
return domain in SUPPORTED_RPC_DOMAINS
|
176
|
+
|
177
|
+
def check_studio_based_rpc(self) -> bool:
|
178
|
+
SUPPORTED_RPC_DOMAINS = ["localhost", "127.0.0.1"]
|
179
|
+
rpc_url = self.get_rpc_url()
|
180
|
+
domain = urlparse(rpc_url).netloc.split(":")[0] # Extract domain without port
|
181
|
+
|
182
|
+
if domain in SUPPORTED_RPC_DOMAINS:
|
183
|
+
return True
|
184
|
+
|
185
|
+
# Check .genlayer.com or .genlayerlabs.com subdomains
|
186
|
+
if domain.endswith(".genlayer.com") or domain.endswith(".genlayerlabs.com"):
|
187
|
+
return True
|
188
|
+
|
189
|
+
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
11
|
DEFAULT_RPC_URL,
|
12
12
|
DEFAULT_ENVIRONMENT,
|
13
13
|
DEFAULT_CONTRACTS_DIR,
|
14
|
+
DEFAULT_ARTIFACTS_DIR,
|
14
15
|
DEFAULT_NETWORK_ID,
|
15
16
|
)
|
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)
|
@@ -32,9 +33,12 @@ def get_default_user_config() -> UserConfig:
|
|
32
33
|
url=DEFAULT_RPC_URL,
|
33
34
|
accounts=accounts_private_keys,
|
34
35
|
from_account=accounts_private_keys[0],
|
36
|
+
leader_only=False,
|
35
37
|
),
|
36
38
|
},
|
37
|
-
paths=PathConfig(
|
39
|
+
paths=PathConfig(
|
40
|
+
contracts=DEFAULT_CONTRACTS_DIR, artifacts=DEFAULT_ARTIFACTS_DIR
|
41
|
+
),
|
38
42
|
environment=DEFAULT_ENVIRONMENT,
|
39
43
|
default_network=DEFAULT_NETWORK,
|
40
44
|
)
|
@@ -81,6 +85,10 @@ def validate_network_config(network_name: str, network_config: dict):
|
|
81
85
|
|
82
86
|
if "from" in network_config and not isinstance(network_config["from"], str):
|
83
87
|
raise ValueError(f"network {network_name} from must be a string")
|
88
|
+
if "leader_only" in network_config and not isinstance(
|
89
|
+
network_config["leader_only"], bool
|
90
|
+
):
|
91
|
+
raise ValueError(f"network {network_name} leader_only must be a boolean")
|
84
92
|
|
85
93
|
# For non-default networks, url and accounts are required
|
86
94
|
if network_name != DEFAULT_NETWORK:
|
@@ -182,18 +190,23 @@ def _get_overridden_networks(raw_config: dict) -> tuple[dict, str]:
|
|
182
190
|
]
|
183
191
|
if "from" in network_config:
|
184
192
|
networks_config[network_name].from_account = network_config["from"]
|
193
|
+
if "leader_only" in network_config:
|
194
|
+
networks_config[network_name].leader_only = network_config[
|
195
|
+
"leader_only"
|
196
|
+
]
|
185
197
|
continue
|
186
198
|
|
187
199
|
url = network_config["url"]
|
188
200
|
accounts = network_config["accounts"]
|
189
201
|
from_account = network_config.get("from", accounts[0])
|
190
202
|
network_id = network_config.get("id")
|
191
|
-
|
203
|
+
leader_only = network_config.get("leader_only", False)
|
192
204
|
networks_config[network_name] = NetworkConfigData(
|
193
205
|
id=network_id,
|
194
206
|
url=url,
|
195
207
|
accounts=accounts,
|
196
208
|
from_account=from_account,
|
209
|
+
leader_only=leader_only,
|
197
210
|
)
|
198
211
|
return networks_config, user_default_network
|
199
212
|
|
@@ -208,10 +221,10 @@ def _get_overridden_environment(raw_config: dict) -> str:
|
|
208
221
|
def _get_overridden_paths(raw_config: dict) -> PathConfig:
|
209
222
|
default_config = get_default_user_config()
|
210
223
|
if "paths" in raw_config:
|
224
|
+
paths_config = raw_config.get("paths", {})
|
211
225
|
return PathConfig(
|
212
|
-
contracts=Path(
|
213
|
-
|
214
|
-
)
|
226
|
+
contracts=Path(paths_config.get("contracts", DEFAULT_CONTRACTS_DIR)),
|
227
|
+
artifacts=Path(paths_config.get("artifacts", DEFAULT_ARTIFACTS_DIR)),
|
215
228
|
)
|
216
229
|
return default_config.paths
|
217
230
|
|
@@ -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"
|
@@ -12,7 +12,7 @@ def wait_for_contract_deployment(intelligent_oracle_contract, max_retries=10, de
|
|
12
12
|
"""
|
13
13
|
for _ in range(max_retries):
|
14
14
|
try:
|
15
|
-
intelligent_oracle_contract.get_dict(args=[])
|
15
|
+
intelligent_oracle_contract.get_dict(args=[]).call()
|
16
16
|
return True # If successful, contract is deployed
|
17
17
|
except Exception:
|
18
18
|
time.sleep(delay)
|
@@ -124,11 +124,11 @@ def test_intelligent_oracle_factory_pattern(setup_validators):
|
|
124
124
|
market_data["resolution_urls"],
|
125
125
|
market_data["earliest_resolution_date"],
|
126
126
|
],
|
127
|
-
)
|
127
|
+
).transact()
|
128
128
|
assert tx_execution_succeeded(create_result)
|
129
129
|
|
130
130
|
# Get the latest contract address from factory
|
131
|
-
registered_addresses = registry_contract.get_contract_addresses(args=[])
|
131
|
+
registered_addresses = registry_contract.get_contract_addresses(args=[]).call()
|
132
132
|
new_market_address = registered_addresses[-1]
|
133
133
|
|
134
134
|
# Build a contract object
|
@@ -145,7 +145,7 @@ def test_intelligent_oracle_factory_pattern(setup_validators):
|
|
145
145
|
|
146
146
|
# Verify each market's state
|
147
147
|
for i, market_contract in enumerate(created_market_contracts):
|
148
|
-
market_state = market_contract.get_dict(args=[])
|
148
|
+
market_state = market_contract.get_dict(args=[]).call()
|
149
149
|
expected_data = markets_data[i]
|
150
150
|
|
151
151
|
# Verify key market properties
|
@@ -171,10 +171,10 @@ def test_intelligent_oracle_factory_pattern(setup_validators):
|
|
171
171
|
for i, market_contract in enumerate(created_market_contracts):
|
172
172
|
resolve_result = market_contract.resolve(
|
173
173
|
args=[markets_data[i]["evidence_urls"]],
|
174
|
-
)
|
174
|
+
).transact()
|
175
175
|
assert tx_execution_succeeded(resolve_result)
|
176
176
|
|
177
177
|
# Verify market was resolved and has the correct outcome
|
178
|
-
market_state = market_contract.get_dict(args=[])
|
178
|
+
market_state = market_contract.get_dict(args=[]).call()
|
179
179
|
assert market_state["status"] == "Resolved"
|
180
180
|
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"
|
@@ -61,11 +61,11 @@ def test_multi_read_erc20(setup_validators):
|
|
61
61
|
from_account_doge.address,
|
62
62
|
[doge_contract.address, shiba_contract.address],
|
63
63
|
]
|
64
|
-
)
|
64
|
+
).transact()
|
65
65
|
assert tx_execution_succeeded(transaction_response_call)
|
66
66
|
|
67
67
|
# check balances
|
68
|
-
call_method_response_get_balances = multi_read_contract.get_balances(args=[])
|
68
|
+
call_method_response_get_balances = multi_read_contract.get_balances(args=[]).call()
|
69
69
|
assert call_method_response_get_balances == {
|
70
70
|
from_account_doge.address: {
|
71
71
|
doge_contract.address: TOKEN_TOTAL_SUPPLY,
|
@@ -74,20 +74,22 @@ def test_multi_read_erc20(setup_validators):
|
|
74
74
|
}
|
75
75
|
|
76
76
|
# update balances for shiba account
|
77
|
-
transaction_response_call =
|
78
|
-
from_account_shiba
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
77
|
+
transaction_response_call = (
|
78
|
+
multi_read_contract.connect(from_account_shiba)
|
79
|
+
.update_token_balances(
|
80
|
+
args=[
|
81
|
+
from_account_shiba.address,
|
82
|
+
[doge_contract.address, shiba_contract.address],
|
83
|
+
]
|
84
|
+
)
|
85
|
+
.transact()
|
84
86
|
)
|
85
87
|
assert tx_execution_succeeded(transaction_response_call)
|
86
88
|
|
87
89
|
# check balances
|
88
|
-
call_method_response_get_balances =
|
89
|
-
from_account_shiba
|
90
|
-
)
|
90
|
+
call_method_response_get_balances = (
|
91
|
+
multi_read_contract.connect(from_account_shiba).get_balances(args=[]).call()
|
92
|
+
)
|
91
93
|
|
92
94
|
assert call_method_response_get_balances == {
|
93
95
|
from_account_doge.address: {
|