iwa 0.0.19__py3-none-any.whl → 0.0.20__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.
- iwa/core/chainlist.py +116 -0
- iwa/core/constants.py +1 -0
- iwa/core/contracts/cache.py +131 -0
- iwa/core/contracts/contract.py +7 -0
- iwa/core/rpc_monitor.py +60 -0
- iwa/plugins/olas/contracts/activity_checker.py +63 -25
- iwa/plugins/olas/contracts/staking.py +115 -19
- iwa/plugins/olas/events.py +141 -0
- iwa/plugins/olas/service_manager/base.py +7 -2
- iwa/plugins/olas/service_manager/lifecycle.py +30 -5
- iwa/plugins/olas/service_manager/mech.py +9 -0
- iwa/plugins/olas/service_manager/staking.py +6 -2
- iwa/plugins/olas/tests/test_olas_integration.py +38 -10
- iwa/plugins/olas/tests/test_service_manager.py +7 -1
- iwa/plugins/olas/tests/test_service_manager_errors.py +22 -11
- iwa/plugins/olas/tests/test_service_manager_flows.py +24 -8
- iwa/plugins/olas/tests/test_service_staking.py +59 -15
- iwa/plugins/olas/tests/test_staking_validation.py +8 -14
- iwa/tools/test_chainlist.py +38 -0
- iwa/web/routers/olas/staking.py +9 -4
- {iwa-0.0.19.dist-info → iwa-0.0.20.dist-info}/METADATA +1 -1
- {iwa-0.0.19.dist-info → iwa-0.0.20.dist-info}/RECORD +27 -21
- tests/test_rpc_efficiency.py +103 -0
- {iwa-0.0.19.dist-info → iwa-0.0.20.dist-info}/WHEEL +0 -0
- {iwa-0.0.19.dist-info → iwa-0.0.20.dist-info}/entry_points.txt +0 -0
- {iwa-0.0.19.dist-info → iwa-0.0.20.dist-info}/licenses/LICENSE +0 -0
- {iwa-0.0.19.dist-info → iwa-0.0.20.dist-info}/top_level.txt +0 -0
|
@@ -33,7 +33,10 @@ def mock_wallet():
|
|
|
33
33
|
|
|
34
34
|
def test_sm_unstake_not_staked(mock_wallet):
|
|
35
35
|
"""Cover unstake when not staked (lines 736-738)."""
|
|
36
|
-
with patch("iwa.core.models.Config")
|
|
36
|
+
with patch("iwa.core.models.Config"), \
|
|
37
|
+
patch("iwa.plugins.olas.service_manager.base.ContractCache") as mock_cache, \
|
|
38
|
+
patch("iwa.plugins.olas.service_manager.staking.ContractCache", mock_cache):
|
|
39
|
+
mock_cache.return_value.get_contract.side_effect = lambda cls, *a, **k: cls(*a, **k)
|
|
37
40
|
sm = ServiceManager(mock_wallet)
|
|
38
41
|
sm.service = Service(
|
|
39
42
|
service_name="t", chain_name="gnosis", service_id=1, multisig_address=VALID_ADDR
|
|
@@ -48,7 +51,10 @@ def test_sm_unstake_not_staked(mock_wallet):
|
|
|
48
51
|
|
|
49
52
|
def test_sm_unstake_tx_fails(mock_wallet):
|
|
50
53
|
"""Cover unstake transaction failure (lines 766-768)."""
|
|
51
|
-
with patch("iwa.core.models.Config")
|
|
54
|
+
with patch("iwa.core.models.Config"), \
|
|
55
|
+
patch("iwa.plugins.olas.service_manager.base.ContractCache") as mock_cache, \
|
|
56
|
+
patch("iwa.plugins.olas.service_manager.staking.ContractCache", mock_cache):
|
|
57
|
+
mock_cache.return_value.get_contract.side_effect = lambda cls, *a, **k: cls(*a, **k)
|
|
52
58
|
sm = ServiceManager(mock_wallet)
|
|
53
59
|
sm.service = Service(
|
|
54
60
|
service_name="t", chain_name="gnosis", service_id=1, multisig_address=VALID_ADDR
|
|
@@ -71,7 +77,10 @@ def test_sm_unstake_tx_fails(mock_wallet):
|
|
|
71
77
|
|
|
72
78
|
def test_sm_get_staking_status_no_staking_address(mock_wallet):
|
|
73
79
|
"""Cover get_staking_status with no staking address (lines 831)."""
|
|
74
|
-
with patch("iwa.core.models.Config")
|
|
80
|
+
with patch("iwa.core.models.Config"), \
|
|
81
|
+
patch("iwa.plugins.olas.service_manager.base.ContractCache") as mock_cache, \
|
|
82
|
+
patch("iwa.plugins.olas.service_manager.staking.ContractCache", mock_cache):
|
|
83
|
+
mock_cache.return_value.get_contract.side_effect = lambda cls, *a, **k: cls(*a, **k)
|
|
75
84
|
sm = ServiceManager(mock_wallet)
|
|
76
85
|
sm.service = Service(
|
|
77
86
|
service_name="t", chain_name="gnosis", service_id=1, staking_contract_address=VALID_ADDR
|
|
@@ -88,7 +97,10 @@ def test_sm_get_staking_status_no_staking_address(mock_wallet):
|
|
|
88
97
|
|
|
89
98
|
def test_sm_get_staking_status_with_full_info(mock_wallet):
|
|
90
99
|
"""Cover get_staking_status with complete info (lines 866-891)."""
|
|
91
|
-
with patch("iwa.core.models.Config")
|
|
100
|
+
with patch("iwa.core.models.Config"), \
|
|
101
|
+
patch("iwa.plugins.olas.service_manager.base.ContractCache") as mock_cache, \
|
|
102
|
+
patch("iwa.plugins.olas.service_manager.staking.ContractCache", mock_cache):
|
|
103
|
+
mock_cache.return_value.get_contract.side_effect = lambda cls, *a, **k: cls(*a, **k)
|
|
92
104
|
sm = ServiceManager(mock_wallet)
|
|
93
105
|
sm.service = Service(
|
|
94
106
|
service_name="t", chain_name="gnosis", service_id=1, staking_contract_address=VALID_ADDR
|
|
@@ -130,7 +142,10 @@ def test_sm_get_staking_status_with_full_info(mock_wallet):
|
|
|
130
142
|
|
|
131
143
|
def test_sm_claim_rewards_no_service(mock_wallet):
|
|
132
144
|
"""Cover claim_rewards with no service (lines 936-938)."""
|
|
133
|
-
with patch("iwa.core.models.Config")
|
|
145
|
+
with patch("iwa.core.models.Config"), \
|
|
146
|
+
patch("iwa.plugins.olas.service_manager.base.ContractCache") as mock_cache, \
|
|
147
|
+
patch("iwa.plugins.olas.service_manager.staking.ContractCache", mock_cache):
|
|
148
|
+
mock_cache.return_value.get_contract.side_effect = lambda cls, *a, **k: cls(*a, **k)
|
|
134
149
|
sm = ServiceManager(mock_wallet)
|
|
135
150
|
sm.service = None
|
|
136
151
|
|
|
@@ -141,7 +156,10 @@ def test_sm_claim_rewards_no_service(mock_wallet):
|
|
|
141
156
|
|
|
142
157
|
def test_sm_claim_rewards_no_staking_address(mock_wallet):
|
|
143
158
|
"""Cover claim_rewards with no staking address (lines 939-943)."""
|
|
144
|
-
with patch("iwa.core.models.Config")
|
|
159
|
+
with patch("iwa.core.models.Config"), \
|
|
160
|
+
patch("iwa.plugins.olas.service_manager.base.ContractCache") as mock_cache, \
|
|
161
|
+
patch("iwa.plugins.olas.service_manager.staking.ContractCache", mock_cache):
|
|
162
|
+
mock_cache.return_value.get_contract.side_effect = lambda cls, *a, **k: cls(*a, **k)
|
|
145
163
|
sm = ServiceManager(mock_wallet)
|
|
146
164
|
sm.service = Service(
|
|
147
165
|
service_name="t", chain_name="gnosis", service_id=1, staking_contract_address=None
|
|
@@ -153,7 +171,10 @@ def test_sm_claim_rewards_no_staking_address(mock_wallet):
|
|
|
153
171
|
|
|
154
172
|
def test_sm_claim_rewards_tx_fails(mock_wallet):
|
|
155
173
|
"""Cover claim_rewards transaction failure (lines 967-968)."""
|
|
156
|
-
with patch("iwa.core.models.Config")
|
|
174
|
+
with patch("iwa.core.models.Config"), \
|
|
175
|
+
patch("iwa.plugins.olas.service_manager.base.ContractCache") as mock_cache, \
|
|
176
|
+
patch("iwa.plugins.olas.service_manager.staking.ContractCache", mock_cache):
|
|
177
|
+
mock_cache.return_value.get_contract.side_effect = lambda cls, *a, **k: cls(*a, **k)
|
|
157
178
|
sm = ServiceManager(mock_wallet)
|
|
158
179
|
sm.service = Service(
|
|
159
180
|
service_name="t",
|
|
@@ -165,12 +186,22 @@ def test_sm_claim_rewards_tx_fails(mock_wallet):
|
|
|
165
186
|
|
|
166
187
|
mock_staking = MagicMock()
|
|
167
188
|
mock_staking.prepare_claim_tx.return_value = {"to": VALID_ADDR}
|
|
189
|
+
mock_staking.get_staking_state.return_value = StakingState.STAKED
|
|
190
|
+
mock_staking.get_accrued_rewards.return_value = 100
|
|
191
|
+
|
|
192
|
+
def get_contract_side_effect(cls, *args, **kwargs):
|
|
193
|
+
print(f"DEBUG: get_contract called with {cls!r}")
|
|
194
|
+
if "StakingContract" in str(cls):
|
|
195
|
+
return mock_staking
|
|
196
|
+
return cls(*args, **kwargs)
|
|
197
|
+
|
|
198
|
+
mock_cache.return_value.get_contract.side_effect = get_contract_side_effect
|
|
168
199
|
|
|
169
200
|
mock_wallet.sign_and_send_transaction.return_value = (False, None)
|
|
170
201
|
|
|
171
|
-
with patch("iwa.plugins.olas.service_manager.StakingContract", return_value=mock_staking):
|
|
172
|
-
|
|
173
|
-
|
|
202
|
+
with patch("iwa.plugins.olas.service_manager.drain.StakingContract", return_value=mock_staking):
|
|
203
|
+
success, amount = sm.claim_rewards()
|
|
204
|
+
assert success is False
|
|
174
205
|
|
|
175
206
|
|
|
176
207
|
# === SERVICE MANAGER SPIN_UP STATE TRANSITIONS (lines 1188-1241) ===
|
|
@@ -178,7 +209,10 @@ def test_sm_claim_rewards_tx_fails(mock_wallet):
|
|
|
178
209
|
|
|
179
210
|
def test_sm_spin_up_state_mismatch_after_activation(mock_wallet):
|
|
180
211
|
"""Cover spin_up state mismatch after activation (lines 1188-1191)."""
|
|
181
|
-
with patch("iwa.core.models.Config")
|
|
212
|
+
with patch("iwa.core.models.Config"), \
|
|
213
|
+
patch("iwa.plugins.olas.service_manager.base.ContractCache") as mock_cache, \
|
|
214
|
+
patch("iwa.plugins.olas.service_manager.staking.ContractCache", mock_cache):
|
|
215
|
+
mock_cache.return_value.get_contract.side_effect = lambda cls, *a, **k: cls(*a, **k)
|
|
182
216
|
sm = ServiceManager(mock_wallet)
|
|
183
217
|
sm.service = Service(service_name="t", chain_name="gnosis", service_id=1)
|
|
184
218
|
|
|
@@ -199,7 +233,10 @@ def test_sm_spin_up_state_mismatch_after_activation(mock_wallet):
|
|
|
199
233
|
|
|
200
234
|
def test_sm_spin_up_registration_fails(mock_wallet):
|
|
201
235
|
"""Cover spin_up registration failure (lines 1199-1201)."""
|
|
202
|
-
with patch("iwa.core.models.Config")
|
|
236
|
+
with patch("iwa.core.models.Config"), \
|
|
237
|
+
patch("iwa.plugins.olas.service_manager.base.ContractCache") as mock_cache, \
|
|
238
|
+
patch("iwa.plugins.olas.service_manager.staking.ContractCache", mock_cache):
|
|
239
|
+
mock_cache.return_value.get_contract.side_effect = lambda cls, *a, **k: cls(*a, **k)
|
|
203
240
|
sm = ServiceManager(mock_wallet)
|
|
204
241
|
sm.service = Service(service_name="t", chain_name="gnosis", service_id=1)
|
|
205
242
|
|
|
@@ -216,7 +253,10 @@ def test_sm_spin_up_registration_fails(mock_wallet):
|
|
|
216
253
|
|
|
217
254
|
def test_sm_spin_up_deploy_fails(mock_wallet):
|
|
218
255
|
"""Cover spin_up deploy failure (lines 1216-1218)."""
|
|
219
|
-
with patch("iwa.core.models.Config")
|
|
256
|
+
with patch("iwa.core.models.Config"), \
|
|
257
|
+
patch("iwa.plugins.olas.service_manager.base.ContractCache") as mock_cache, \
|
|
258
|
+
patch("iwa.plugins.olas.service_manager.staking.ContractCache", mock_cache):
|
|
259
|
+
mock_cache.return_value.get_contract.side_effect = lambda cls, *a, **k: cls(*a, **k)
|
|
220
260
|
sm = ServiceManager(mock_wallet)
|
|
221
261
|
sm.service = Service(service_name="t", chain_name="gnosis", service_id=1)
|
|
222
262
|
|
|
@@ -233,7 +273,10 @@ def test_sm_spin_up_deploy_fails(mock_wallet):
|
|
|
233
273
|
|
|
234
274
|
def test_sm_wind_down_terminate_fails(mock_wallet):
|
|
235
275
|
"""Cover wind_down terminate failure (lines 1299-1301)."""
|
|
236
|
-
with patch("iwa.core.models.Config")
|
|
276
|
+
with patch("iwa.core.models.Config"), \
|
|
277
|
+
patch("iwa.plugins.olas.service_manager.base.ContractCache") as mock_cache, \
|
|
278
|
+
patch("iwa.plugins.olas.service_manager.staking.ContractCache", mock_cache):
|
|
279
|
+
mock_cache.return_value.get_contract.side_effect = lambda cls, *a, **k: cls(*a, **k)
|
|
237
280
|
sm = ServiceManager(mock_wallet)
|
|
238
281
|
sm.service = Service(service_name="t", chain_name="gnosis", service_id=1)
|
|
239
282
|
|
|
@@ -250,7 +293,8 @@ def test_sm_wind_down_terminate_fails(mock_wallet):
|
|
|
250
293
|
|
|
251
294
|
def test_sm_wind_down_unbond_fails(mock_wallet):
|
|
252
295
|
"""Cover wind_down unbond failure (lines 1315-1317)."""
|
|
253
|
-
with patch("iwa.core.models.Config")
|
|
296
|
+
with patch("iwa.core.models.Config"), \
|
|
297
|
+
patch("iwa.plugins.olas.service_manager.base.ContractCache"):
|
|
254
298
|
sm = ServiceManager(mock_wallet)
|
|
255
299
|
sm.service = Service(service_name="t", chain_name="gnosis", service_id=1)
|
|
256
300
|
|
|
@@ -25,19 +25,12 @@ def mock_staking():
|
|
|
25
25
|
def test_staking_get_service_info_nested_tuple(mock_staking):
|
|
26
26
|
"""Test get_service_info with nested tuple result from web3."""
|
|
27
27
|
nested_result = (("0xMultisig", "0xOwner", (1, 2), 1000, 500, 0),)
|
|
28
|
-
mock_staking.call.side_effect =
|
|
29
|
-
"0x1"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
10, # maxNumServices
|
|
35
|
-
50, # minStakingDeposit
|
|
36
|
-
7200, # minStakingDuration
|
|
37
|
-
"0xToken", # stakingToken
|
|
38
|
-
nested_result, # getServiceInfo
|
|
39
|
-
2000, # getNextRewardCheckpointTimestamp
|
|
40
|
-
]
|
|
28
|
+
mock_staking.call.side_effect = (
|
|
29
|
+
["0x1"] # activityChecker
|
|
30
|
+
+ [nested_result] # getServiceInfo
|
|
31
|
+
+ [2000] * 5 # getNextRewardCheckpointTimestamp and any others
|
|
32
|
+
)
|
|
33
|
+
|
|
41
34
|
# Re-init to trigger calls
|
|
42
35
|
with (
|
|
43
36
|
patch("iwa.plugins.olas.contracts.staking.ActivityCheckerContract"),
|
|
@@ -45,7 +38,8 @@ def test_staking_get_service_info_nested_tuple(mock_staking):
|
|
|
45
38
|
):
|
|
46
39
|
mock_ci.get_instance.return_value.web3.eth.contract.return_value = MagicMock()
|
|
47
40
|
staking = StakingContract("0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB", "gnosis")
|
|
48
|
-
|
|
41
|
+
# Update call on the new instance
|
|
42
|
+
staking.call = MagicMock(side_effect=mock_staking.call.side_effect)
|
|
49
43
|
staking.activity_checker.get_multisig_nonces.return_value = (1, 3)
|
|
50
44
|
staking.get_required_requests = MagicMock(return_value=5)
|
|
51
45
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Script to verify ChainlistRPC functionality."""
|
|
2
|
+
from iwa.core.chainlist import ChainlistRPC
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def main() -> None:
|
|
6
|
+
"""Run the verification script."""
|
|
7
|
+
print("Initializing ChainlistRPC...")
|
|
8
|
+
chainlist = ChainlistRPC()
|
|
9
|
+
|
|
10
|
+
print("Fetching data...")
|
|
11
|
+
chainlist.fetch_data()
|
|
12
|
+
|
|
13
|
+
gnosis_chain_id = 100
|
|
14
|
+
print(f"\n--- Gnosis Chain (ID: {gnosis_chain_id}) ---")
|
|
15
|
+
|
|
16
|
+
all_rpcs = chainlist.get_rpcs(gnosis_chain_id)
|
|
17
|
+
print(f"Total RPCs found: {len(all_rpcs)}")
|
|
18
|
+
|
|
19
|
+
https_rpcs = chainlist.get_https_rpcs(gnosis_chain_id)
|
|
20
|
+
print(f"HTTPS RPCs ({len(https_rpcs)}):")
|
|
21
|
+
for url in https_rpcs[:5]:
|
|
22
|
+
print(f" - {url}")
|
|
23
|
+
if len(https_rpcs) > 5:
|
|
24
|
+
print(" ... and more")
|
|
25
|
+
|
|
26
|
+
wss_rpcs = chainlist.get_wss_rpcs(gnosis_chain_id)
|
|
27
|
+
print(f"WSS RPCs ({len(wss_rpcs)}):")
|
|
28
|
+
for url in wss_rpcs[:5]:
|
|
29
|
+
print(f" - {url}")
|
|
30
|
+
if len(wss_rpcs) > 5:
|
|
31
|
+
print(" ... and more")
|
|
32
|
+
|
|
33
|
+
print("\nTracking info for first 5 RPCs:")
|
|
34
|
+
for node in all_rpcs[:5]:
|
|
35
|
+
print(f" - {node.url}: Tracking={node.is_tracking} (Privacy={node.privacy}, Tracking={node.tracking})")
|
|
36
|
+
|
|
37
|
+
if __name__ == "__main__":
|
|
38
|
+
main()
|
iwa/web/routers/olas/staking.py
CHANGED
|
@@ -105,16 +105,21 @@ def _check_availability(name, address, interface):
|
|
|
105
105
|
"""Check availability of a single staking contract."""
|
|
106
106
|
# Import at module level would cause circular import, but we can cache it
|
|
107
107
|
# The import is cached by Python after first call so this is efficient
|
|
108
|
+
from iwa.core.contracts.cache import ContractCache
|
|
108
109
|
from iwa.plugins.olas.contracts.staking import StakingContract
|
|
109
110
|
|
|
110
111
|
try:
|
|
111
|
-
|
|
112
|
+
# Use ContractCache to benefit from shared instances and property caching
|
|
113
|
+
contract = ContractCache().get_contract(
|
|
114
|
+
StakingContract, address, chain_name=interface.chain.name
|
|
115
|
+
)
|
|
112
116
|
|
|
113
117
|
# StakingContract uses .call() which handles with_retry and rotation
|
|
118
|
+
# Use properties instead of .call() to leverage caching
|
|
114
119
|
service_ids = contract.call("getServiceIds")
|
|
115
|
-
max_services = contract.
|
|
116
|
-
min_deposit = contract.
|
|
117
|
-
staking_token = contract.
|
|
120
|
+
max_services = contract.max_num_services
|
|
121
|
+
min_deposit = contract.min_staking_deposit
|
|
122
|
+
staking_token = contract.staking_token_address
|
|
118
123
|
used = len(service_ids)
|
|
119
124
|
|
|
120
125
|
return {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
iwa/__init__.py,sha256=vu12UytYNREtMRvIWp6AfV1GgUe53XWwCMhYyqKAPgo,19
|
|
2
2
|
iwa/__main__.py,sha256=eJU5Uxeu9Y7shWg5dt5Mcq0pMC4wFVNWjeYGKSf4Apw,88
|
|
3
3
|
iwa/core/__init__.py,sha256=GJv4LJOXeZ3hgGvbt5I6omkoFkP2A9qhHjpDlOep9ik,24
|
|
4
|
+
iwa/core/chainlist.py,sha256=IOnlfRFaPlzdg91HbILynzvRfEJ9afikjFUS06K4rfU,4021
|
|
4
5
|
iwa/core/cli.py,sha256=GCrHSUp5W1KdLHoWbk0aCLTphkKDLROoFh82uyUqdY8,7729
|
|
5
|
-
iwa/core/constants.py,sha256=
|
|
6
|
+
iwa/core/constants.py,sha256=_CYUVQpR--dRPuxotsmbzQE-22y61tlnjUD7IhlvVVA,997
|
|
6
7
|
iwa/core/db.py,sha256=WI-mP0tQAmwFPeEi9w7RCa_Mcf_zBfd_7JcbHJwU1aU,10377
|
|
7
8
|
iwa/core/ipfs.py,sha256=aHjq_pflgwDVHl8g5EMQv0q2RAmMs-a0pOTVsj_L5xE,4980
|
|
8
9
|
iwa/core/keys.py,sha256=ckacVZxm_02V9hlmHIxz-CkxjXdGHqvGGAXfO6EeHCw,22365
|
|
@@ -11,6 +12,7 @@ iwa/core/models.py,sha256=kBQ0cBe6uFmL2QfW7mjKiMFeZxhT-FRN-RyK3Ko0vE8,12849
|
|
|
11
12
|
iwa/core/monitor.py,sha256=OmhKVMkfhvtxig3wDUL6iGwBIClTx0YUqMncCao4SqI,7953
|
|
12
13
|
iwa/core/plugins.py,sha256=FLvOG4S397fKi0aTH1fWBEtexn4yvGv_QzGWqFrhSKE,1102
|
|
13
14
|
iwa/core/pricing.py,sha256=uENpqVMmuogZHctsLuEsU7WJ1cLSNAI-rZTtbpTDjeQ,4048
|
|
15
|
+
iwa/core/rpc_monitor.py,sha256=-NHR1Mn2IJKJ9x975NGfsze_shI12yL0OyTPtmjUMKg,1661
|
|
14
16
|
iwa/core/secrets.py,sha256=U7DZKrwKuSOFV00Ij3ISrrO1cWn_t1GBW_0PyAqjcD4,2588
|
|
15
17
|
iwa/core/tables.py,sha256=y7Cg67PAGHYVMVyAjbo_CQ9t2iz7UXE-OTuUHRyFRTo,2021
|
|
16
18
|
iwa/core/test.py,sha256=gey0dql5eajo1itOhgkSrgfyGWue2eSfpr0xzX3vc38,643
|
|
@@ -25,7 +27,8 @@ iwa/core/chain/manager.py,sha256=cFEzh6pK5OyVhjhpeMAqhc9RnRDQR1DjIGiGKp-FXBI,115
|
|
|
25
27
|
iwa/core/chain/models.py,sha256=0OgBo08FZEQisOdd00YUMXSAV7BC0CcWpqJ2y-gs0cI,4863
|
|
26
28
|
iwa/core/chain/rate_limiter.py,sha256=gU7TmWdH9D_wbXKT1X7mIgoIUCWVuebgvRhxiyLGAmI,6613
|
|
27
29
|
iwa/core/contracts/__init__.py,sha256=P5GFY_pnuI02teqVY2U0t98bn1_SSPAbcAzRMpCdTi4,34
|
|
28
|
-
iwa/core/contracts/
|
|
30
|
+
iwa/core/contracts/cache.py,sha256=7wGQgyXAmofvx-irbxSnGgIDzQik6Pcpm7up6wMQcoo,4454
|
|
31
|
+
iwa/core/contracts/contract.py,sha256=DCSQmlOom_SkGXElcr1VQyAt2nt0GjkYhLpiQsWDJPY,12810
|
|
29
32
|
iwa/core/contracts/erc20.py,sha256=VqriOdUXej0ilTgpukpm1FUF_9sSrVMAPuEpIvyZ2SQ,2646
|
|
30
33
|
iwa/core/contracts/multisend.py,sha256=tSdBCWe7LSdBoKZ7z2QebmRFK4M2ln7H3kmJBeEb4Ho,2431
|
|
31
34
|
iwa/core/contracts/abis/erc20.json,sha256=vrdExMWcIogg_nO59j1Pmipmpa2Ulj3oCCdcdrrFVCE,16995
|
|
@@ -57,17 +60,18 @@ iwa/plugins/gnosis/tests/test_cow.py,sha256=iVy5ockMIcPZWsX4WGXU91DhBsYEZ5NOxtFz
|
|
|
57
60
|
iwa/plugins/gnosis/tests/test_safe.py,sha256=pw1zrYvAiVtmPIU5k7BtOQpDNAQTSTrLIaeljCjSahc,3216
|
|
58
61
|
iwa/plugins/olas/__init__.py,sha256=_NhBczzM61fhGYwGhnWfEeL8Jywyy_730GASe2BxzeQ,106
|
|
59
62
|
iwa/plugins/olas/constants.py,sha256=iTFoO2QW3KbhL5k5sKsJxxyDytl9wVIb_9hAih55KrE,7728
|
|
63
|
+
iwa/plugins/olas/events.py,sha256=SWD3wYdQ-l6dLUJSkfh_WsLmedH4Vsw_EvYXg7QC3yc,5970
|
|
60
64
|
iwa/plugins/olas/importer.py,sha256=f8KlZ9dGcNbpg8uoTYbO9sDvbluZoslhpWFLqPjPnLA,26717
|
|
61
65
|
iwa/plugins/olas/mech_reference.py,sha256=CaSCpQnQL4F7wOG6Ox6Zdoy-uNEQ78YBwVLILQZKL8Q,5782
|
|
62
66
|
iwa/plugins/olas/models.py,sha256=xC5hYakX53pBT6zZteM9cyiC7t6XRLLpobjQmDYueOo,3520
|
|
63
67
|
iwa/plugins/olas/plugin.py,sha256=S_vnvZ02VdVWD7N5kp7u5JIRQ2JLtfwGDZ7OHkAN0M8,9390
|
|
64
|
-
iwa/plugins/olas/contracts/activity_checker.py,sha256=
|
|
68
|
+
iwa/plugins/olas/contracts/activity_checker.py,sha256=WXxuzbpXGVqIfEiMPiiqN3Z_UxIY-Lvx0raa1ErBfPA,5323
|
|
65
69
|
iwa/plugins/olas/contracts/base.py,sha256=y73aQbDq6l4zUpz_eQAg4MsLkTAEqjjupXlcvxjfgCI,240
|
|
66
70
|
iwa/plugins/olas/contracts/mech.py,sha256=dXYtyORc-oiu9ga5PtTquOFkoakb6BLGKvlUsteygIg,2767
|
|
67
71
|
iwa/plugins/olas/contracts/mech_marketplace.py,sha256=hMADl5MQGvT2wLRKu4vHGe4RrAZVq8Y2M_EvXWWz528,1554
|
|
68
72
|
iwa/plugins/olas/contracts/mech_marketplace_v1.py,sha256=ooF5uw1wxwYsoriGUGGxXxmaD8DtWZtK4TJBCUNTGtI,2501
|
|
69
73
|
iwa/plugins/olas/contracts/service.py,sha256=BDQKeCTCnBNrwKD1a8rrlLytpKG3CAdjr-s0ec-dsFY,8243
|
|
70
|
-
iwa/plugins/olas/contracts/staking.py,sha256=
|
|
74
|
+
iwa/plugins/olas/contracts/staking.py,sha256=TimiHSJy5wAlx35uplyeG7TG6NpxPigkmKcrz_ZBCjY,18487
|
|
71
75
|
iwa/plugins/olas/contracts/abis/activity_checker.json,sha256=HT0IMbyTLMO71ITBKwoS950rHe772suPP4b8eDAodJ0,2230
|
|
72
76
|
iwa/plugins/olas/contracts/abis/mech.json,sha256=bMMCXInjE_2PTPnc_sIyS_H8pod5Sm_e-xTbKgZppKc,16369
|
|
73
77
|
iwa/plugins/olas/contracts/abis/mech_marketplace.json,sha256=KPnF-H_UATb3wdb_7o6ky_hSp5xwgvckD-QqylsWJLg,32468
|
|
@@ -81,17 +85,17 @@ iwa/plugins/olas/contracts/abis/staking_token.json,sha256=cuUOmi1s4Z6VSIX0an_IxK
|
|
|
81
85
|
iwa/plugins/olas/scripts/test_full_mech_flow.py,sha256=Fqoq5bn7Z_3YyRrnuqNAZy9cwQDLiXP6Vf3EIeWPo2I,9024
|
|
82
86
|
iwa/plugins/olas/scripts/test_simple_lifecycle.py,sha256=8T50tOZx3afeECSfCNAb0rAHNtYOsBaeXlMwKXElCk8,2099
|
|
83
87
|
iwa/plugins/olas/service_manager/__init__.py,sha256=GXiThMEY3nPgHUl1i-DLrF4h96z9jPxxI8Jepo2E1PM,1926
|
|
84
|
-
iwa/plugins/olas/service_manager/base.py,sha256=
|
|
88
|
+
iwa/plugins/olas/service_manager/base.py,sha256=EBPg0ymqgtAb7ZvVSfTt31QYgv_6gp4UAc6je00NLAg,5009
|
|
85
89
|
iwa/plugins/olas/service_manager/drain.py,sha256=IS7YYKuQdkULcNdxfHVzjcq95pXKdpajolzLL78u4jc,12430
|
|
86
|
-
iwa/plugins/olas/service_manager/lifecycle.py,sha256=
|
|
87
|
-
iwa/plugins/olas/service_manager/mech.py,sha256=
|
|
88
|
-
iwa/plugins/olas/service_manager/staking.py,sha256=
|
|
90
|
+
iwa/plugins/olas/service_manager/lifecycle.py,sha256=Lr2O3Vmv8dLlzwUVt_Ga8bFRQD3TbrM6LGs5kKeiAOE,48410
|
|
91
|
+
iwa/plugins/olas/service_manager/mech.py,sha256=NVzVbEmyOe3wK92VEzCCOSuy3HDkEP1MSoVt7Av8Psk,27949
|
|
92
|
+
iwa/plugins/olas/service_manager/staking.py,sha256=7REp_HziKtqF9uSvbcq01C9XiaxgVT3gCimuLAAdNnM,28219
|
|
89
93
|
iwa/plugins/olas/tests/conftest.py,sha256=4vM7EI00SrTGyeP0hNzsGSQHEj2-iznVgzlNh2_OGfo,739
|
|
90
94
|
iwa/plugins/olas/tests/test_importer.py,sha256=i9LKov7kNRECB3hmRnhKBwcfx3uxtjWe4BB77bOOpeo,4282
|
|
91
95
|
iwa/plugins/olas/tests/test_importer_error_handling.py,sha256=X37TrvJ6-3-NuJ2megm0Cnx3KJdA1wke563pRf_EPJk,12084
|
|
92
96
|
iwa/plugins/olas/tests/test_mech_contracts.py,sha256=wvxuigPafF-ySIHVBdWVei3AO418iPh7cSVdAlUGm_s,3566
|
|
93
97
|
iwa/plugins/olas/tests/test_olas_contracts.py,sha256=B8X-5l1KfYMoZOiM94_rcNzbILLl78rqt_jhyxzAOqE,10835
|
|
94
|
-
iwa/plugins/olas/tests/test_olas_integration.py,sha256=
|
|
98
|
+
iwa/plugins/olas/tests/test_olas_integration.py,sha256=vjL8-RNdxXu6RFR5F1Bn7xqnxnUVWTzl2--Pp7-0r5A,22973
|
|
95
99
|
iwa/plugins/olas/tests/test_olas_models.py,sha256=5scX-wvRLGH3G44S2okq_tyQ9Rk7Pd0Ak1zNCZ2HtI4,4957
|
|
96
100
|
iwa/plugins/olas/tests/test_olas_view.py,sha256=kh3crsriyoRiZC6l8vzGllocvQnYmqziv-csbmXih0E,10489
|
|
97
101
|
iwa/plugins/olas/tests/test_olas_view_actions.py,sha256=jAxr9bjFNAaxGf1btIrxdMaHgJ0PWX9aDwVU-oPGMpk,5109
|
|
@@ -99,15 +103,15 @@ iwa/plugins/olas/tests/test_olas_view_modals.py,sha256=8j0PNFjKqFC5V1kBdVFWNLMvq
|
|
|
99
103
|
iwa/plugins/olas/tests/test_plugin.py,sha256=RVgU-Cq6t_3mOh90xFAGwlJOV7ZIgp0VNaK5ZAxisAQ,2565
|
|
100
104
|
iwa/plugins/olas/tests/test_plugin_full.py,sha256=xevLYmdU4zd5FyEEEn9gvzGimPztmt6vymybeZHXnq8,8507
|
|
101
105
|
iwa/plugins/olas/tests/test_service_lifecycle.py,sha256=sOCtpz8T9s55AZe9AoqP1h3XrXw5NDSjDqwLgYThvU4,5559
|
|
102
|
-
iwa/plugins/olas/tests/test_service_manager.py,sha256=
|
|
103
|
-
iwa/plugins/olas/tests/test_service_manager_errors.py,sha256=
|
|
104
|
-
iwa/plugins/olas/tests/test_service_manager_flows.py,sha256=
|
|
106
|
+
iwa/plugins/olas/tests/test_service_manager.py,sha256=rS2m0A26apc-o4HsfP5oXmVcmZSR5e874bjhQKZRaSg,40650
|
|
107
|
+
iwa/plugins/olas/tests/test_service_manager_errors.py,sha256=udlAsQj_t1F5TwVQuWhroF6jDJ4RmGEXaxPh87tMsuA,8538
|
|
108
|
+
iwa/plugins/olas/tests/test_service_manager_flows.py,sha256=QvRFpJIapZXbagxPApr-995i64aJDapxSFyae8tNSHU,20722
|
|
105
109
|
iwa/plugins/olas/tests/test_service_manager_mech.py,sha256=qG6qu5IPRNypXUsblU2OEkuiuwDJ0TH8RXZbibmTFcQ,4937
|
|
106
110
|
iwa/plugins/olas/tests/test_service_manager_rewards.py,sha256=hIVckGl5rEr-KHGNUxxVopal0Tpw4EZharBt0MbaCVA,11798
|
|
107
111
|
iwa/plugins/olas/tests/test_service_manager_validation.py,sha256=ajlfH5uc4mAHf8A7GLE5cW7X8utM2vUilM0JdGDdlVg,5382
|
|
108
|
-
iwa/plugins/olas/tests/test_service_staking.py,sha256=
|
|
112
|
+
iwa/plugins/olas/tests/test_service_staking.py,sha256=miNGZZoIrZf0Am-pJ8gTyvVAruL4P7jMvrtFEhG5wxQ,15694
|
|
109
113
|
iwa/plugins/olas/tests/test_staking_integration.py,sha256=QCBQf6P2ZmmsEGt2k8W2r53lG2aVRuoMJE-aFxVDLss,9701
|
|
110
|
-
iwa/plugins/olas/tests/test_staking_validation.py,sha256=
|
|
114
|
+
iwa/plugins/olas/tests/test_staking_validation.py,sha256=uug64jFcXYJ3Nw_lNa3O4fnhNr5wAWHHIrchSbR2MVE,4020
|
|
111
115
|
iwa/plugins/olas/tui/__init__.py,sha256=5ZRsbC7J3z1xfkZRiwr4bLEklf78rNVjdswe2p7SlS8,28
|
|
112
116
|
iwa/plugins/olas/tui/olas_view.py,sha256=qcPxhurDPJjHWln6R64ZVAJ2h82IXzw48unhRvQVZqQ,36448
|
|
113
117
|
iwa/tools/__init__.py,sha256=jQyuwDQGRigSe7S9JMb4yK3CXPgZFJNffzt6N2v9PU0,21
|
|
@@ -117,6 +121,7 @@ iwa/tools/release.py,sha256=-Z9GG6Y-K6KG32K0VUf_MruiUdJxG6W7ToOMzhyCH7Y,3963
|
|
|
117
121
|
iwa/tools/reset_env.py,sha256=FKN0wuh9Xq00c94B2kEFehHPKcWldxYqgU45yJwg5Cg,3140
|
|
118
122
|
iwa/tools/reset_tenderly.py,sha256=usKfOLrQvdCzEncueg-Sz3spqX80vHPQmbh2tIygo8o,11295
|
|
119
123
|
iwa/tools/restore_backup.py,sha256=_LJbmKv9SlekLUQFdjI3aHCvAc6uePobJe3bQEFyatk,2455
|
|
124
|
+
iwa/tools/test_chainlist.py,sha256=9J06sTsKgnEcN7WSn-YgJkCHhfbGDdVS-KNMDBhYllA,1143
|
|
120
125
|
iwa/tools/wallet_check.py,sha256=IQLgb8oCt4oG6FMEAqzUxM57DLv_UE24dFUSVxtBo_Y,4774
|
|
121
126
|
iwa/tui/__init__.py,sha256=XYIZNQNy-fZC1NHHM0sd9qUO0vE1slml-cm0CpQ4NLY,27
|
|
122
127
|
iwa/tui/app.py,sha256=XDQ4nAPGBwhrEmdL_e3V8oYSOho8pY7jsd3C_wk92UU,4163
|
|
@@ -144,7 +149,7 @@ iwa/web/routers/olas/admin.py,sha256=PMRdNelqYgQ1xbqh3floFV5xrVtBRQiwZPd8J9_ffxg
|
|
|
144
149
|
iwa/web/routers/olas/funding.py,sha256=f8fADNtbZEBFl-vuVKfas6os38Vot6K5tJBTenZmCD0,4832
|
|
145
150
|
iwa/web/routers/olas/general.py,sha256=dPsBQppTGoQY1RztliUhseOHOZGeeCR10lhThD9kyXo,803
|
|
146
151
|
iwa/web/routers/olas/services.py,sha256=IpjvkpJeCwREbdHt47gov-fvTl9bY4EBUmZZZEHi3iI,16310
|
|
147
|
-
iwa/web/routers/olas/staking.py,sha256=
|
|
152
|
+
iwa/web/routers/olas/staking.py,sha256=Ak29SIIMNAgPqIij6sdNAG4z7LUeUGRVRpplZw4hsAU,12666
|
|
148
153
|
iwa/web/static/app.js,sha256=CWm_TR2nKSDe8z0-nUQp7VaBHIGJg7mAOU-XJDveFsk,113487
|
|
149
154
|
iwa/web/static/index.html,sha256=q7s7plnMbN1Nkzr5bRxZgvgOFerUChEGIZW7SpAVtPc,28514
|
|
150
155
|
iwa/web/static/style.css,sha256=aTtE42mmfYV6y7xfo9cUgUhT8x-KyNC1zmPjSdskxIk,24315
|
|
@@ -152,7 +157,7 @@ iwa/web/tests/test_web_endpoints.py,sha256=C264MH-CTyDW4GLUrTXBgLJKUk4-89pFAScBd
|
|
|
152
157
|
iwa/web/tests/test_web_olas.py,sha256=0CVSsrncOeJ3x0ECV7mVLQV_CXZRrOqGiVjgLIi6hZ8,16308
|
|
153
158
|
iwa/web/tests/test_web_swap.py,sha256=7A4gBJFL01kIXPtW1E1J17SCsVc_0DmUn-R8kKrnnVA,2974
|
|
154
159
|
iwa/web/tests/test_web_swap_coverage.py,sha256=zGNrzlhZ_vWDCvWmLcoUwFgqxnrp_ACbo49AtWBS_Kw,5584
|
|
155
|
-
iwa-0.0.
|
|
160
|
+
iwa-0.0.20.dist-info/licenses/LICENSE,sha256=eIubm_IlBHPYRQlLNZKbBNKhJUUP3JH0A2miZUhAVfI,1078
|
|
156
161
|
tests/legacy_cow.py,sha256=oOkZvIxL70ReEoD9oHQbOD5GpjIr6AGNHcOCgfPlerU,8389
|
|
157
162
|
tests/legacy_safe.py,sha256=AssM2g13E74dNGODu_H0Q0y412lgqsrYnEzI97nm_Ts,2972
|
|
158
163
|
tests/legacy_transaction_retry_logic.py,sha256=D9RqZ7DBu61Xr2djBAodU2p9UE939LL-DnQXswX5iQk,1497
|
|
@@ -183,6 +188,7 @@ tests/test_plugin_service.py,sha256=ZEe37kV_sv4Eb04032O1hZIoo9yf5gJo83ks7Grzrng,
|
|
|
183
188
|
tests/test_pricing.py,sha256=ptu_2Csc6d64bIzMMw3TheJge2Kfn05Gs-twz_KmBzg,5276
|
|
184
189
|
tests/test_rate_limiter.py,sha256=DOIlrBP2AtVFHCpznIoFn2FjFc33emG7M_FffLh4MGE,7314
|
|
185
190
|
tests/test_reset_tenderly.py,sha256=GVoqbDT3n4_GnlKF5Lx-8ew15jT8I2hIPdTulQDb6dI,7215
|
|
191
|
+
tests/test_rpc_efficiency.py,sha256=EEcBlbUXEi9JVBorLU7mK7mmK0vcFt53KhefHr1oPQc,3741
|
|
186
192
|
tests/test_rpc_rotation.py,sha256=YU21TrMnEbcb36zu_L8dpCSbaHX7CkqXLjipz1swkkc,10554
|
|
187
193
|
tests/test_rpc_view.py,sha256=sgZ53KEHl8VGb7WKYa0VI7Cdxbf8JH1SdroHYbWHjfQ,2031
|
|
188
194
|
tests/test_safe_coverage.py,sha256=g9Bdrpkc-Mc8HBjk07lYNRkzxWZiF922uiVLZqhehBE,5093
|
|
@@ -204,8 +210,8 @@ tests/test_utils.py,sha256=vkP49rYNI8BRzLpWR3WnKdDr8upeZjZcs7Rx0pjbQMo,1292
|
|
|
204
210
|
tests/test_workers.py,sha256=MInwdkFY5LdmFB3o1odIaSD7AQZb3263hNafO1De5PE,2793
|
|
205
211
|
tools/create_and_stake_service.py,sha256=1xwy_bJQI1j9yIQ968Oc9Db_F6mk1659LuuZntTASDE,3742
|
|
206
212
|
tools/verify_drain.py,sha256=PkMjblyOOAuQge88FwfEzRtCYeEtJxXhPBmtQYCoQ-8,6743
|
|
207
|
-
iwa-0.0.
|
|
208
|
-
iwa-0.0.
|
|
209
|
-
iwa-0.0.
|
|
210
|
-
iwa-0.0.
|
|
211
|
-
iwa-0.0.
|
|
213
|
+
iwa-0.0.20.dist-info/METADATA,sha256=_ERQ1f_nDtVFZClmaQ4vW6o6Yso2JjqumBbS56JJCCs,7295
|
|
214
|
+
iwa-0.0.20.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
215
|
+
iwa-0.0.20.dist-info/entry_points.txt,sha256=nwB6kscrfA7M00pYmL2j-sBH6eF6h2ga9IK1BZxdiyQ,241
|
|
216
|
+
iwa-0.0.20.dist-info/top_level.txt,sha256=kedS9cRUbm4JE2wYeabIXilhHjN8KCw0IGbqqqsw0Bs,16
|
|
217
|
+
iwa-0.0.20.dist-info/RECORD,,
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
from unittest.mock import MagicMock, patch
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from iwa.core.contracts.cache import ContractCache
|
|
6
|
+
from iwa.plugins.olas.contracts.staking import StakingContract
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.fixture
|
|
10
|
+
def mock_chain_interface():
|
|
11
|
+
with patch("iwa.core.contracts.contract.ChainInterfaces") as mock_chains:
|
|
12
|
+
mock_interface = MagicMock()
|
|
13
|
+
mock_chains.return_value.get.return_value = mock_interface
|
|
14
|
+
|
|
15
|
+
# Mock web3 and contract
|
|
16
|
+
mock_web3_backend = MagicMock()
|
|
17
|
+
mock_interface.web3._web3 = mock_web3_backend
|
|
18
|
+
|
|
19
|
+
mock_contract = MagicMock()
|
|
20
|
+
mock_web3_backend.eth.contract.return_value = mock_contract
|
|
21
|
+
|
|
22
|
+
# Mock with_retry to execute the function
|
|
23
|
+
mock_interface.with_retry.side_effect = lambda func, **kwargs: func()
|
|
24
|
+
|
|
25
|
+
# Yield both interface and contract mock
|
|
26
|
+
yield mock_interface, mock_contract
|
|
27
|
+
|
|
28
|
+
def test_staking_contract_lazy_loading(mock_chain_interface):
|
|
29
|
+
"""Verify StakingContract init does NOT make RPC calls."""
|
|
30
|
+
mock_interface, mock_contract = mock_chain_interface
|
|
31
|
+
|
|
32
|
+
# Reset ContractCache
|
|
33
|
+
ContractCache().clear()
|
|
34
|
+
|
|
35
|
+
# Instantiate logic
|
|
36
|
+
contract = StakingContract(address="0x123", chain_name="gnosis")
|
|
37
|
+
|
|
38
|
+
# Assert NO calls to call yet (since we mock with_retry to execute immediately, 0 calls means 0 executions)
|
|
39
|
+
assert mock_interface.with_retry.call_count == 0
|
|
40
|
+
|
|
41
|
+
# Setup return value
|
|
42
|
+
# livenessPeriod is a property that calls "livenessPeriod" on contract
|
|
43
|
+
mock_contract.functions.livenessPeriod.return_value.call.return_value = 3600
|
|
44
|
+
|
|
45
|
+
# Access property
|
|
46
|
+
val = contract.liveness_period
|
|
47
|
+
assert val == 3600
|
|
48
|
+
|
|
49
|
+
# Assert 1 call
|
|
50
|
+
assert mock_contract.functions.livenessPeriod.return_value.call.call_count == 1
|
|
51
|
+
|
|
52
|
+
# Access again
|
|
53
|
+
val = contract.liveness_period
|
|
54
|
+
|
|
55
|
+
# Assert still 1 call (cached)
|
|
56
|
+
assert mock_contract.functions.livenessPeriod.return_value.call.call_count == 1
|
|
57
|
+
|
|
58
|
+
def test_contract_cache_singleton(mock_chain_interface):
|
|
59
|
+
"""Verify ContractCache returns same instance and reuses property cache."""
|
|
60
|
+
mock_interface, mock_contract = mock_chain_interface
|
|
61
|
+
ContractCache().clear()
|
|
62
|
+
|
|
63
|
+
c1 = ContractCache().get_contract(StakingContract, "0xABC", "gnosis")
|
|
64
|
+
c2 = ContractCache().get_contract(StakingContract, "0xabc", "gnosis") # Check ignore case
|
|
65
|
+
|
|
66
|
+
assert c1 is c2
|
|
67
|
+
|
|
68
|
+
# populate cache on c1
|
|
69
|
+
mock_contract.functions.maxNumServices.return_value.call.return_value = 500
|
|
70
|
+
|
|
71
|
+
val1 = c1.max_num_services
|
|
72
|
+
assert val1 == 500
|
|
73
|
+
assert mock_contract.functions.maxNumServices.return_value.call.call_count == 1
|
|
74
|
+
|
|
75
|
+
# access on c2
|
|
76
|
+
val2 = c2.max_num_services
|
|
77
|
+
assert val2 == 500
|
|
78
|
+
# Call count should NOT increase
|
|
79
|
+
assert mock_contract.functions.maxNumServices.return_value.call.call_count == 1
|
|
80
|
+
|
|
81
|
+
def test_epoch_aware_caching(mock_chain_interface):
|
|
82
|
+
"""Verify ts_checkpoint caching logic."""
|
|
83
|
+
mock_interface, mock_contract = mock_chain_interface
|
|
84
|
+
ContractCache().clear()
|
|
85
|
+
contract = StakingContract(address="0xEpoch", chain_name="gnosis")
|
|
86
|
+
|
|
87
|
+
# Mock return values for tsCheckpoint
|
|
88
|
+
# We use side_effect on the call() method to simulate changing return values if needed
|
|
89
|
+
# But here we just want it to return 1000 once
|
|
90
|
+
mock_contract.functions.tsCheckpoint.return_value.call.return_value = 1000
|
|
91
|
+
|
|
92
|
+
# Set liveness period in cache to avoid RPC call for it
|
|
93
|
+
contract._contract_params_cache["livenessPeriod"] = 600
|
|
94
|
+
|
|
95
|
+
# 1. Fetch ts_checkpoint
|
|
96
|
+
ts = contract.ts_checkpoint()
|
|
97
|
+
assert ts == 1000
|
|
98
|
+
assert mock_contract.functions.tsCheckpoint.return_value.call.call_count == 1
|
|
99
|
+
|
|
100
|
+
# 2. Call again - should be cached
|
|
101
|
+
ts2 = contract.ts_checkpoint()
|
|
102
|
+
assert ts2 == 1000
|
|
103
|
+
assert mock_contract.functions.tsCheckpoint.return_value.call.call_count == 1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|