iwa 0.0.62__py3-none-any.whl → 0.0.65__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.
@@ -136,8 +136,8 @@ class TransferService(
136
136
 
137
137
  amount_eth = float(chain_interface.web3.from_wei(amount_wei, "ether"))
138
138
  logger.info(
139
- f"Sending {amount_eth:.4f} {token_address_or_name} "
140
- f"from {from_address_or_tag} to {to_address_or_tag}"
139
+ f"Sending {amount_eth:.4f} {token_symbol} "
140
+ f"from {from_tag or from_address_or_tag} to {to_tag or to_address_or_tag}"
141
141
  )
142
142
 
143
143
  if is_safe:
@@ -2,7 +2,7 @@
2
2
 
3
3
  from typing import Dict, List, Optional
4
4
 
5
- from pydantic import BaseModel, Field, root_validator
5
+ from pydantic import BaseModel, Field
6
6
 
7
7
  from iwa.core.models import EthereumAddress
8
8
 
@@ -15,37 +15,20 @@ class Service(BaseModel):
15
15
  service_id: int # Unique per chain
16
16
  agent_ids: List[int] = Field(default_factory=list) # List of agent type IDs
17
17
 
18
- # New explicit owner fields
18
+ # Owner fields:
19
+ # - service_owner_eoa_address: EOA that owns the service (or signs for the multisig)
20
+ # - service_owner_multisig_address: Safe multisig owner (optional, if service is owned by a Safe)
19
21
  service_owner_eoa_address: Optional[EthereumAddress] = None
20
22
  service_owner_multisig_address: Optional[EthereumAddress] = None
21
23
 
22
- # Deprecated fields (kept for migration, removed from physical model via aliasing/validation)
23
- # Actually, we keep it optional but not used, or use migration logic.
24
- # Let's remove it from fields and rely on before validator to map it to eoa.
25
-
26
24
  agent_address: Optional[EthereumAddress] = None
27
25
  multisig_address: Optional[EthereumAddress] = None
28
26
  staking_contract_address: Optional[EthereumAddress] = None
29
27
  token_address: Optional[EthereumAddress] = None
30
28
 
31
- @root_validator(pre=True)
32
- def migrate_owner_fields(cls, values): # noqa: N805
33
- """Migrate legacy service_owner_address to service_owner_eoa_address."""
34
- # Check for legacy 'service_owner_address'
35
- if "service_owner_address" in values and values["service_owner_address"]:
36
- legacy_addr = values["service_owner_address"]
37
-
38
- # If service_owner_eoa_address is missing, use legacy
39
- if "service_owner_eoa_address" not in values or not values["service_owner_eoa_address"]:
40
- values["service_owner_eoa_address"] = legacy_addr
41
-
42
- # Remove legacy field from values so it doesn't cause extra field errors if we removed it from model
43
- # Or if strict.
44
- return values
45
-
46
29
  @property
47
30
  def service_owner_address(self) -> Optional[EthereumAddress]:
48
- """Backward compatibility property: Returns effective owner (Safe if present, else EOA)."""
31
+ """Returns effective owner address (Safe multisig if present, else EOA)."""
49
32
  return self.service_owner_multisig_address or self.service_owner_eoa_address
50
33
 
51
34
  @property
@@ -12,7 +12,9 @@ from iwa.plugins.olas.contracts.staking import StakingContract, StakingState
12
12
  class DrainManagerMixin:
13
13
  """Mixin for draining and service token management."""
14
14
 
15
- def claim_rewards(self, staking_contract: Optional[StakingContract] = None) -> Tuple[bool, int]:
15
+ def claim_rewards( # noqa: C901
16
+ self, staking_contract: Optional[StakingContract] = None
17
+ ) -> Tuple[bool, int]:
16
18
  """Claim staking rewards for the active service.
17
19
 
18
20
  The claimed OLAS tokens will be sent to the service's multisig (Safe).
@@ -51,13 +53,19 @@ class DrainManagerMixin:
51
53
  logger.info("Service not staked, skipping claim")
52
54
  return False, 0
53
55
 
54
- # Check accrued rewards
55
- accrued_rewards = staking_contract.get_accrued_rewards(service_id)
56
- if accrued_rewards == 0:
57
- logger.info("No accrued rewards to claim")
56
+ # Check claimable rewards using calculate_staking_reward for accurate value
57
+ # (get_accrued_rewards returns stored value which may be outdated)
58
+ try:
59
+ claimable_rewards = staking_contract.calculate_staking_reward(service_id)
60
+ except Exception:
61
+ # Fallback to stored value if calculation fails
62
+ claimable_rewards = staking_contract.get_accrued_rewards(service_id)
63
+
64
+ if claimable_rewards == 0:
65
+ logger.info("No rewards to claim")
58
66
  return False, 0
59
67
 
60
- logger.info(f"Claiming {accrued_rewards / 1e18:.4f} OLAS rewards for service {service_id}")
68
+ logger.info(f"Claiming ~{claimable_rewards / 1e18:.4f} OLAS rewards for service {service_id}")
61
69
 
62
70
  # Use service owner which holds the reward rights (not necessarily master)
63
71
  owner_address = self.service.service_owner_address or self.wallet.master_account.address
@@ -72,6 +80,13 @@ class DrainManagerMixin:
72
80
  logger.error("Failed to prepare claim transaction")
73
81
  return False, 0
74
82
 
83
+ # Simulate transaction to catch revert before sending
84
+ try:
85
+ staking_contract.chain_interface.web3.eth.call(claim_tx)
86
+ except Exception as e:
87
+ logger.warning(f"Claim would revert, skipping: {e}")
88
+ return False, 0
89
+
75
90
  success, receipt = self.wallet.sign_and_send_transaction(
76
91
  claim_tx,
77
92
  signer_address_or_tag=owner_address,
@@ -83,11 +98,19 @@ class DrainManagerMixin:
83
98
  return False, 0
84
99
 
85
100
  events = staking_contract.extract_events(receipt)
86
- if "RewardClaimed" not in [event["name"] for event in events]:
87
- logger.warning("RewardClaimed event not found, but transaction succeeded")
88
101
 
89
- logger.info(f"Successfully claimed {accrued_rewards / 1e18:.4f} OLAS rewards")
90
- return True, accrued_rewards
102
+ # Extract actual claimed amount from RewardClaimed event
103
+ claimed_amount = claimable_rewards # Default to estimated
104
+ for event in events:
105
+ if event["name"] == "RewardClaimed":
106
+ # RewardClaimed event has 'amount' or 'reward' field
107
+ claimed_amount = event["args"].get("amount", event["args"].get("reward", claimed_amount))
108
+ break
109
+ else:
110
+ logger.warning("RewardClaimed event not found, using estimated amount")
111
+
112
+ logger.info(f"Successfully claimed {claimed_amount / 1e18:.4f} OLAS rewards")
113
+ return True, claimed_amount
91
114
 
92
115
  def withdraw_rewards(self) -> Tuple[bool, float]:
93
116
  """Withdraw OLAS from the service Safe to the configured withdrawal address.
@@ -132,8 +155,14 @@ class DrainManagerMixin:
132
155
  return False, 0
133
156
 
134
157
  olas_amount = olas_balance / 1e18
135
- withdrawal_tag = self.wallet.get_tag_by_address(withdrawal_address) or withdrawal_address
136
- multisig_tag = self.wallet.get_tag_by_address(multisig_address) or multisig_address
158
+ withdrawal_tag = (
159
+ self.wallet.account_service.get_tag_by_address(withdrawal_address)
160
+ or withdrawal_address
161
+ )
162
+ multisig_tag = (
163
+ self.wallet.account_service.get_tag_by_address(multisig_address)
164
+ or multisig_address
165
+ )
137
166
 
138
167
  logger.info(f"Withdrawing {olas_amount:.4f} OLAS from {multisig_tag} to {withdrawal_tag}")
139
168
 
@@ -183,7 +183,7 @@ class LifecycleManagerMixin:
183
183
  service_name=service_name,
184
184
  chain_name=chain_name,
185
185
  agent_id_values=agent_id_values,
186
- service_owner_address=service_owner_account.address,
186
+ service_owner_eoa_address=service_owner_account.address,
187
187
  token_address=token_address,
188
188
  )
189
189
 
@@ -263,7 +263,7 @@ class LifecycleManagerMixin:
263
263
  service_name: Optional[str],
264
264
  chain_name: str,
265
265
  agent_id_values: List[int],
266
- service_owner_address: str,
266
+ service_owner_eoa_address: str,
267
267
  token_address: Optional[str],
268
268
  ) -> None:
269
269
  """Create and save the new Service model."""
@@ -272,7 +272,7 @@ class LifecycleManagerMixin:
272
272
  chain_name=chain_name,
273
273
  service_id=service_id,
274
274
  agent_ids=agent_id_values,
275
- service_owner_address=service_owner_address,
275
+ service_owner_eoa_address=service_owner_eoa_address,
276
276
  token_address=token_address,
277
277
  )
278
278
 
@@ -14,7 +14,7 @@ class TestOlasConfig:
14
14
  chain_name="gnosis",
15
15
  service_id=456,
16
16
  agent_ids=[25],
17
- service_owner_address="0x1234567890123456789012345678901234567890",
17
+ service_owner_eoa_address="0x1234567890123456789012345678901234567890",
18
18
  )
19
19
 
20
20
  config.add_service(service)
@@ -30,7 +30,7 @@ class TestOlasConfig:
30
30
  chain_name="gnosis",
31
31
  service_id=789,
32
32
  agent_ids=[25],
33
- service_owner_address="0x1234567890123456789012345678901234567890",
33
+ service_owner_eoa_address="0x1234567890123456789012345678901234567890",
34
34
  )
35
35
  config.services["gnosis:789"] = service
36
36
 
@@ -53,7 +53,7 @@ class TestOlasConfig:
53
53
  chain_name="ethereum",
54
54
  service_id=200,
55
55
  agent_ids=[25],
56
- service_owner_address="0x1234567890123456789012345678901234567890",
56
+ service_owner_eoa_address="0x1234567890123456789012345678901234567890",
57
57
  )
58
58
  config.services["ethereum:200"] = service
59
59
 
@@ -116,7 +116,7 @@ class TestService:
116
116
  chain_name="gnosis",
117
117
  service_id=123,
118
118
  agent_ids=[25],
119
- service_owner_address="0x1234567890123456789012345678901234567890",
119
+ service_owner_eoa_address="0x1234567890123456789012345678901234567890",
120
120
  )
121
121
 
122
122
  assert service.key == "gnosis:123"
@@ -133,7 +133,7 @@ class TestService:
133
133
  chain_name="gnosis",
134
134
  service_id=456,
135
135
  agent_ids=[25],
136
- service_owner_address="0x1234567890123456789012345678901234567890",
136
+ service_owner_eoa_address="0x1234567890123456789012345678901234567890",
137
137
  staking_contract_address=staking_addr,
138
138
  token_address=token_addr,
139
139
  )
@@ -35,7 +35,7 @@ def mock_olas_config():
35
35
  chain_name="gnosis",
36
36
  agent_address=VALID_ADDR_1,
37
37
  multisig_address=VALID_ADDR_2,
38
- service_owner_address=VALID_ADDR_3,
38
+ service_owner_eoa_address=VALID_ADDR_3,
39
39
  staking_contract_address=VALID_ADDR_1,
40
40
  )
41
41
  config = OlasConfig(services={"gnosis:1": service})
@@ -108,6 +108,7 @@ def test_claim_rewards_no_accrued_rewards(mock_wallet):
108
108
 
109
109
  mock_staking = MagicMock()
110
110
  mock_staking.get_staking_state.return_value = StakingState.STAKED
111
+ mock_staking.calculate_staking_reward.return_value = 0
111
112
  mock_staking.get_accrued_rewards.return_value = 0
112
113
 
113
114
  success, amount = manager.claim_rewards(staking_contract=mock_staking)
@@ -129,9 +130,12 @@ def test_claim_rewards_success(mock_wallet):
129
130
 
130
131
  mock_staking = MagicMock()
131
132
  mock_staking.get_staking_state.return_value = StakingState.STAKED
133
+ mock_staking.calculate_staking_reward.return_value = 10 * 10**18 # 10 OLAS
132
134
  mock_staking.get_accrued_rewards.return_value = 10 * 10**18 # 10 OLAS
133
135
  mock_staking.prepare_claim_tx.return_value = {"data": "0x"}
134
- mock_staking.extract_events.return_value = [{"name": "RewardClaimed"}]
136
+ mock_staking.extract_events.return_value = [
137
+ {"name": "RewardClaimed", "args": {"amount": 10 * 10**18}}
138
+ ]
135
139
 
136
140
  success, amount = manager.claim_rewards(staking_contract=mock_staking)
137
141
 
@@ -152,6 +156,7 @@ def test_claim_rewards_tx_fails(mock_wallet):
152
156
 
153
157
  mock_staking = MagicMock()
154
158
  mock_staking.get_staking_state.return_value = StakingState.STAKED
159
+ mock_staking.calculate_staking_reward.return_value = 10 * 10**18
155
160
  mock_staking.get_accrued_rewards.return_value = 10 * 10**18
156
161
  mock_staking.prepare_claim_tx.return_value = {"data": "0x"}
157
162
  mock_wallet.sign_and_send_transaction.return_value = (False, {})
@@ -201,6 +201,7 @@ def test_sm_claim_rewards_tx_fails(mock_wallet):
201
201
  mock_staking = MagicMock()
202
202
  mock_staking.prepare_claim_tx.return_value = {"to": VALID_ADDR}
203
203
  mock_staking.get_staking_state.return_value = StakingState.STAKED
204
+ mock_staking.calculate_staking_reward.return_value = 100
204
205
  mock_staking.get_accrued_rewards.return_value = 100
205
206
 
206
207
  def get_contract_side_effect(cls, *args, **kwargs):
iwa/web/routers/state.py CHANGED
@@ -3,6 +3,7 @@
3
3
  from fastapi import APIRouter, Depends
4
4
 
5
5
  from iwa.core.chain import ChainInterfaces
6
+ from iwa.core.models import Config
6
7
  from iwa.web.dependencies import verify_auth
7
8
 
8
9
  router = APIRouter(prefix="/api", tags=["state"])
@@ -25,12 +26,19 @@ def get_state(auth: bool = Depends(verify_auth)):
25
26
  # Get token symbols from the interface (dict of symbol -> address)
26
27
  tokens[name] = list(interface.tokens.keys())
27
28
 
29
+ # Get whitelist from config
30
+ config = Config()
31
+ whitelist = {}
32
+ if config.core and config.core.whitelist:
33
+ whitelist = {tag: str(addr) for tag, addr in config.core.whitelist.items()}
34
+
28
35
  return {
29
36
  "chains": chain_names,
30
37
  "tokens": tokens,
31
38
  "native_currencies": native_currencies,
32
39
  "default_chain": "gnosis",
33
40
  "testing": ChainInterfaces().gnosis.is_tenderly,
41
+ "whitelist": whitelist,
34
42
  }
35
43
 
36
44
 
iwa/web/static/app.js CHANGED
@@ -12,6 +12,7 @@ document.addEventListener("DOMContentLoaded", () => {
12
12
  olasServicesCache: {}, // { chain: [services] }
13
13
  stakingContractsCache: null, // Cached staking contracts
14
14
  olasPriceCache: null, // Cached OLAS price in EUR
15
+ whitelist: {}, // { tag: address } from config
15
16
  };
16
17
 
17
18
  // Real-time countdown updater for unstake availability
@@ -138,6 +139,7 @@ document.addEventListener("DOMContentLoaded", () => {
138
139
  state.chains = data.chains;
139
140
  state.tokens = data.tokens;
140
141
  state.nativeCurrencies = data.native_currencies || {};
142
+ state.whitelist = data.whitelist || {};
141
143
 
142
144
  // Update status indicator for testing mode
143
145
  const statusText = document.getElementById("status-text");
@@ -518,12 +520,24 @@ document.addEventListener("DOMContentLoaded", () => {
518
520
  )
519
521
  .join("");
520
522
 
521
- toSelect.innerHTML = state.accounts
523
+ // Build To options: own accounts + whitelisted addresses
524
+ const accountOptions = state.accounts
522
525
  .map(
523
526
  (acc) =>
524
527
  `<option value="${escapeHtml(acc.tag)}">${escapeHtml(acc.tag)}</option>`,
525
528
  )
526
529
  .join("");
530
+ const whitelistOptions = Object.entries(state.whitelist)
531
+ .map(
532
+ ([tag, addr]) =>
533
+ `<option value="${escapeHtml(addr)}">${escapeHtml(tag)} (whitelist)</option>`,
534
+ )
535
+ .join("");
536
+ toSelect.innerHTML =
537
+ accountOptions +
538
+ (whitelistOptions
539
+ ? `<optgroup label="Whitelist">${whitelistOptions}</optgroup>`
540
+ : "");
527
541
 
528
542
  tokenSelect.innerHTML =
529
543
  `<option value="native">${escapeHtml(nativeSymbol)}</option>` +
iwa/web/static/index.html CHANGED
@@ -538,6 +538,6 @@
538
538
  </div>
539
539
  <!-- Modals (minimal implementation for now) -->
540
540
  <div id="toast-container" class="toast-container"></div>
541
- <script src="/static/app.js?v=1.0.4"></script>
541
+ <script src="/static/app.js?v=1.0.5"></script>
542
542
  </body>
543
543
  </html>
@@ -43,7 +43,7 @@ def mock_olas_config():
43
43
  chain_name="gnosis",
44
44
  agent_address="0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB",
45
45
  multisig_address="0x40A2aCCbd92BCA938b02010E17A5b8929b49130D",
46
- service_owner_address="0x1111111111111111111111111111111111111111",
46
+ service_owner_eoa_address="0x1111111111111111111111111111111111111111",
47
47
  staking_contract_address="0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB",
48
48
  )
49
49
  return OlasConfig(services={"gnosis:1": service})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iwa
3
- Version: 0.0.62
3
+ Version: 0.0.65
4
4
  Summary: A secure, modular, and plugin-based framework for crypto agents and ops
5
5
  Requires-Python: <4.0,>=3.12
6
6
  Description-Content-Type: text/markdown
@@ -43,7 +43,7 @@ iwa/core/services/plugin.py,sha256=GNNlbtELyHl7MNVChrypF76GYphxXduxDog4kx1MLi8,3
43
43
  iwa/core/services/safe.py,sha256=vqvpk7aIqHljaG1zYYpmKdW4mi5OVuoyXcpReISPYM0,15744
44
44
  iwa/core/services/safe_executor.py,sha256=TqpDgtvh8d5cedYAKBj7s1SW7EnomTT9MW_GnYWMxDE,17157
45
45
  iwa/core/services/transaction.py,sha256=FrGRWn1xo5rbGIr2ToZ2kPzapr3zmWW38oycyB87TK8,19971
46
- iwa/core/services/transfer/__init__.py,sha256=ZJfshFxJRsp8rkOqfVvd1cqEzIJ9tqBJh8pc0l90GLk,5576
46
+ iwa/core/services/transfer/__init__.py,sha256=7p22xtwrH0murXWTuTGNw0WRKBDqjJEnnVaUpWd8Vfo,5589
47
47
  iwa/core/services/transfer/base.py,sha256=sohz-Ss2i-pGYGl4x9bD93cnYKcSvsXaXyvyRawvgQs,9043
48
48
  iwa/core/services/transfer/erc20.py,sha256=e6RD1_QcI_-iJvP85kj7aw4p6NnCPjZcm-QSKi14RRA,10104
49
49
  iwa/core/services/transfer/multisend.py,sha256=MuOTjzUQoYg1eSixXKhJGBmB1c0ymLelvk4puHm_VGE,15194
@@ -70,7 +70,7 @@ iwa/plugins/olas/constants.py,sha256=BbEDho_TAh10cCGsrlk2vP1OVrS_ZWBE_cAEITd_658
70
70
  iwa/plugins/olas/events.py,sha256=HHjYu4pN3tuZATIh8vGWWzDb7z9wuqhsaTqI3_4H0-I,6086
71
71
  iwa/plugins/olas/importer.py,sha256=5xTtlQe5hO5bUCOg1sRuFkN2UcohYdJEQwfMm2JckyI,42088
72
72
  iwa/plugins/olas/mech_reference.py,sha256=CaSCpQnQL4F7wOG6Ox6Zdoy-uNEQ78YBwVLILQZKL8Q,5782
73
- iwa/plugins/olas/models.py,sha256=uXih8UcmBYj6PlxqP-cnyAiazJezjShjkCaN1Kqlb2I,4921
73
+ iwa/plugins/olas/models.py,sha256=VtDjSyc63Yxs3aManmALrcf7asehdQ5f-5Y6MtAdWIk,4056
74
74
  iwa/plugins/olas/plugin.py,sha256=kz21CxIGQw3Is6HC2dvKvFRIm9m1FRKHO0YgUuDEplQ,15650
75
75
  iwa/plugins/olas/contracts/activity_checker.py,sha256=OXh0SFPGfcpeD665ay-I19LqcIx38qEz8o62dw0A9zE,5361
76
76
  iwa/plugins/olas/contracts/base.py,sha256=y73aQbDq6l4zUpz_eQAg4MsLkTAEqjjupXlcvxjfgCI,240
@@ -93,8 +93,8 @@ iwa/plugins/olas/scripts/test_full_mech_flow.py,sha256=Fqoq5bn7Z_3YyRrnuqNAZy9cw
93
93
  iwa/plugins/olas/scripts/test_simple_lifecycle.py,sha256=8T50tOZx3afeECSfCNAb0rAHNtYOsBaeXlMwKXElCk8,2099
94
94
  iwa/plugins/olas/service_manager/__init__.py,sha256=GXiThMEY3nPgHUl1i-DLrF4h96z9jPxxI8Jepo2E1PM,1926
95
95
  iwa/plugins/olas/service_manager/base.py,sha256=EBPg0ymqgtAb7ZvVSfTt31QYgv_6gp4UAc6je00NLAg,5009
96
- iwa/plugins/olas/service_manager/drain.py,sha256=Hoa8rTIDwp9xGf_0O-7Nvn58LMZ_8PTOTr2ETUY5TjY,12920
97
- iwa/plugins/olas/service_manager/lifecycle.py,sha256=JCLGN7RjJbbPXXHOqvD64OKj2wH2NVh7o3mCBqJQEAQ,50570
96
+ iwa/plugins/olas/service_manager/drain.py,sha256=tJLqvMEPOymxukFuxt-AdgOB4bIIciKcXoxOPx9j-LM,13983
97
+ iwa/plugins/olas/service_manager/lifecycle.py,sha256=Jz2WTsBE_kGjFnsnpQlUBmMM2csOuqEfYdvj4cLrNuU,50586
98
98
  iwa/plugins/olas/service_manager/mech.py,sha256=NVzVbEmyOe3wK92VEzCCOSuy3HDkEP1MSoVt7Av8Psk,27949
99
99
  iwa/plugins/olas/service_manager/staking.py,sha256=kT9OOQ4fi3FrIJB2T2gsvmv7DBRD6pDxqcXXh2o6iwc,29600
100
100
  iwa/plugins/olas/tests/conftest.py,sha256=4vM7EI00SrTGyeP0hNzsGSQHEj2-iznVgzlNh2_OGfo,739
@@ -104,9 +104,9 @@ iwa/plugins/olas/tests/test_mech_contracts.py,sha256=wvxuigPafF-ySIHVBdWVei3AO41
104
104
  iwa/plugins/olas/tests/test_olas_archiving.py,sha256=rwyP-9eZ1cNvvV4h4bBOrs_8qV-du9yt-VNMuH_13nY,3443
105
105
  iwa/plugins/olas/tests/test_olas_contracts.py,sha256=B8X-5l1KfYMoZOiM94_rcNzbILLl78rqt_jhyxzAOqE,10835
106
106
  iwa/plugins/olas/tests/test_olas_integration.py,sha256=LGkdeso5lvi7_0GjlS9EFlSs6PEEn_b5aD2USmperDA,23086
107
- iwa/plugins/olas/tests/test_olas_models.py,sha256=5scX-wvRLGH3G44S2okq_tyQ9Rk7Pd0Ak1zNCZ2HtI4,4957
107
+ iwa/plugins/olas/tests/test_olas_models.py,sha256=LCtU01v2LhPgSjzMBGlhRQ9nBb7sgcd7n7F1z-T-IuA,4977
108
108
  iwa/plugins/olas/tests/test_olas_view.py,sha256=2SsQYayeV3rf_mAPVvt4vINcMysAXmICkkQe3MRn4K8,10662
109
- iwa/plugins/olas/tests/test_olas_view_actions.py,sha256=jAxr9bjFNAaxGf1btIrxdMaHgJ0PWX9aDwVU-oPGMpk,5109
109
+ iwa/plugins/olas/tests/test_olas_view_actions.py,sha256=67al8ffNWMETI-foq-FjsXqpjdEruuH1sRCsGo_x9GE,5113
110
110
  iwa/plugins/olas/tests/test_olas_view_modals.py,sha256=8j0PNFjKqFC5V1kBdVFWNLMvqGt49H6fLSYGxn02c8o,5562
111
111
  iwa/plugins/olas/tests/test_plugin.py,sha256=RVgU-Cq6t_3mOh90xFAGwlJOV7ZIgp0VNaK5ZAxisAQ,2565
112
112
  iwa/plugins/olas/tests/test_plugin_full.py,sha256=55EBa07JhJLVG3IMi6QKlR_ivWLYCdLQTySP66qbEXo,8584
@@ -115,9 +115,9 @@ iwa/plugins/olas/tests/test_service_manager.py,sha256=_mFRptssimITHhjvZA5jUPU2bI
115
115
  iwa/plugins/olas/tests/test_service_manager_errors.py,sha256=-qpLmU4Uiqqtre59L2wXpO4WPMs4ej_K_gAL3naEvRg,8554
116
116
  iwa/plugins/olas/tests/test_service_manager_flows.py,sha256=ZSmBJNa18d_MyAaLQRoPpfFYRwzmk9k-5AhSAGd7WeI,20737
117
117
  iwa/plugins/olas/tests/test_service_manager_mech.py,sha256=qG6qu5IPRNypXUsblU2OEkuiuwDJ0TH8RXZbibmTFcQ,4937
118
- iwa/plugins/olas/tests/test_service_manager_rewards.py,sha256=jVAe4HSAxDfnq8Ec-JMsvE2E0HYsydO78ITFHnSSka4,11993
118
+ iwa/plugins/olas/tests/test_service_manager_rewards.py,sha256=2YCrXBU5bEkPuhBoGBhjnO1nA2qwHxn5Ivrror18FHM,12248
119
119
  iwa/plugins/olas/tests/test_service_manager_validation.py,sha256=ajlfH5uc4mAHf8A7GLE5cW7X8utM2vUilM0JdGDdlVg,5382
120
- iwa/plugins/olas/tests/test_service_staking.py,sha256=ETNnWzV52FDhK0mrPb9xl9gSiYRH2EeDVxcaQIV0d5Q,15849
120
+ iwa/plugins/olas/tests/test_service_staking.py,sha256=78yyPoLo51N1aQyDxjzj7I0a263JHKHqekL-W3oQAsw,15914
121
121
  iwa/plugins/olas/tests/test_staking_integration.py,sha256=QCBQf6P2ZmmsEGt2k8W2r53lG2aVRuoMJE-aFxVDLss,9701
122
122
  iwa/plugins/olas/tests/test_staking_validation.py,sha256=uug64jFcXYJ3Nw_lNa3O4fnhNr5wAWHHIrchSbR2MVE,4020
123
123
  iwa/plugins/olas/tui/__init__.py,sha256=5ZRsbC7J3z1xfkZRiwr4bLEklf78rNVjdswe2p7SlS8,28
@@ -150,7 +150,7 @@ iwa/web/dependencies.py,sha256=0_dAJlRh6gKrUDRPKUe92eshFsg572yx_H0lQgSqGDA,2103
150
150
  iwa/web/models.py,sha256=MSD9WPy_Nz_amWgoo2KSDTn4ZLv_AV0o0amuNtSf-68,3035
151
151
  iwa/web/server.py,sha256=4ZLVFEKoGs_NoCcXMeyYzDNdxUXazjwHQaX7CR1pwHE,5239
152
152
  iwa/web/routers/accounts.py,sha256=VhCHrwzRWqZcSW-tTEqFWT5hFl-IYEWpqXeuN8xM3-4,3922
153
- iwa/web/routers/state.py,sha256=aEfeGFAOyaS6kWhXuWLrdvEbnQAeonKIWxJrQkqJ1GY,2198
153
+ iwa/web/routers/state.py,sha256=wsBAOIWZeMWjMwLiiWVhuEXHAceI0IIq6CPpmh7SbIc,2469
154
154
  iwa/web/routers/swap.py,sha256=8xycAytquR29ELxW3vx428W8s9bI_w_x2kpRhhJ0KXY,22630
155
155
  iwa/web/routers/transactions.py,sha256=bRjfD7zcuX3orVIHzOMVsIkEtcE_pM_KCom4cdAKV6Q,5602
156
156
  iwa/web/routers/olas/__init__.py,sha256=Jo6Dm1e8fHafCD800fbxsxeFz3tvuEEKXEf5-9tj5Qg,947
@@ -159,14 +159,14 @@ iwa/web/routers/olas/funding.py,sha256=f8fADNtbZEBFl-vuVKfas6os38Vot6K5tJBTenZmC
159
159
  iwa/web/routers/olas/general.py,sha256=dPsBQppTGoQY1RztliUhseOHOZGeeCR10lhThD9kyXo,803
160
160
  iwa/web/routers/olas/services.py,sha256=jDbxLUJBN48vs2-fXrIpxhPSM6quqYxggmMOkUVEIaI,18200
161
161
  iwa/web/routers/olas/staking.py,sha256=jktJ2C1Q9X4aC0tWJByN3sHpEXY0EIvr3rr4N0MtXXc,14081
162
- iwa/web/static/app.js,sha256=hBjUSivxf5Uyy2H6BR-rfdvF8e7qBoDPK23aY3dagNY,114418
163
- iwa/web/static/index.html,sha256=q7s7plnMbN1Nkzr5bRxZgvgOFerUChEGIZW7SpAVtPc,28514
162
+ iwa/web/static/app.js,sha256=VCm9zPJERb9pX6zbFQ_7D47UnztGdibrkZ1dmwhsvdc,114949
163
+ iwa/web/static/index.html,sha256=pPwUcpqzv51P8FSKd-ml5K_xgmVGjigh3sFOPKsQpO8,28514
164
164
  iwa/web/static/style.css,sha256=7i6T96pS7gXSLDZfyp_87gRlyB9rpsFWJEHJ-dRY1ug,24371
165
165
  iwa/web/tests/test_web_endpoints.py,sha256=vA25YghHNB23sbmhD4ciesn_f_okSq0tjlkrSiKZ0rs,24007
166
- iwa/web/tests/test_web_olas.py,sha256=0CVSsrncOeJ3x0ECV7mVLQV_CXZRrOqGiVjgLIi6hZ8,16308
166
+ iwa/web/tests/test_web_olas.py,sha256=GunKEAzcbzL7FoUGMtEl8wqiqwYwA5lB9sOhfCNj0TA,16312
167
167
  iwa/web/tests/test_web_swap.py,sha256=7A4gBJFL01kIXPtW1E1J17SCsVc_0DmUn-R8kKrnnVA,2974
168
168
  iwa/web/tests/test_web_swap_coverage.py,sha256=zGNrzlhZ_vWDCvWmLcoUwFgqxnrp_ACbo49AtWBS_Kw,5584
169
- iwa-0.0.62.dist-info/licenses/LICENSE,sha256=eIubm_IlBHPYRQlLNZKbBNKhJUUP3JH0A2miZUhAVfI,1078
169
+ iwa-0.0.65.dist-info/licenses/LICENSE,sha256=eIubm_IlBHPYRQlLNZKbBNKhJUUP3JH0A2miZUhAVfI,1078
170
170
  tests/legacy_cow.py,sha256=oOkZvIxL70ReEoD9oHQbOD5GpjIr6AGNHcOCgfPlerU,8389
171
171
  tests/legacy_safe.py,sha256=AssM2g13E74dNGODu_H0Q0y412lgqsrYnEzI97nm_Ts,2972
172
172
  tests/legacy_transaction_retry_logic.py,sha256=D9RqZ7DBu61Xr2djBAodU2p9UE939LL-DnQXswX5iQk,1497
@@ -178,11 +178,12 @@ tests/test_balance_service.py,sha256=wcuCOVszxPy8nPkldAVcEiygcOK3BuQt797fqAJvbp4
178
178
  tests/test_chain.py,sha256=VZoidSojWyt1y4mQdZdoZsjuuDZjLC6neTC-2SF_Q7I,13957
179
179
  tests/test_chain_interface.py,sha256=bgqGM8wJGZjc-BOX6i0K4sh06KCJl-6UAvrwl8x24lA,8324
180
180
  tests/test_chain_interface_coverage.py,sha256=fvrVvw8-DMwdsSFKQHUhpbfutrVRxnnTc-tjB7Bb-jo,3327
181
- tests/test_chainlist_enrichment.py,sha256=2iD5121SxSDpvQTkaoBXOW-cV-FD1NwkRvzlqRn2Ynk,12928
181
+ tests/test_chainlist_enrichment.py,sha256=hxfYjI54hT2pBXeacmQkLJGEPyuaAwDtNL5sEVZURp8,22065
182
182
  tests/test_cli.py,sha256=Pl4RC2xp1omiJUnL3Dza6pCmIoO29LJ0vGw33_ZpT5c,3980
183
183
  tests/test_contract.py,sha256=tApHAxsfKGawYJWA9PhTNrOZUE0VVAq79ruIe3KxeWY,14412
184
+ tests/test_contract_cache.py,sha256=TYIYPwIm_pVsdDjXJj_9-yDah_RFYB3PBn_fyE-a_YU,8454
184
185
  tests/test_db.py,sha256=dmbrupj0qlUeiiycZ2mzMFjf7HrDa6tcqMPY8zpiKIk,5710
185
- tests/test_drain_coverage.py,sha256=oFpY7tFPXWe9WLh3z2D4L2GxuAJO6_txLNxJmtgZT7M,7208
186
+ tests/test_drain_coverage.py,sha256=x-ANNt2YVJcuJApMe7VlzZE-1RRpSvGtDz5M_UXLc4I,18497
186
187
  tests/test_erc20.py,sha256=kNEw1afpm5EbXRNXkjpkBNZIy7Af1nqGlztKH5IWAwU,3074
187
188
  tests/test_gnosis_plugin.py,sha256=XMoHBCTrnVBq9bXYPzMUIrhr95caucMVRxooCjKrzjg,3454
188
189
  tests/test_keys.py,sha256=Qk4n3QDZ2HjXYRvehdrSlvDS_q3NLRLMnCq45Eo1Q9o,17551
@@ -210,7 +211,7 @@ tests/test_service_manager_integration.py,sha256=I_BLUzEKrVTyg_8jqsUK0oFD3aQVPCR
210
211
  tests/test_service_manager_structure.py,sha256=zK506ucCXCBHcjPYKrKEuK1bgq0xsbawyL8Y-wahXf8,868
211
212
  tests/test_service_transaction.py,sha256=IeqYhmRD-pIXffBJrBQwfPx-qnfNEJs0iPM3eCb8MLo,7054
212
213
  tests/test_staking_router.py,sha256=cnOtwWeQPu09kecVhlCf1WA4ONqs13OcQJhJCx2EOPY,3067
213
- tests/test_staking_simple.py,sha256=NHyZ1pcVQEJGFiGseC5m6Y9Y6FJGnRIFJUwhd1hAV9g,1138
214
+ tests/test_staking_simple.py,sha256=LN1ehVpNlT2oGGNhj0B1DAmazoL5xRmSCHB5AUL8900,19643
214
215
  tests/test_tables.py,sha256=1KQHgxuizoOrRxpubDdnzk9iaU5Lwyp3bcWP_hZD5uU,2686
215
216
  tests/test_transaction_service.py,sha256=q2IQ6cJ6sZtzc_pVCM_dv0vW7LW2sONNrK5Pvrm63rU,12816
216
217
  tests/test_transfer_multisend.py,sha256=PErjNqNwN66TMh4oVa307re64Ucccg1LkXqB0KlkmsI,6677
@@ -223,8 +224,8 @@ tests/test_utils.py,sha256=vkP49rYNI8BRzLpWR3WnKdDr8upeZjZcs7Rx0pjbQMo,1292
223
224
  tests/test_workers.py,sha256=MInwdkFY5LdmFB3o1odIaSD7AQZb3263hNafO1De5PE,2793
224
225
  tools/create_and_stake_service.py,sha256=1xwy_bJQI1j9yIQ968Oc9Db_F6mk1659LuuZntTASDE,3742
225
226
  tools/verify_drain.py,sha256=PkMjblyOOAuQge88FwfEzRtCYeEtJxXhPBmtQYCoQ-8,6743
226
- iwa-0.0.62.dist-info/METADATA,sha256=jnpILBgHX2FmSfLn2CXjYKhmkMp_Yr4rlOV5Ep_uknQ,7337
227
- iwa-0.0.62.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
228
- iwa-0.0.62.dist-info/entry_points.txt,sha256=nwB6kscrfA7M00pYmL2j-sBH6eF6h2ga9IK1BZxdiyQ,241
229
- iwa-0.0.62.dist-info/top_level.txt,sha256=kedS9cRUbm4JE2wYeabIXilhHjN8KCw0IGbqqqsw0Bs,16
230
- iwa-0.0.62.dist-info/RECORD,,
227
+ iwa-0.0.65.dist-info/METADATA,sha256=E6lkx395V7EMKgNrvdvYWu4vQRbwFDv8Udj14n2UaR4,7337
228
+ iwa-0.0.65.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
229
+ iwa-0.0.65.dist-info/entry_points.txt,sha256=nwB6kscrfA7M00pYmL2j-sBH6eF6h2ga9IK1BZxdiyQ,241
230
+ iwa-0.0.65.dist-info/top_level.txt,sha256=kedS9cRUbm4JE2wYeabIXilhHjN8KCw0IGbqqqsw0Bs,16
231
+ iwa-0.0.65.dist-info/RECORD,,