iwa 0.0.1a6__py3-none-any.whl → 0.0.10__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.
Files changed (50) hide show
  1. iwa/core/chain/interface.py +30 -23
  2. iwa/core/chain/models.py +21 -0
  3. iwa/core/contracts/contract.py +8 -2
  4. iwa/core/pricing.py +30 -21
  5. iwa/core/services/safe.py +13 -8
  6. iwa/core/services/transaction.py +15 -4
  7. iwa/core/utils.py +22 -0
  8. iwa/plugins/gnosis/safe.py +4 -3
  9. iwa/plugins/gnosis/tests/test_safe.py +9 -7
  10. iwa/plugins/olas/contracts/service.py +4 -4
  11. iwa/plugins/olas/contracts/staking.py +2 -3
  12. iwa/plugins/olas/plugin.py +14 -7
  13. iwa/plugins/olas/service_manager/lifecycle.py +109 -48
  14. iwa/plugins/olas/service_manager/mech.py +1 -1
  15. iwa/plugins/olas/service_manager/staking.py +92 -34
  16. iwa/plugins/olas/tests/test_plugin.py +6 -1
  17. iwa/plugins/olas/tests/test_plugin_full.py +12 -7
  18. iwa/plugins/olas/tests/test_service_manager_validation.py +16 -15
  19. iwa/tools/list_contracts.py +2 -2
  20. iwa/web/dependencies.py +1 -3
  21. iwa/web/routers/accounts.py +1 -2
  22. iwa/web/routers/olas/admin.py +1 -3
  23. iwa/web/routers/olas/funding.py +1 -3
  24. iwa/web/routers/olas/general.py +1 -3
  25. iwa/web/routers/olas/services.py +1 -2
  26. iwa/web/routers/olas/staking.py +19 -22
  27. iwa/web/routers/swap.py +1 -2
  28. iwa/web/routers/transactions.py +0 -2
  29. iwa/web/server.py +8 -6
  30. iwa/web/static/app.js +22 -0
  31. iwa/web/tests/test_web_endpoints.py +1 -1
  32. iwa/web/tests/test_web_olas.py +1 -1
  33. {iwa-0.0.1a6.dist-info → iwa-0.0.10.dist-info}/METADATA +1 -1
  34. {iwa-0.0.1a6.dist-info → iwa-0.0.10.dist-info}/RECORD +50 -49
  35. tests/test_chain_interface_coverage.py +3 -2
  36. tests/test_contract.py +165 -0
  37. tests/test_keys.py +2 -1
  38. tests/test_legacy_wallet.py +11 -0
  39. tests/test_pricing.py +32 -15
  40. tests/test_safe_coverage.py +3 -3
  41. tests/test_safe_service.py +3 -6
  42. tests/test_service_transaction.py +8 -3
  43. tests/test_staking_router.py +6 -3
  44. tests/test_transaction_service.py +4 -0
  45. tools/create_and_stake_service.py +103 -0
  46. tools/verify_drain.py +1 -4
  47. {iwa-0.0.1a6.dist-info → iwa-0.0.10.dist-info}/WHEEL +0 -0
  48. {iwa-0.0.1a6.dist-info → iwa-0.0.10.dist-info}/entry_points.txt +0 -0
  49. {iwa-0.0.1a6.dist-info → iwa-0.0.10.dist-info}/licenses/LICENSE +0 -0
  50. {iwa-0.0.1a6.dist-info → iwa-0.0.10.dist-info}/top_level.txt +0 -0
@@ -19,10 +19,13 @@ def test_check_availability_exception():
19
19
  """Test _check_availability handles contract call failures."""
20
20
  from iwa.web.routers.olas.staking import _check_availability
21
21
 
22
- mock_w3 = MagicMock()
23
- mock_w3.eth.contract.side_effect = Exception("Contract error")
22
+ mock_interface = MagicMock()
23
+ mock_interface.chain.name = "gnosis"
24
+
25
+ with patch("iwa.plugins.olas.contracts.staking.StakingContract") as mock_contract_cls:
26
+ mock_contract_cls.side_effect = Exception("Contract error")
27
+ result = _check_availability("Test", "0xAddr", mock_interface)
24
28
 
25
- result = _check_availability("Test", "0xAddr", mock_w3, [])
26
29
  assert result["name"] == "Test"
27
30
  assert result["usage"] is None
28
31
 
@@ -55,6 +55,10 @@ def mock_chain_interfaces():
55
55
  gnosis_interface.web3.eth.wait_for_transaction_receipt.return_value = mock_receipt
56
56
 
57
57
  instance.get.return_value = gnosis_interface
58
+
59
+ # Mock with_retry to execute the operation
60
+ gnosis_interface.with_retry.side_effect = lambda op, **kwargs: op()
61
+
58
62
  yield instance
59
63
 
60
64
 
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env python3
2
+ """Create a service with correct bond and stake it in Expert 7 MM contract.
3
+
4
+ This script demonstrates the minimum steps to:
5
+ 1. Get the required bond amount from the staking contract
6
+ 2. Create a service with that bond (NOT 1 wei)
7
+ 3. Spin up the service (activate → register → deploy)
8
+ 4. Stake the service in the staking contract
9
+
10
+ IMPORTANT: The service MUST be created with the correct bond amount
11
+ specified by the staking contract. Creating with bond=1 wei will
12
+ cause staking to fail because the on-chain bond won't match requirements.
13
+ """
14
+
15
+ import sys
16
+ from pathlib import Path
17
+
18
+ # Add src to path
19
+ sys.path.insert(0, str(Path(__file__).parent.parent))
20
+
21
+ from iwa.core.wallet import Wallet
22
+ from iwa.plugins.olas.constants import OLAS_TRADER_STAKING_CONTRACTS
23
+ from iwa.plugins.olas.contracts.staking import StakingContract
24
+ from iwa.plugins.olas.service_manager import ServiceManager
25
+
26
+
27
+ def main():
28
+ """Create and stake a service in Expert 7 MM contract."""
29
+ print("=" * 60)
30
+ print(" Create & Stake Service - Expert 7 MM (10k OLAS)")
31
+ print("=" * 60)
32
+
33
+ # 1. Initialize wallet
34
+ print("\n[1] Initializing Wallet...")
35
+ wallet = Wallet()
36
+ master_address = wallet.master_account.address if wallet.master_account else "N/A"
37
+ print(f" OK: Master account: {master_address}")
38
+
39
+ # 2. Get the staking contract
40
+ print("\n[2] Loading staking contract...")
41
+ staking_address = OLAS_TRADER_STAKING_CONTRACTS["gnosis"]["Expert 7 MM (10k OLAS)"]
42
+ staking_contract = StakingContract(staking_address, chain_name="gnosis")
43
+ print(f" OK: Staking contract: {staking_address}")
44
+
45
+ # 3. Get the required bond amount from the staking contract
46
+ print("\n[3] Getting staking requirements...")
47
+ requirements = staking_contract.get_requirements()
48
+ required_bond = requirements["required_agent_bond"]
49
+ min_deposit = requirements["min_staking_deposit"]
50
+ staking_token = str(requirements["staking_token"])
51
+ print(f" - Required agent bond: {required_bond} wei")
52
+ print(f" - Min staking deposit: {min_deposit} wei")
53
+ print(f" - Staking token: {staking_token}")
54
+
55
+ # 4. Create service with the correct bond amount
56
+ print("\n[4] Creating Service with correct bond...")
57
+ manager = ServiceManager(wallet)
58
+ service_id = manager.create(
59
+ chain_name="gnosis",
60
+ service_name="staked_service_7mm",
61
+ token_address_or_tag=staking_token, # Use OLAS token
62
+ bond_amount_wei=required_bond, # THIS IS THE KEY: use required bond, not 1 wei
63
+ )
64
+
65
+ if not service_id:
66
+ print(" FAIL: Failed to create service")
67
+ return False
68
+
69
+ print(f" OK: Service created with ID: {service_id}")
70
+
71
+ # 5. Spin up the service (activate -> register -> deploy -> stake)
72
+ print("\n[5] Spinning up and staking Service...")
73
+ success = manager.spin_up(
74
+ bond_amount_wei=required_bond,
75
+ staking_contract=staking_contract, # spin_up handles staking automatically
76
+ )
77
+ if not success:
78
+ print(" FAIL: Failed to spin up/stake service")
79
+ return False
80
+
81
+ print(" OK: Service deployed and staked!")
82
+ print(f" - Agent: {manager.service.agent_address}")
83
+ print(f" - Multisig: {manager.service.multisig_address}")
84
+
85
+ print("\n" + "=" * 60)
86
+ print(" SUCCESS: Service created and staked!")
87
+ print("=" * 60)
88
+ print(f"\nService ID: {service_id}")
89
+ print("Staking Contract: Expert 7 MM (10k OLAS)")
90
+ print(f"Contract Address: {staking_address}")
91
+ return True
92
+
93
+
94
+ if __name__ == "__main__":
95
+ try:
96
+ success = main()
97
+ sys.exit(0 if success else 1)
98
+ except Exception as e:
99
+ print(f"\n❌ Error: {e}")
100
+ import traceback
101
+
102
+ traceback.print_exc()
103
+ sys.exit(1)
tools/verify_drain.py CHANGED
@@ -1,14 +1,11 @@
1
1
  """Verification script for draining services."""
2
2
 
3
- import logging
4
3
  import subprocess # nosec: B404
5
4
  import sys
6
5
  import time
7
6
  from typing import List
8
7
 
9
- # Configure logging
10
- logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
11
- logger = logging.getLogger(__name__)
8
+ from loguru import logger
12
9
 
13
10
 
14
11
  def run_command(command: List[str]): # noqa: D103
File without changes